Fork me on GitHub

root/drivers/block/ide.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ide_identify
  2. get_device_size
  3. get_udma
  4. get_piomode
  5. ide_results
  6. ide_get_status
  7. irq_ide0
  8. irq_ide1
  9. ide0_timer
  10. ide1_timer
  11. ide_error
  12. ide_delay
  13. ide_wait400ns
  14. ide_drvsel
  15. ide_softreset
  16. get_ide_controller
  17. get_ide_drive
  18. ide_open
  19. ide_close
  20. ide_read
  21. ide_write
  22. ide_ioctl
  23. ide_init

   1 /*
   2  * fiwix/drivers/block/ide.c
   3  *
   4  * Copyright 2018-2022, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/asm.h>
   9 #include <fiwix/ide.h>
  10 #include <fiwix/ide_hd.h>
  11 #include <fiwix/ide_cd.h>
  12 #include <fiwix/devices.h>
  13 #include <fiwix/sleep.h>
  14 #include <fiwix/timer.h>
  15 #include <fiwix/sched.h>
  16 #include <fiwix/cpu.h>
  17 #include <fiwix/pic.h>
  18 #include <fiwix/irq.h>
  19 #include <fiwix/fs.h>
  20 #include <fiwix/mm.h>
  21 #include <fiwix/errno.h>
  22 #include <fiwix/stdio.h>
  23 #include <fiwix/string.h>
  24 
  25 int ide0_need_reset = 0;
  26 int ide0_wait_interrupt = 0;
  27 int ide0_timeout = 0;
  28 int ide1_need_reset = 0;
  29 int ide1_wait_interrupt = 0;
  30 int ide1_timeout = 0;
  31 
  32 struct ide ide_table[NR_IDE_CTRLS] = {
  33         { IDE_PRIMARY, IDE0_BASE, IDE0_CTRL, IDE0_IRQ, { 0, 0 },
  34                 {
  35                         { IDE_MASTER, "hda", IDE0_MAJOR, 0, IDE_MASTER_MSF, 0, 0, 0, 0, 0, { 0 }, {{ 0 }} },
  36                         { IDE_SLAVE, "hdb", IDE0_MAJOR, 0, IDE_SLAVE_MSF, 0, 0, 0, 0, 0, { 0 }, {{ 0 }} }
  37                 }
  38         },
  39         { IDE_SECONDARY, IDE1_BASE, IDE1_CTRL, IDE1_IRQ, { 0, 0 },
  40                 {
  41                         { IDE_MASTER, "hdc", IDE1_MAJOR, 0, IDE_MASTER_MSF, 0, 0, 0, 0, 0, { 0 }, {{ 0 }} },
  42                         { IDE_SLAVE, "hdd", IDE1_MAJOR, 0, IDE_SLAVE_MSF, 0, 0, 0, 0, 0, { 0 }, {{ 0 }} }
  43                 }
  44         }
  45 };
  46 
  47 static char *ide_ctrl_name[] = { "primary", "secondary" };
  48 static char *ide_drv_name[] = { "master", "slave" };
  49 
  50 static unsigned int ide0_sizes[256];
  51 static unsigned int ide1_sizes[256];
  52 
  53 static struct fs_operations ide_driver_fsop = {
  54         0,
  55         0,
  56 
  57         ide_open,
  58         ide_close,
  59         NULL,                   /* read */
  60         NULL,                   /* write */
  61         ide_ioctl,
  62         NULL,                   /* lseek */
  63         NULL,                   /* readdir */
  64         NULL,                   /* mmap */
  65         NULL,                   /* select */
  66 
  67         NULL,                   /* readlink */
  68         NULL,                   /* followlink */
  69         NULL,                   /* bmap */
  70         NULL,                   /* lockup */
  71         NULL,                   /* rmdir */
  72         NULL,                   /* link */
  73         NULL,                   /* unlink */
  74         NULL,                   /* symlink */
  75         NULL,                   /* mkdir */
  76         NULL,                   /* mknod */
  77         NULL,                   /* truncate */
  78         NULL,                   /* create */
  79         NULL,                   /* rename */
  80 
  81         ide_read,
  82         ide_write,
  83 
  84         NULL,                   /* read_inode */
  85         NULL,                   /* write_inode */
  86         NULL,                   /* ialloc */
  87         NULL,                   /* ifree */
  88         NULL,                   /* statfs */
  89         NULL,                   /* read_superblock */
  90         NULL,                   /* remount_fs */
  91         NULL,                   /* write_superblock */
  92         NULL                    /* release_superblock */
  93 };
  94 
  95 static struct device ide0_device = {
  96         "ide0",
  97         IDE0_MAJOR,
  98         { 0, 0, 0, 0, 0, 0, 0, 0 },
  99         0,
 100         &ide0_sizes,
 101         &ide_driver_fsop,
 102         NULL
 103 };
 104 
 105 static struct device ide1_device = {
 106         "ide1",
 107         IDE1_MAJOR,
 108         { 0, 0, 0, 0, 0, 0, 0, 0 },
 109         0,
 110         &ide1_sizes,
 111         &ide_driver_fsop,
 112         NULL
 113 };
 114 
 115 static struct interrupt irq_config_ide0 = { 0, "ide0", &irq_ide0, NULL };
 116 static struct interrupt irq_config_ide1 = { 0, "ide1", &irq_ide1, NULL };
 117 
 118 static int ide_identify(struct ide *ide, int drive)
 119 {
 120         short int status, *buffer;
 121         struct callout_req creq;
 122 
 123         if((status = ide_drvsel(ide, drive, IDE_CHS_MODE, 0))) {
 124                 /* some controllers return 0xFF to indicate a non-drive condition */
 125                 if(status == 0xFF) {
 126                         return status;
 127                 }
 128                 printk("WARNING: %s(): error on device '%s'.\n", __FUNCTION__, ide->drive[drive].dev_name);
 129                 ide_error(ide, status);
 130                 return status;
 131         }
 132 
 133         if(ide->channel == IDE_PRIMARY) {
 134                 ide0_wait_interrupt = ide->base;
 135                 creq.fn = ide0_timer;
 136                 creq.arg = 0;
 137                 add_callout(&creq, WAIT_FOR_IDE);
 138                 outport_b(ide->base + IDE_COMMAND, (ide->drive[drive].flags & DEVICE_IS_ATAPI) ? ATA_IDENTIFY_PACKET : ATA_IDENTIFY);
 139                 if(ide0_wait_interrupt) {
 140                         sleep(&irq_ide0, PROC_UNINTERRUPTIBLE);
 141                 }
 142                 if(ide0_timeout) {
 143                         status = inport_b(ide->base + IDE_STATUS);
 144                         if((status & (IDE_STAT_RDY | IDE_STAT_DRQ)) != (IDE_STAT_RDY | IDE_STAT_DRQ)) {
 145                                 return 1;
 146                         }
 147                 }
 148                 del_callout(&creq);
 149         }
 150         if(ide->channel == IDE_SECONDARY) {
 151                 ide1_wait_interrupt = ide->base;
 152                 creq.fn = ide1_timer;
 153                 creq.arg = 0;
 154                 add_callout(&creq, WAIT_FOR_IDE);
 155                 outport_b(ide->base + IDE_COMMAND, (ide->drive[drive].flags & DEVICE_IS_ATAPI) ? ATA_IDENTIFY_PACKET : ATA_IDENTIFY);
 156                 if(ide1_wait_interrupt) {
 157                         sleep(&irq_ide1, PROC_UNINTERRUPTIBLE);
 158                 }
 159                 if(ide1_timeout) {
 160                         status = inport_b(ide->base + IDE_STATUS);
 161                         if((status & (IDE_STAT_RDY | IDE_STAT_DRQ)) != (IDE_STAT_RDY | IDE_STAT_DRQ)) {
 162                                 return 1;
 163                         }
 164                 }
 165                 del_callout(&creq);
 166         }
 167 
 168         status = inport_b(ide->base + IDE_STATUS);
 169         if((status & (IDE_STAT_RDY | IDE_STAT_DRQ)) != (IDE_STAT_RDY | IDE_STAT_DRQ)) {
 170                 return 1;
 171         }
 172 
 173         if(!(buffer = (void *)kmalloc())) {
 174                 return 1;
 175         }
 176 
 177         inport_sw(ide->base + IDE_DATA, (void *)buffer, IDE_HD_SECTSIZE / sizeof(short int));
 178         memcpy_b(&ide->drive[drive].ident, (void *)buffer, sizeof(struct ide_drv_ident));
 179         kfree((unsigned int)buffer);
 180 
 181         /* some basic checks to make sure that data received makes sense */
 182         if(ide->drive[drive].ident.logic_cyls > 0xF000 &&
 183            ide->drive[drive].ident.logic_heads > 0xF000 &&
 184            ide->drive[drive].ident.logic_spt > 0xF000 &&
 185            ide->drive[drive].ident.buffer_cache > 0xF000
 186         ) {
 187                 memset_b(&ide->drive[drive].ident, 0, sizeof(struct ide_drv_ident));
 188                 return 1;
 189         }
 190 
 191         if(ide->drive[drive].ident.gen_config == IDE_SUPPORTS_CFA) {
 192                 ide->drive[drive].flags |= DEVICE_IS_CFA;
 193         }
 194 
 195         if(ide->drive[drive].flags & DEVICE_IS_ATAPI) {
 196                 if(((ide->drive[drive].ident.gen_config >> 8) & 0x1F) == ATAPI_IS_CDROM) {
 197                         ide->drive[drive].flags |= DEVICE_IS_CDROM;
 198                 }
 199                 if(ide->drive[drive].ident.gen_config & 0x3) {
 200                         printk("WARNING: %s(): packet size must be 16 bytes!\n");
 201                 }
 202         }
 203 
 204         /* only bits 0-7 are relevant */
 205         ide->drive[drive].ident.rw_multiple &= 0xFF;
 206         return 0;
 207 }
 208 
 209 static void get_device_size(struct ide_drv *drive)
 210 {
 211         if(drive->ident.capabilities & IDE_HAS_LBA) {
 212                 drive->lba_cyls = drive->ident.logic_cyls;
 213                 drive->lba_heads = drive->ident.logic_heads;
 214                 drive->lba_factor = 0;
 215 
 216                 while(drive->lba_cyls > 1023) {
 217                         if(drive->lba_heads < 255) {
 218                                 drive->lba_cyls >>= 1;
 219                                 drive->lba_heads <<= 1;
 220                         } else {
 221                                 break;
 222                         }
 223                         drive->lba_factor++;
 224                 }
 225                 drive->nr_sects = drive->ident.tot_sectors | (drive->ident.tot_sectors2 << 16);
 226         }
 227 
 228         /* some old disk drives (ATA or ATA2) don't specify total sectors */
 229         if(!(drive->ident.capabilities & IDE_HAS_LBA)) {
 230                 if(drive->nr_sects == 0) {
 231                         drive->nr_sects = drive->ident.logic_cyls * drive->ident.logic_heads * drive->ident.logic_spt;
 232                 }
 233         }
 234 
 235 }
 236 
 237 static int get_udma(struct ide *ide, int drive)
 238 {
 239         int udma;
 240 
 241         if(ide->drive[drive].ident.fields_validity & IDE_HAS_UDMA) {
 242                 if((ide->drive[drive].ident.ultradma >> 13) & 1) {
 243                         udma = 5;
 244                 } else if((ide->drive[drive].ident.ultradma >> 12) & 1) {
 245                         udma = 4;
 246                 } else if((ide->drive[drive].ident.ultradma >> 11) & 1) {
 247                         udma = 3;
 248                 } else if((ide->drive[drive].ident.ultradma >> 10) & 1) {
 249                         udma = 2;
 250                 } else if((ide->drive[drive].ident.ultradma >> 9) & 1) {
 251                         udma = 1;
 252                 } else {
 253                         udma = 0;
 254                 }
 255         } else {
 256                 udma = -1;
 257         }
 258         return udma;
 259 }
 260 
 261 static int get_piomode(struct ide *ide, int drive)
 262 {
 263         int piomode;
 264 
 265         piomode = 0;
 266 
 267         if(ide->drive[drive].ident.fields_validity & IDE_HAS_ADVANCED_PIO) {
 268                 if(ide->drive[drive].ident.adv_pio_modes & 1) {
 269                         piomode = 3;
 270                 }
 271                 if(ide->drive[drive].ident.adv_pio_modes & 2) {
 272                         piomode = 4;
 273                 }
 274         }
 275 
 276         return piomode;
 277 }
 278 
 279 static void ide_results(struct ide *ide, int drive)
 280 {
 281         unsigned int cyl, hds, sect;
 282         __loff_t size;
 283         int ksize;
 284         int udma, piomode;
 285         int udma_speed[] = { 16, 25, 33, 44, 66, 100 };
 286 
 287         cyl = ide->drive[drive].ident.logic_cyls;
 288         hds = ide->drive[drive].ident.logic_heads;
 289         sect = ide->drive[drive].ident.logic_spt;
 290 
 291         if(ide->drive[drive].ident.fields_validity & IDE_HAS_CURR_VALUES) {
 292                 cyl = ide->drive[drive].ident.cur_log_cyls;
 293                 hds = ide->drive[drive].ident.cur_log_heads;
 294                 sect = ide->drive[drive].ident.cur_log_spt;
 295         }
 296 
 297         udma = get_udma(ide, drive);
 298         piomode = get_piomode(ide, drive);
 299 
 300         /*
 301          * After knowing if the device is UDMA capable we could choose between
 302          * the PIO transfer mode or the UDMA transfer mode.
 303          * FIXME: Currently only PIO mode is supported.
 304          */
 305 
 306         size = (__loff_t)ide->drive[drive].nr_sects * BPS;
 307         size = size / 1024;
 308         if(size < 1024) {
 309                 /* the size is less than 1MB (will be reported in KB) */
 310                 ksize = size;
 311                 size = 0;
 312         } else {
 313                 size = size / 1024;
 314                 ksize = 0;
 315         }
 316 
 317         printk("%s       0x%04x-0x%04x    %d\t", ide->drive[drive].dev_name, ide->base, ide->base + IDE_BASE_LEN, ide->irq);
 318         swap_asc_word(ide->drive[drive].ident.model_number, 40);
 319         printk("%s %s ", ide_ctrl_name[ide->channel], ide_drv_name[ide->drive[drive].drive]);
 320 
 321         if(!(ide->drive[drive].flags & DEVICE_IS_ATAPI)) {
 322                 printk("ATA");
 323         } else {
 324                 printk("ATAPI");
 325         }
 326 
 327         if(ide->drive[drive].flags & DEVICE_IS_CFA) {
 328                 printk(" CFA");
 329         }
 330 
 331         if(ide->drive[drive].flags & DEVICE_IS_DISK) {
 332                 if(ksize) {
 333                         printk(" DISK drive %dKB\n", ksize);
 334                 } else {
 335                         printk(" DISK drive %dMB\n", (unsigned int)size);
 336                 }
 337                 printk("                                model=%s\n", ide->drive[drive].ident.model_number);
 338                 if(ide->drive[drive].nr_sects < IDE_MIN_LBA) {
 339                         printk("\t\t\t\tCHS=%d/%d/%d", cyl, hds, sect);
 340                 } else {
 341                         ide->drive[drive].flags |= DEVICE_REQUIRES_LBA;
 342                         printk("\t\t\t\tsectors=%d", ide->drive[drive].nr_sects);
 343                 }
 344                 printk(" cache=%dKB", ide->drive[drive].ident.buffer_cache >> 1);
 345         }
 346 
 347         if(ide->drive[drive].flags & DEVICE_IS_CDROM) {
 348                 printk(" CDROM drive\n");
 349                 printk("\t\t\t\tmodel=%s\n", ide->drive[drive].ident.model_number);
 350                 printk("\t\t\t\tcache=%dKB", ide->drive[drive].ident.buffer_cache >> 1);
 351         }
 352 
 353         /*
 354         if(udma >= 0) {
 355                 printk(" UDMA%d(%d)", udma, udma_speed[udma]);
 356         }
 357         */
 358         printk(" PIO mode=%d", piomode);
 359 
 360         if(ide->drive[drive].ident.capabilities & IDE_HAS_LBA) {
 361                 ide->drive[drive].flags |= DEVICE_REQUIRES_LBA;
 362                 printk(" LBA");
 363         }
 364 
 365         printk("\n");
 366 
 367         if(ide->drive[drive].ident.rw_multiple > 1) {
 368                 /*
 369                  * Some very old controllers report a value of 16 here but they
 370                  * don't support read or write multiple in PIO mode. So far,
 371                  * I can detect these old controlers because they report a zero
 372                  * in the Advanced PIO Data Transfer Supported Field (word 64).
 373                  */
 374                 if(piomode > 0) {
 375                         ide->drive[drive].flags |= DEVICE_HAS_RW_MULTIPLE;
 376                 }
 377         }
 378 
 379         /*
 380         printk("\n");
 381         printk("%s -> %s\n", ide->drive[drive].dev_name, ide->drive[drive].flags & DEVICE_IS_ATAPI ? "ATAPI" : "ATA");
 382         printk("general conf  = %d (%b) (0x%x)\n", ide->drive[drive].ident.gen_config, ide->drive[drive].ident.gen_config, ide->drive[drive].ident.gen_config);
 383         printk("logic_cyls    = %d (%b)\n", ide->drive[drive].ident.logic_cyls, ide->drive[drive].ident.logic_cyls);
 384         printk("reserved2     = %d (%b)\n", ide->drive[drive].ident.reserved2, ide->drive[drive].ident.reserved2);
 385         printk("logic_heads   = %d (%b)\n", ide->drive[drive].ident.logic_heads, ide->drive[drive].ident.logic_heads);
 386         printk("retired4      = %d (%b)\n", ide->drive[drive].ident.retired4, ide->drive[drive].ident.retired4);
 387         printk("retired5      = %d (%b)\n", ide->drive[drive].ident.retired5, ide->drive[drive].ident.retired5);
 388         printk("logic_spt     = %d (%b)\n", ide->drive[drive].ident.logic_spt, ide->drive[drive].ident.logic_spt);
 389         printk("retired7      = %d (%b)\n", ide->drive[drive].ident.retired7, ide->drive[drive].ident.retired7);
 390         printk("retired8      = %d (%b)\n", ide->drive[drive].ident.retired8, ide->drive[drive].ident.retired8);
 391         printk("retired9      = %d (%b)\n", ide->drive[drive].ident.retired9, ide->drive[drive].ident.retired9);
 392         printk("serial number = '%s'\n", ide->drive[drive].ident.serial_number);
 393         printk("vendor spec20 = %d (%b)\n", ide->drive[drive].ident.vendor_spec20, ide->drive[drive].ident.vendor_spec20);
 394         printk("buffer cache  = %d (%b)\n", ide->drive[drive].ident.buffer_cache, ide->drive[drive].ident.buffer_cache);
 395         printk("vendor spec22 = %d (%b)\n", ide->drive[drive].ident.vendor_spec22, ide->drive[drive].ident.vendor_spec22);
 396         printk("firmware rev  = '%s'\n", ide->drive[drive].ident.firmware_rev);
 397         printk("model number  = '%s'\n", ide->drive[drive].ident.model_number);
 398         printk("rw multiple   = %d (%b)\n", ide->drive[drive].ident.rw_multiple, ide->drive[drive].ident.rw_multiple);
 399         printk("reserved48    = %d (%b)\n", ide->drive[drive].ident.reserved48, ide->drive[drive].ident.reserved48);
 400         printk("capabilities  = %d (%b)\n", ide->drive[drive].ident.capabilities, ide->drive[drive].ident.capabilities);
 401         printk("reserved50    = %d (%b)\n", ide->drive[drive].ident.reserved50, ide->drive[drive].ident.reserved50);
 402         printk("pio mode      = %d (%b)\n", ide->drive[drive].ident.pio_mode, ide->drive[drive].ident.pio_mode);
 403         printk("dma mode      = %d (%b)\n", ide->drive[drive].ident.dma_mode, ide->drive[drive].ident.dma_mode);
 404         printk("fields validi = %d (%b)\n", ide->drive[drive].ident.fields_validity, ide->drive[drive].ident.fields_validity);
 405         printk("cur log cyls  = %d (%b)\n", ide->drive[drive].ident.cur_log_cyls, ide->drive[drive].ident.cur_log_cyls);
 406         printk("cur log heads = %d (%b)\n", ide->drive[drive].ident.cur_log_heads, ide->drive[drive].ident.cur_log_heads);
 407         printk("cur log spt   = %d (%b)\n", ide->drive[drive].ident.cur_log_spt, ide->drive[drive].ident.cur_log_spt);
 408         printk("cur capacity  = %d (%b)\n", ide->drive[drive].ident.cur_capacity | (ide->drive[drive].ident.cur_capacity2 << 16), ide->drive[drive].ident.cur_capacity | (ide->drive[drive].ident.cur_capacity2 << 16));
 409         printk("mult sect set = %d (%b)\n", ide->drive[drive].ident.mult_sect_set, ide->drive[drive].ident.mult_sect_set);
 410         printk("tot sectors   = %d (%b)\n", ide->drive[drive].ident.tot_sectors | (ide->drive[drive].ident.tot_sectors2 << 16), ide->drive[drive].ident.tot_sectors | (ide->drive[drive].ident.tot_sectors2 << 16));
 411         printk("singleword dma= %d (%b)\n", ide->drive[drive].ident.singleword_dma, ide->drive[drive].ident.singleword_dma);
 412         printk("multiword dma = %d (%b)\n", ide->drive[drive].ident.multiword_dma, ide->drive[drive].ident.multiword_dma);
 413         printk("adv pio modes = %d (%b)\n", ide->drive[drive].ident.adv_pio_modes, ide->drive[drive].ident.adv_pio_modes);
 414         printk("min multiword = %d (%b)\n", ide->drive[drive].ident.min_multiword, ide->drive[drive].ident.min_multiword);
 415         printk("rec multiword = %d (%b)\n", ide->drive[drive].ident.rec_multiword, ide->drive[drive].ident.rec_multiword);
 416         printk("min pio wo fc = %d (%b)\n", ide->drive[drive].ident.min_pio_wo_fc, ide->drive[drive].ident.min_pio_wo_fc);
 417         printk("min pio w fc  = %d (%b)\n", ide->drive[drive].ident.min_pio_w_fc, ide->drive[drive].ident.min_pio_w_fc);
 418         printk("reserved69    = %d (%b)\n", ide->drive[drive].ident.reserved69, ide->drive[drive].ident.reserved69);
 419         printk("reserved70    = %d (%b)\n", ide->drive[drive].ident.reserved70, ide->drive[drive].ident.reserved70);
 420         printk("reserved71    = %d (%b)\n", ide->drive[drive].ident.reserved71, ide->drive[drive].ident.reserved71);
 421         printk("reserved72    = %d (%b)\n", ide->drive[drive].ident.reserved72, ide->drive[drive].ident.reserved72);
 422         printk("reserved73    = %d (%b)\n", ide->drive[drive].ident.reserved73, ide->drive[drive].ident.reserved73);
 423         printk("reserved74    = %d (%b)\n", ide->drive[drive].ident.reserved74, ide->drive[drive].ident.reserved74);
 424         printk("queue depth   = %d (%b)\n", ide->drive[drive].ident.queue_depth, ide->drive[drive].ident.queue_depth);
 425         printk("reserved76    = %d (%b)\n", ide->drive[drive].ident.reserved76, ide->drive[drive].ident.reserved76);
 426         printk("reserved77    = %d (%b)\n", ide->drive[drive].ident.reserved77, ide->drive[drive].ident.reserved77);
 427         printk("reserved78    = %d (%b)\n", ide->drive[drive].ident.reserved78, ide->drive[drive].ident.reserved78);
 428         printk("reserved79    = %d (%b)\n", ide->drive[drive].ident.reserved79, ide->drive[drive].ident.reserved79);
 429         printk("major version = %d (%b)\n", ide->drive[drive].ident.majorver, ide->drive[drive].ident.majorver);
 430         printk("minor version = %d (%b)\n", ide->drive[drive].ident.minorver, ide->drive[drive].ident.minorver);
 431         printk("cmdset1       = %d (%b)\n", ide->drive[drive].ident.cmdset1, ide->drive[drive].ident.cmdset1);
 432         printk("cmdset2       = %d (%b)\n", ide->drive[drive].ident.cmdset2, ide->drive[drive].ident.cmdset2);
 433         printk("cmdsf ext     = %d (%b)\n", ide->drive[drive].ident.cmdsf_ext, ide->drive[drive].ident.cmdsf_ext);
 434         printk("cmdsf enable1 = %d (%b)\n", ide->drive[drive].ident.cmdsf_enable1, ide->drive[drive].ident.cmdsf_enable1);
 435         printk("cmdsf enable2 = %d (%b)\n", ide->drive[drive].ident.cmdsf_enable2, ide->drive[drive].ident.cmdsf_enable2);
 436         printk("cmdsf default = %d (%b)\n", ide->drive[drive].ident.cmdsf_default, ide->drive[drive].ident.cmdsf_default);
 437         printk("ultra dma     = %d (%b)\n", ide->drive[drive].ident.ultradma, ide->drive[drive].ident.ultradma);
 438         printk("reserved89    = %d (%b)\n", ide->drive[drive].ident.reserved89, ide->drive[drive].ident.reserved89);
 439         printk("reserved90    = %d (%b)\n", ide->drive[drive].ident.reserved90, ide->drive[drive].ident.reserved90);
 440         printk("current apm   = %d (%b)\n", ide->drive[drive].ident.curapm, ide->drive[drive].ident.curapm);
 441         */
 442 }
 443 
 444 static int ide_get_status(struct ide *ide)
 445 {
 446         int n, retries, status;
 447 
 448         status = 0;
 449         SET_IDE_RDY_RETR(retries);
 450 
 451         for(n = 0; n < retries; n++) {
 452                 status = inport_b(ide->ctrl + IDE_ALT_STATUS);
 453                 if(!(status & IDE_STAT_BSY)) {
 454                         return 0;
 455                 }
 456                 ide_delay();
 457         }
 458 
 459         inport_b(ide->base + IDE_STATUS);       /* clear any pending interrupt */
 460         return status;
 461 }
 462 
 463 void irq_ide0(int num, struct sigcontext *sc)
 464 {
 465         if(!ide0_wait_interrupt) {
 466                 printk("WARNING: %s(): unexpected interrupt!\n", __FUNCTION__);
 467                 ide0_need_reset = 1;
 468         } else {
 469                 ide0_timeout = ide0_wait_interrupt = 0;
 470                 wakeup(&irq_ide0);
 471         }
 472 }
 473 
 474 void irq_ide1(int num, struct sigcontext *sc)
 475 {
 476         if(!ide1_wait_interrupt) {
 477                 printk("WARNING: %s(): unexpected interrupt!\n", __FUNCTION__);
 478                 ide1_need_reset = 1;
 479         } else {
 480                 ide1_timeout = ide1_wait_interrupt = 0;
 481                 wakeup(&irq_ide1);
 482         }
 483 }
 484 
 485 void ide0_timer(unsigned int arg)
 486 {
 487         ide0_timeout = 1;
 488         ide0_wait_interrupt = 0;
 489         wakeup(&irq_ide0);
 490 }
 491 
 492 void ide1_timer(unsigned int arg)
 493 {
 494         ide1_timeout = 1;
 495         ide1_wait_interrupt = 0;
 496         wakeup(&irq_ide1);
 497 }
 498 
 499 void ide_error(struct ide *ide, int status)
 500 {
 501         int error;
 502 
 503         if(status & IDE_STAT_ERR) {
 504                 error = inport_b(ide->base + IDE_ERROR);
 505                 if(error) {
 506                         printk("error=0x%x [", error);
 507                         if(error & IDE_ERR_AMNF) {
 508                                 printk("address mark not found, ");
 509                         }
 510                         if(error & IDE_ERR_TK0NF) {
 511                                 printk("track 0 not found (no media) or media error, ");
 512                         }
 513                         if(error & IDE_ERR_ABRT) {
 514                                 printk("command aborted, ");
 515                         }
 516                         if(error & IDE_ERR_MCR) {
 517                                 printk("media change requested, ");
 518                         }
 519                         if(error & IDE_ERR_IDNF) {
 520                                 printk("id mark not found, ");
 521                         }
 522                         if(error & IDE_ERR_MC) {
 523                                 printk("media changer, ");
 524                         }
 525                         if(error & IDE_ERR_UNC) {
 526                                 printk("uncorrectable data, ");
 527                         }
 528                         if(error & IDE_ERR_BBK) {
 529                                 printk("bad block, ");
 530                         }
 531                         printk("]");
 532                 }
 533         }
 534         if(status & IDE_STAT_DWF) {
 535                 printk("device fault, ");
 536         }
 537         if(status & IDE_STAT_BSY) {
 538                 printk("device busy, ");
 539         }
 540         printk("\n");
 541 }
 542 
 543 void ide_delay(void)
 544 {
 545         int n;
 546 
 547         for(n = 0; n < 10000; n++) {
 548                 NOP();
 549         }
 550 }
 551 
 552 void ide_wait400ns(struct ide *ide)
 553 {
 554         int n;
 555 
 556         /* wait 400ns */
 557         for(n = 0; n < 4; n++) {
 558                 inport_b(ide->ctrl + IDE_ALT_STATUS);
 559         }
 560 }
 561 
 562 int ide_drvsel(struct ide *ide, int drive, int mode, unsigned char lba24_head)
 563 {
 564         int n, status;
 565 
 566         status = 0;
 567 
 568         for(n = 0; n < MAX_IDE_ERR; n++) {
 569                 if((status = ide_get_status(ide))) {
 570                         continue;
 571                 }
 572                 break;
 573         }
 574         if(status) {
 575                 return status;
 576         }
 577 
 578         outport_b(ide->base + IDE_DRVHD, (mode + (drive << 4)) | lba24_head);
 579         ide_wait400ns(ide);
 580 
 581         for(n = 0; n < MAX_IDE_ERR; n++) {
 582                 if((status = ide_get_status(ide))) {
 583                         continue;
 584                 }
 585                 break;
 586         }
 587         return status;
 588 }
 589 
 590 int ide_softreset(struct ide *ide)
 591 {
 592         int error;
 593         unsigned short int dev_type;
 594 
 595         error = 0;
 596 
 597         outport_b(ide->base + IDE_DRVHD, IDE_CHS_MODE);
 598         ide_delay();
 599 
 600         outport_b(ide->ctrl + IDE_DEV_CTRL, IDE_DEVCTR_SRST | IDE_DEVCTR_NIEN);
 601         ide_delay();
 602         outport_b(ide->ctrl + IDE_DEV_CTRL, 0);
 603         ide_delay();
 604 
 605         outport_b(ide->base + IDE_DRVHD, IDE_CHS_MODE);
 606         ide_delay();
 607         if(ide_get_status(ide)) {
 608                 printk("WARNING: %s(): reset error on IDE(%d:0).\n", __FUNCTION__, ide->channel);
 609                 error = 1;
 610         } else {
 611                 /* find out the device type */
 612                 if(inport_b(ide->base + IDE_SECCNT) == 1 && inport_b(ide->base + IDE_SECNUM) == 1) {
 613                         dev_type = (inport_b(ide->base + IDE_HCYL) << 8) | inport_b(ide->base + IDE_LCYL);
 614                         switch(dev_type) {
 615                                 case 0xEB14:
 616                                         ide->drive[IDE_MASTER].flags |= DEVICE_IS_ATAPI;
 617                                         break;
 618                                 case 0x0:
 619                                 default:
 620                                         ide->drive[IDE_MASTER].flags |= DEVICE_IS_DISK;
 621                         }
 622                 }
 623         }
 624 
 625         outport_b(ide->base + IDE_DRVHD, IDE_CHS_MODE + (1 << 4));
 626         ide_delay();
 627         if(ide_get_status(ide)) {
 628                 printk("WARNING: %s(): reset error on IDE(%d:1).\n", __FUNCTION__, ide->channel);
 629                 outport_b(ide->base + IDE_DRVHD, IDE_CHS_MODE);
 630                 ide_delay();
 631                 ide_get_status(ide);
 632                 error |= (1 << 4);
 633         }
 634 
 635         outport_b(ide->ctrl + IDE_DEV_CTRL, 0);
 636         ide_delay();
 637         if(error > 1) {
 638                 return error;
 639         }
 640 
 641         /* find out the device type */
 642         if(inport_b(ide->base + IDE_SECCNT) == 1 && inport_b(ide->base + IDE_SECNUM) == 1) {
 643                 dev_type = (inport_b(ide->base + IDE_HCYL) << 8) | inport_b(ide->base + IDE_LCYL);
 644                 switch(dev_type) {
 645                         case 0xEB14:
 646                                 ide->drive[IDE_SLAVE].flags |= DEVICE_IS_ATAPI;
 647                                 break;
 648                         case 0x0:
 649                         default:
 650                                 ide->drive[IDE_SLAVE].flags |= DEVICE_IS_DISK;
 651                 }
 652         }
 653 
 654         return error;
 655 }
 656 
 657 struct ide *get_ide_controller(__dev_t dev)
 658 {
 659         int controller;
 660 
 661         if(MAJOR(dev) == IDE0_MAJOR) {
 662                 controller = IDE_PRIMARY;
 663         } else {
 664                 if(MAJOR(dev) == IDE1_MAJOR) {
 665                         controller = IDE_SECONDARY;
 666                 } else {
 667                         return NULL;
 668                 }
 669         }
 670         return &ide_table[controller];
 671 }
 672 
 673 int get_ide_drive(__dev_t dev)
 674 {
 675         int drive;
 676 
 677         drive = MINOR(dev);
 678         if(drive) {
 679                 if(drive & (1 << IDE_SLAVE_MSF)) {
 680                         drive = IDE_SLAVE;
 681                 } else {
 682                         drive = IDE_MASTER;
 683                 }
 684         }
 685         return drive;
 686 }
 687 
 688 int ide_open(struct inode *i, struct fd *fd_table)
 689 {
 690         int drive;
 691         struct ide *ide;
 692 
 693         if(!(ide = get_ide_controller(i->rdev))) {
 694                 return -EINVAL;
 695         }
 696 
 697         if(!get_device(BLK_DEV, i->rdev)) {
 698                 return -ENXIO;
 699         }
 700 
 701         drive = get_ide_drive(i->rdev);
 702         if(ide->drive[drive].fsop && ide->drive[drive].fsop->open) {
 703                 return ide->drive[drive].fsop->open(i, fd_table);
 704         }
 705         return -EINVAL;
 706 }
 707 
 708 int ide_close(struct inode *i, struct fd *fd_table)
 709 {
 710         int drive;
 711         struct ide *ide;
 712 
 713         if(!(ide = get_ide_controller(i->rdev))) {
 714                 return -EINVAL;
 715         }
 716 
 717         if(!get_device(BLK_DEV, i->rdev)) {
 718                 return -ENXIO;
 719         }
 720 
 721         drive = get_ide_drive(i->rdev);
 722         if(ide->drive[drive].fsop && ide->drive[drive].fsop->close) {
 723                 return ide->drive[drive].fsop->close(i, fd_table);
 724         }
 725         return -EINVAL;
 726 }
 727 
 728 int ide_read(__dev_t dev, __blk_t block, char *buffer, int blksize)
 729 {
 730         int drive;
 731         struct ide *ide;
 732 
 733         if(!(ide = get_ide_controller(dev))) {
 734                 printk("%s(): no ide controller!\n", __FUNCTION__);
 735                 return -EINVAL;
 736         }
 737 
 738         if(!get_device(BLK_DEV, dev)) {
 739                 return -ENXIO;
 740         }
 741 
 742         drive = get_ide_drive(dev);
 743         if(ide->drive[drive].fsop && ide->drive[drive].fsop->read_block) {
 744                 return ide->drive[drive].fsop->read_block(dev, block, buffer, blksize);
 745         }
 746         printk("WARNING: %s(): device %d,%d does not have the read_block() method!\n", __FUNCTION__, MAJOR(dev), MINOR(dev));
 747         return -EINVAL;
 748 }
 749 
 750 int ide_write(__dev_t dev, __blk_t block, char *buffer, int blksize)
 751 {
 752         int drive;
 753         struct ide *ide;
 754 
 755         if(!(ide = get_ide_controller(dev))) {
 756                 printk("%s(): no ide controller!\n", __FUNCTION__);
 757                 return -EINVAL;
 758         }
 759 
 760         if(!get_device(BLK_DEV, dev)) {
 761                 return -ENXIO;
 762         }
 763 
 764         drive = get_ide_drive(dev);
 765         if(ide->drive[drive].fsop && ide->drive[drive].fsop->write_block) {
 766                 return ide->drive[drive].fsop->write_block(dev, block, buffer, blksize);
 767         }
 768         printk("WARNING: %s(): device %d,%d does not have the write_block() method!\n", __FUNCTION__, MAJOR(dev), MINOR(dev));
 769         return -EINVAL;
 770 }
 771 
 772 int ide_ioctl(struct inode *i, int cmd, unsigned long int arg)
 773 {
 774         int drive;
 775         struct ide *ide;
 776 
 777         if(!(ide = get_ide_controller(i->rdev))) {
 778                 return -EINVAL;
 779         }
 780 
 781         if(!get_device(BLK_DEV, i->rdev)) {
 782                 return -ENXIO;
 783         }
 784 
 785         drive = get_ide_drive(i->rdev);
 786         if(ide->drive[drive].fsop && ide->drive[drive].fsop->ioctl) {
 787                 return ide->drive[drive].fsop->ioctl(i, cmd, arg);
 788         }
 789         return -EINVAL;
 790 }
 791 
 792 void ide_init(void)
 793 {
 794         int devices, errno;
 795         struct ide *ide;
 796 
 797         if(!register_irq(IDE0_IRQ, &irq_config_ide0)) {
 798                 enable_irq(IDE0_IRQ);
 799         }
 800         devices = 0;
 801 
 802         ide = &ide_table[IDE_PRIMARY];
 803         errno = ide_softreset(ide);
 804         if(!(errno & 1)) {
 805                 if(!(ide_identify(ide, IDE_MASTER))) {
 806                         get_device_size(&ide->drive[IDE_MASTER]);
 807                         ide_results(ide, IDE_MASTER);
 808                         SET_MINOR(ide0_device.minors, 0);
 809                         register_device(BLK_DEV, &ide0_device);
 810                         if(ide->drive[IDE_MASTER].flags & DEVICE_IS_DISK) {
 811                                 if(!ide_hd_init(ide, IDE_MASTER)) {
 812                                         devices++;
 813                                 }
 814                         }
 815                         if(ide->drive[IDE_MASTER].flags & DEVICE_IS_CDROM) {
 816                                 if(!ide_cd_init(ide, IDE_MASTER)) {
 817                                         devices++;
 818                                 }
 819                         }
 820                 }
 821         }
 822         if(!(errno & 0x10)) {
 823                 if(!(ide_identify(ide, IDE_SLAVE))) {
 824                         get_device_size(&ide->drive[IDE_SLAVE]);
 825                         ide_results(ide, IDE_SLAVE);
 826                         SET_MINOR(ide0_device.minors, 1 << IDE_SLAVE_MSF);
 827                         if(!devices) {
 828                                 register_device(BLK_DEV, &ide0_device);
 829                         }
 830                         if(ide->drive[IDE_SLAVE].flags & DEVICE_IS_DISK) {
 831                                 if(!ide_hd_init(ide, IDE_SLAVE)) {
 832                                         devices++;
 833                                 }
 834                         }
 835                         if(ide->drive[IDE_SLAVE].flags & DEVICE_IS_CDROM) {
 836                                 if(!ide_cd_init(ide, IDE_SLAVE)) {
 837                                         devices++;
 838                                 }
 839                         }
 840                 }
 841         }
 842         if(!devices) {
 843                 disable_irq(IDE0_IRQ);
 844                 unregister_irq(IDE0_IRQ, &irq_config_ide0);
 845         }
 846 
 847         if(!register_irq(IDE1_IRQ, &irq_config_ide1)) {
 848                 enable_irq(IDE1_IRQ);
 849         }
 850         devices = 0;
 851         ide = &ide_table[IDE_SECONDARY];
 852         errno = ide_softreset(ide);
 853         if(!(errno & 1)) {
 854                 if(!(ide_identify(ide, IDE_MASTER))) {
 855                         get_device_size(&ide->drive[IDE_MASTER]);
 856                         ide_results(ide, IDE_MASTER);
 857                         SET_MINOR(ide1_device.minors, 0);
 858                         register_device(BLK_DEV, &ide1_device);
 859                         if(ide->drive[IDE_MASTER].flags & DEVICE_IS_DISK) {
 860                                 if(!ide_hd_init(ide, IDE_MASTER)) {
 861                                         devices++;
 862                                 }
 863                         }
 864                         if(ide->drive[IDE_MASTER].flags & DEVICE_IS_CDROM) {
 865                                 if(!ide_cd_init(ide, IDE_MASTER)) {
 866                                         devices++;
 867                                 }
 868                         }
 869                 }
 870         }
 871         if(!(errno & 0x10)) {
 872                 if(!(ide_identify(ide, IDE_SLAVE))) {
 873                         get_device_size(&ide->drive[IDE_SLAVE]);
 874                         ide_results(ide, IDE_SLAVE);
 875                         SET_MINOR(ide1_device.minors, 1 << IDE_SLAVE_MSF);
 876                         if(!devices) {
 877                                 register_device(BLK_DEV, &ide1_device);
 878                         }
 879                         if(ide->drive[IDE_SLAVE].flags & DEVICE_IS_DISK) {
 880                                 if(!ide_hd_init(ide, IDE_SLAVE)) {
 881                                         devices++;
 882                                 }
 883                         }
 884                         if(ide->drive[IDE_SLAVE].flags & DEVICE_IS_CDROM) {
 885                                 if(!ide_cd_init(ide, IDE_SLAVE)) {
 886                                         devices++;
 887                                 }
 888                         }
 889                 }
 890         }
 891         if(!devices) {
 892                 disable_irq(IDE1_IRQ);
 893                 unregister_irq(IDE1_IRQ, &irq_config_ide1);
 894         }
 895 }

/* [previous][next][first][last][top][bottom][index][help] */