--- Gnu-Mach/linux/src/drivers/block/ide.c 2020/09/02 04:41:40 1.1 +++ Gnu-Mach/linux/src/drivers/block/ide.c 2020/09/02 04:53:20 1.1.1.4 @@ -302,6 +302,8 @@ #include #include +#include + #include #include #include @@ -323,7 +325,7 @@ #endif /* CONFIG_BLK_DEV_PROMISE */ static const byte ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR}; -static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168}; +static unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168}; static const byte default_irqs[MAX_HWIFS] = {14, 15, 11, 10}; static int idebus_parameter; /* holds the "idebus=" parameter */ static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ @@ -365,6 +367,15 @@ static void set_recovery_timer (ide_hwif #endif /* DISK_RECOVERY_TIME */ +/* Called by other drivers to disable the legacy IDE driver on a given IDE base. */ +void ide_disable_base(unsigned base) +{ + unsigned i; + for (i = 0; i < MAX_HWIFS; i++) + if (default_io_base[i] == base) + default_io_base[i] = 0; +} + /* * Do not even *think* about calling this! @@ -409,7 +420,11 @@ static void init_hwif_data (unsigned int drive->special.b.set_geometry = 1; drive->name[0] = 'h'; drive->name[1] = 'd'; +#ifdef MACH + drive->name[2] = '0' + (index * MAX_DRIVES) + unit; +#else drive->name[2] = 'a' + (index * MAX_DRIVES) + unit; +#endif } } @@ -600,6 +615,9 @@ void ide_set_handler (ide_drive_t *drive * * Returns: 1 if lba_capacity looks sensible * 0 otherwise + * + * Note: we must not change id->cyls here, otherwise a second call + * of this routine might no longer find lba_capacity ok. */ static int lba_capacity_is_ok (struct hd_driveid *id) { @@ -607,11 +625,16 @@ static int lba_capacity_is_ok (struct hd unsigned long chs_sects = id->cyls * id->heads * id->sectors; unsigned long _10_percent = chs_sects / 10; - /* very large drives (8GB+) may lie about the number of cylinders */ - if (id->cyls == 16383 && id->heads == 16 && id->sectors == 63 && lba_sects > chs_sects) { - id->cyls = lba_sects / (16 * 63); /* correct cyls */ + /* + * The ATA spec tells large drives to return + * C/H/S = 16383/16/63 independent of their size. + * Some drives can be jumpered to use 15 heads instead of 16. + */ + if (id->cyls == 16383 && id->sectors == 63 && + (id->heads == 15 || id->heads == 16) && + id->lba_capacity >= 16383*63*id->heads) return 1; /* lba_capacity is our only option */ - } + /* perform a rough sanity check on lba_sects: within 10% is "okay" */ if ((lba_sects - chs_sects) < _10_percent) return 1; /* lba_capacity is good */ @@ -628,11 +651,13 @@ static int lba_capacity_is_ok (struct hd /* * current_capacity() returns the capacity (in sectors) of a drive * according to its current geometry/LBA settings. + * + * It also sets select.b.lba. */ static unsigned long current_capacity (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - unsigned long capacity = drive->cyl * drive->head * drive->sect; + unsigned long capacity; if (!drive->present) return 0; @@ -642,11 +667,12 @@ static unsigned long current_capacity (i #endif /* CONFIG_BLK_DEV_IDEFLOPPY */ if (drive->media != ide_disk) return 0x7fffffff; /* cdrom or tape */ + drive->select.b.lba = 0; /* Determine capacity, and use LBA if the drive properly supports it */ + capacity = drive->cyl * drive->head * drive->sect; if (id != NULL && (id->capability & 2) && lba_capacity_is_ok(id)) { if (id->lba_capacity >= capacity) { - drive->cyl = id->lba_capacity / (drive->head * drive->sect); capacity = id->lba_capacity; drive->select.b.lba = 1; } @@ -1127,6 +1153,9 @@ read_next: msect -= nsect; } else nsect = 1; + i = rq->nr_sectors - nsect; + if (i > 0 && !msect) + ide_set_handler (drive, &read_intr, WAIT_CMD); ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); #ifdef DEBUG printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n", @@ -1136,14 +1165,11 @@ read_next: rq->sector += nsect; rq->buffer += nsect<<9; rq->errors = 0; - i = (rq->nr_sectors -= nsect); + rq->nr_sectors = i; if ((rq->current_nr_sectors -= nsect) <= 0) ide_end_request(1, HWGROUP(drive)); - if (i > 0) { - if (msect) - goto read_next; - ide_set_handler (drive, &read_intr, WAIT_CMD); - } + if (i > 0 && msect) + goto read_next; } /* @@ -1171,8 +1197,8 @@ static void write_intr (ide_drive_t *dri if (rq->current_nr_sectors <= 0) ide_end_request(1, hwgroup); if (i > 0) { - ide_output_data (drive, rq->buffer, SECTOR_WORDS); ide_set_handler (drive, &write_intr, WAIT_CMD); + ide_output_data (drive, rq->buffer, SECTOR_WORDS); } return; } @@ -1229,8 +1255,8 @@ static void multwrite_intr (ide_drive_t if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) { if (stat & DRQ_STAT) { if (rq->nr_sectors) { - ide_multwrite(drive, drive->mult_count); ide_set_handler (drive, &multwrite_intr, WAIT_CMD); + ide_multwrite(drive, drive->mult_count); return; } } else { @@ -1493,6 +1519,10 @@ static inline void do_rw_disk (ide_drive if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive))) return; #endif /* CONFIG_BLK_DEV_TRITON */ + if (drive->mult_count) + ide_set_handler (drive, &multwrite_intr, WAIT_CMD); + else + ide_set_handler (drive, &write_intr, WAIT_CMD); OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, io_base+IDE_COMMAND_OFFSET); if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { printk("%s: no DRQ after issuing %s\n", drive->name, @@ -1503,10 +1533,8 @@ static inline void do_rw_disk (ide_drive cli(); if (drive->mult_count) { HWGROUP(drive)->wrq = *rq; /* scratchpad */ - ide_set_handler (drive, &multwrite_intr, WAIT_CMD); ide_multwrite(drive, drive->mult_count); } else { - ide_set_handler (drive, &write_intr, WAIT_CMD); ide_output_data(drive, rq->buffer, SECTOR_WORDS); } return; @@ -1521,7 +1549,7 @@ static inline void do_rw_disk (ide_drive */ static void execute_drive_cmd (ide_drive_t *drive, struct request *rq) { - byte *args = rq->buffer; + byte *args = (byte *)rq->buffer; if (args) { #ifdef DEBUG printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x xx=0x%02x\n", @@ -1573,8 +1601,14 @@ static inline void do_request (ide_hwif_ block = rq->sector; blockend = block + rq->nr_sectors; if ((blockend < block) || (blockend > drive->part[minor&PARTN_MASK].nr_sects)) { +#ifdef MACH + printk ("%s%c: bad access: block=%ld, count=%ld, blockend=%ld, nr_sects%ld\n", + drive->name, (minor&PARTN_MASK)?'0'+(minor&PARTN_MASK):' ', + block, rq->nr_sectors, blockend, drive->part[minor&PARTN_MASK].nr_sects); +#else printk("%s%c: bad access: block=%ld, count=%ld\n", drive->name, (minor&PARTN_MASK)?'0'+(minor&PARTN_MASK):' ', block, rq->nr_sectors); +#endif goto kill_rq; } block += drive->part[minor&PARTN_MASK].start_sect + drive->sect0; @@ -1596,7 +1630,7 @@ static inline void do_request (ide_hwif_ printk("%s: drive not ready for command\n", drive->name); return; } - + if (!drive->special.all) { if (rq->cmd == IDE_DRIVE_CMD) { execute_drive_cmd(drive, rq); @@ -1636,7 +1670,7 @@ static inline void do_request (ide_hwif_ #else do_rw_disk (drive, rq, block); /* simpler and faster */ return; -#endif /* CONFIG_BLK_DEV_IDEATAPI */; +#endif /* CONFIG_BLK_DEV_IDEATAPI */ } do_special(drive); return; @@ -1686,7 +1720,7 @@ void ide_do_request (ide_hwgroup_t *hwgr hwgroup->active = 0; return; /* no work left for this hwgroup */ } - got_rq: + got_rq: do_request(hwgroup->hwif = hwgroup->next_hwif = hwif, hwgroup->rq = rq); cli(); } while (hwgroup->handler == NULL); @@ -1902,6 +1936,7 @@ void ide_init_drive_cmd (struct request rq->rq_status = RQ_ACTIVE; rq->rq_dev = ????; #endif + rq->quiet = 0; } /* @@ -2010,7 +2045,7 @@ static int ide_open(struct inode * inode struct request rq; check_disk_change(inode->i_rdev); ide_init_drive_cmd (&rq); - rq.buffer = door_lock; + rq.buffer = (char *)door_lock; /* * Ignore the return code from door_lock, * since the open() has already succeeded, @@ -2061,7 +2096,7 @@ static void ide_release(struct inode * i struct request rq; invalidate_buffers(inode->i_rdev); ide_init_drive_cmd (&rq); - rq.buffer = door_unlock; + rq.buffer = (char *)door_unlock; (void) ide_do_drive_cmd(drive, &rq, ide_wait); } } @@ -2147,6 +2182,14 @@ static int ide_ioctl (struct inode *inod { struct hd_geometry *loc = (struct hd_geometry *) arg; if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; +#ifdef MACH + loc->heads = drive->bios_head; + loc->sectors = drive->bios_sect; + loc->cylinders = drive->bios_cyl; + loc->start + = (drive->part[MINOR(inode->i_rdev)&PARTN_MASK] + .start_sect); +#else err = verify_area(VERIFY_WRITE, loc, sizeof(*loc)); if (err) return err; put_user(drive->bios_head, (byte *) &loc->heads); @@ -2154,6 +2197,7 @@ static int ide_ioctl (struct inode *inod put_user(drive->bios_cyl, (unsigned short *) &loc->cylinders); put_user((unsigned)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].start_sect, (unsigned long *) &loc->start); +#endif return 0; } case BLKFLSBUF: @@ -2302,7 +2346,7 @@ static int ide_ioctl (struct inode *inod argbuf[3] = args[3]; } if (!(err = verify_area(VERIFY_WRITE,(void *)arg, argsize))) { - rq.buffer = argbuf; + rq.buffer = (char *)argbuf; err = ide_do_drive_cmd(drive, &rq, ide_wait); memcpy_tofs((void *)arg, argbuf, argsize); } @@ -2410,7 +2454,7 @@ static inline void do_identify (ide_driv #if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA) /* - * EATA SCSI controllers do a hardware ATA emulation: + * EATA SCSI controllers do a hardware ATA emulation: * Ignore them if there is a driver for them available. */ if ((id->model[0] == 'P' && id->model[1] == 'M') @@ -2436,7 +2480,7 @@ static inline void do_identify (ide_driv ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap); ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap); - if (strstr(id->model, "E X A B Y T E N E S T")) + if (strstr((char *)id->model, "E X A B Y T E N E S T")) return; #ifdef CONFIG_BLK_DEV_IDEATAPI @@ -2455,9 +2499,12 @@ static inline void do_identify (ide_driv #endif /* CONFIG_BLK_DEV_PROMISE */ if (!drive->ide_scsi) switch (type) { case 0: - if (!strstr(id->model, "oppy") && !strstr(id->model, "poyp") && !strstr(id->model, "ZIP")) + if (!strstr((char *)id->model, "oppy") && + !strstr((char *)id->model, "poyp") && + !strstr((char *)id->model, "ZIP")) printk("cdrom or floppy?, assuming "); - if (drive->media != ide_cdrom && !strstr(id->model, "CD-ROM")) { + if (drive->media != ide_cdrom && + !strstr((char *)id->model, "CD-ROM")) { #ifdef CONFIG_BLK_DEV_IDEFLOPPY printk("FLOPPY drive\n"); drive->media = ide_floppy; @@ -2488,7 +2535,7 @@ static inline void do_identify (ide_driv drive->media = ide_tape; drive->present = 1; drive->removable = 1; - if (drive->autotune != 2 && HWIF(drive)->dmaproc != NULL) { + if (drive->autotune != 2 && HWIF(drive)->dmaproc != NULL && !drive->nodma) { if (!HWIF(drive)->dmaproc(ide_dma_check, drive)) printk(", DMA"); } @@ -2546,8 +2593,7 @@ static inline void do_identify (ide_driv } /* Handle logical geometry translation by the drive */ if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads - && (id->cur_heads <= 16) && id->cur_sectors) - { + && (id->cur_heads <= 16) && id->cur_sectors) { /* * Extract the physical drive geometry for our use. * Note that we purposely do *not* update the bios info. @@ -2572,23 +2618,35 @@ static inline void do_identify (ide_driv } } /* Use physical geometry if what we have still makes no sense */ - if ((!drive->head || drive->head > 16) && id->heads && id->heads <= 16) { + if ((!drive->head || drive->head > 16) && + id->heads && id->heads <= 16) { drive->cyl = id->cyls; drive->head = id->heads; drive->sect = id->sectors; } /* calculate drive capacity, and select LBA if possible */ - (void) current_capacity (drive); + capacity = current_capacity (drive); - /* Correct the number of cyls if the bios value is too small */ - if (drive->sect == drive->bios_sect && drive->head == drive->bios_head) { - if (drive->cyl > drive->bios_cyl) - drive->bios_cyl = drive->cyl; + /* + * if possible, give fdisk access to more of the drive, + * by correcting bios_cyls: + */ + if (capacity > drive->bios_cyl * drive->bios_head * drive->bios_sect + && !drive->forced_geom && drive->bios_sect && drive->bios_head) { + int cyl = (capacity / drive->bios_sect) / drive->bios_head; + if (cyl <= 65535) + drive->bios_cyl = cyl; + else { + /* OK until 539 GB */ + drive->bios_sect = 63; + drive->bios_head = 255; + drive->bios_cyl = capacity / (63*255); + } } - if (!strncmp(id->model, "BMI ", 4) && - strstr(id->model, " ENHANCED IDE ") && + if (!strncmp((char *)id->model, "BMI ", 4) && + strstr((char *)id->model, " ENHANCED IDE ") && drive->select.b.lba) drive->no_geom = 1; @@ -2604,7 +2662,7 @@ static inline void do_identify (ide_driv if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect)) drive->special.b.set_multmode = 1; } - if (drive->autotune != 2 && HWIF(drive)->dmaproc != NULL) { + if (drive->autotune != 2 && HWIF(drive)->dmaproc != NULL && !drive->nodma) { if (!(HWIF(drive)->dmaproc(ide_dma_check, drive))) { if ((id->field_valid & 4) && (id->dma_ultra & (id->dma_ultra >> 8) & 7)) printk(", UDMA"); @@ -2827,7 +2885,7 @@ static inline byte probe_for_drive (ide_ (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ #endif /* CONFIG_BLK_DEV_IDEATAPI */ } - if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T")) + if (drive->id && strstr((char *)drive->id->model, "E X A B Y T E N E S T")) enable_nest(drive); if (!drive->present) return 0; /* drive not found */ @@ -2887,11 +2945,23 @@ static void probe_cmos_for_drives (ide_h for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; if ((cmos_disks & (0xf0 >> (unit*4))) && !drive->present && !drive->nobios) { - drive->cyl = drive->bios_cyl = *(unsigned short *)BIOS; - drive->head = drive->bios_head = *(BIOS+2); - drive->sect = drive->bios_sect = *(BIOS+14); - drive->ctl = *(BIOS+8); - drive->present = 1; + unsigned short cyl = *(unsigned short *)BIOS; + unsigned char head = *(BIOS+2); + unsigned char sect = *(BIOS+14); + unsigned char ctl = *(BIOS+8); + if (cyl > 0 && head > 0 && sect > 0 && sect < 64) { + drive->cyl = drive->bios_cyl = cyl; + drive->head = drive->bios_head = head; + drive->sect = drive->bios_sect = sect; + drive->ctl = ctl; + drive->present = 1; + printk("hd%d: got CHS=%d/%d/%d CTL=%x from BIOS\n", + unit, cyl, head, sect, ctl); + + } else { + printk("hd%d: CHS=%d/%d/%d CTL=%x from BIOS ignored\n", + unit, cyl, head, sect, ctl); + } } BIOS += 16; } @@ -3047,6 +3117,7 @@ static int match_parm (char *s, const ch * Not fully supported by all chipset types, * and quite likely to cause trouble with * older/odd IDE drives. + * "hdx=nodma" : disallow DMA for the drive * * "idebus=xx" : inform IDE driver of VESA/PCI bus speed in Mhz, * where "xx" is between 20 and 66 inclusive, @@ -3091,7 +3162,11 @@ void ide_setup (char *s) ide_hwif_t *hwif; ide_drive_t *drive; unsigned int hw, unit; +#ifdef MACH + const char max_drive = '0' + ((MAX_HWIFS * MAX_DRIVES) - 1); +#else const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1); +#endif const char max_hwif = '0' + (MAX_HWIFS - 1); printk("ide_setup: %s", s); @@ -3100,11 +3175,19 @@ void ide_setup (char *s) /* * Look for drive options: "hdx=" */ +#ifdef MACH + if (s[0] == 'h' && s[1] == 'd' && s[2] >= '0' && s[2] <= max_drive) { +#else if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { +#endif const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom", "serialize", "autotune", "noautotune", - "slow", "ide-scsi", NULL}; + "slow", "ide-scsi", "nodma", NULL}; +#ifdef MACH + unit = s[2] - '0'; +#else unit = s[2] - 'a'; +#endif hw = unit / MAX_DRIVES; unit = unit % MAX_DRIVES; hwif = &ide_hwifs[hw]; @@ -3139,6 +3222,9 @@ void ide_setup (char *s) case -9: /* "ide-scsi" */ drive->ide_scsi = 1; goto done; + case -10: /* "nodma" */ + drive->nodma = 1; + goto done; case 3: /* cyl,head,sect */ drive->media = ide_disk; drive->cyl = drive->bios_cyl = vals[0]; @@ -3314,6 +3400,7 @@ done: * an IDE disk drive, or if a geometry was "forced" on the commandline. * Returns 1 if the geometry translation was successful. */ + int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg) { ide_drive_t *drive; @@ -3321,7 +3408,11 @@ int ide_xlate_1024 (kdev_t i_rdev, int x const byte *heads = head_vals; unsigned long tracks; - if ((drive = get_info_ptr(i_rdev)) == NULL || drive->forced_geom) + drive = get_info_ptr(i_rdev); + if (!drive) + return 0; + + if (drive->forced_geom) return 0; if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) @@ -3329,6 +3420,10 @@ int ide_xlate_1024 (kdev_t i_rdev, int x printk("%s ", msg); + if (xparm < 0 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63)) { + return 0; /* small disk: no translation needed */ + } + if (drive->id) { drive->cyl = drive->id->cyls; drive->head = drive->id->heads; @@ -3567,9 +3662,6 @@ static void ide_probe_promise_20246(void hwif->ctl_port = io[tmp + 1] + 2; hwif->noprobe = 0; } -#ifdef CONFIG_BLK_DEV_TRITON - ide_init_promise (bus, fn, &ide_hwifs[2], &ide_hwifs[3], io[4]); -#endif /* CONFIG_BLK_DEV_TRITON */ } #endif /* CONFIG_PCI */ @@ -3602,6 +3694,9 @@ static void probe_for_hwifs (void) ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371_0, &ide_init_triton, 1); ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1, &ide_init_triton, 0); ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, &ide_init_triton, 0); + ide_probe_pci (PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, &ide_init_triton, 0); + ide_probe_pci (PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, &ide_init_triton, 0); + ide_probe_pci (PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, &ide_init_triton, 0); #endif /* CONFIG_BLK_DEV_TRITON */ ide_probe_promise_20246(); } @@ -3615,13 +3710,14 @@ static void probe_for_hwifs (void) #ifdef CONFIG_BLK_DEV_PROMISE init_dc4030(); #endif + ahci_probe_pci(); } static int hwif_init (int h) { ide_hwif_t *hwif = &ide_hwifs[h]; void (*rfn)(void); - + if (!hwif->present) return 0; if (!hwif->irq) { @@ -3636,7 +3732,7 @@ static int hwif_init (int h) return (hwif->present = 0); } #endif /* CONFIG_BLK_DEV_HD */ - + hwif->present = 0; /* we set it back to 1 if all is ok below */ switch (hwif->major) { case IDE0_MAJOR: rfn = &do_ide0_request; break; @@ -3691,7 +3787,7 @@ int ide_init (void) #ifdef CONFIG_BLK_DEV_IDETAPE idetape_register_chrdev(); /* Register character device interface to the ide tape */ #endif /* CONFIG_BLK_DEV_IDETAPE */ - + return 0; }