--- 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:46:34 1.1.1.2 @@ -302,6 +302,8 @@ #include #include +#include + #include #include #include @@ -409,7 +411,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 +606,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 +616,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 +642,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 +658,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 +1144,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 +1156,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 +1188,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 +1246,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 +1510,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 +1524,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 +1540,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 +1592,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 +1621,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 +1661,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 +1711,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); @@ -2010,7 +2035,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 +2086,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 +2172,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 +2187,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 +2336,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 +2444,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 +2470,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 +2489,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; @@ -2546,8 +2583,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 +2608,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; @@ -2827,7 +2875,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 +2935,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; } @@ -3314,6 +3374,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 +3382,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 +3394,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 +3636,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 +3668,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 +3684,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 +3706,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 +3761,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; }