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. ide_results
  5. ide_get_status
  6. irq_ide0
  7. irq_ide1
  8. ide0_timer
  9. ide1_timer
  10. ide_error
  11. ide_delay
  12. ide_wait400ns
  13. ide_drvsel
  14. ide_softreset
  15. get_ide_controller
  16. get_ide_drive
  17. ide_open
  18. ide_close
  19. ide_read
  20. ide_write
  21. ide_ioctl
  22. ide_init

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

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