diff -urN linux-2.4.19-p7-pristine/arch/i386/kernel/pci-pc.c linux-2.4.19-p7/arch/i386/kernel/pci-pc.c --- linux-2.4.19-p7-pristine/arch/i386/kernel/pci-pc.c Tue Apr 16 03:14:15 2002 +++ linux-2.4.19-p7/arch/i386/kernel/pci-pc.c Sat Apr 20 01:21:17 2002 @@ -1143,6 +1143,12 @@ */ if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) return; + /* + * PCI IDE controllers who are not function 1 off the south bridge + * need to be skipped. + */ + if (!(PCI_FUNC(d->devfn) & 1)) + return; DBG("PCI: IDE base address fixup for %s\n", d->slot_name); for(i=0; i<4; i++) { struct resource *r = &d->resource[i]; @@ -1199,6 +1205,11 @@ int where = 0x55; if (d->device == PCI_DEVICE_ID_VIA_8367_0) { + /* fix pci bus latency issues resulted by NB bios error + it appears on bug free^Wreduced kt266x's bios forces + NB latency to zero */ + pci_write_config_byte(d, PCI_LATENCY_TIMER, 0); + where = 0x95; /* the memory write queue timer register is different for the kt266x's: 0x95 not 0x55 */ } @@ -1216,6 +1227,7 @@ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, pci_fixup_ide_trash }, { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency }, diff -urN linux-2.4.19-p7-pristine/arch/ppc/kernel/setup.c linux-2.4.19-p7/arch/ppc/kernel/setup.c --- linux-2.4.19-p7-pristine/arch/ppc/kernel/setup.c Tue Apr 16 03:14:53 2002 +++ linux-2.4.19-p7/arch/ppc/kernel/setup.c Tue Apr 16 23:16:56 2002 @@ -687,14 +687,16 @@ id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); id->csf_default = __le16_to_cpu(id->csf_default); id->dma_ultra = __le16_to_cpu(id->dma_ultra); - id->word89 = __le16_to_cpu(id->word89); - id->word90 = __le16_to_cpu(id->word90); + id->trseuc = __le16_to_cpu(id->trseuc); + id->trsEuc = __le16_to_cpu(id->trsEuc); id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); - id->word92 = __le16_to_cpu(id->word92); + id->mprc = __le16_to_cpu(id->mprc); id->hw_config = __le16_to_cpu(id->hw_config); id->acoustic = __le16_to_cpu(id->acoustic); - for (i = 0; i < 5; i++) - id->words95_99[i] = __le16_to_cpu(id->words95_99[i]); + id->msrqs = __le16_to_cpu(id->msrqs); + id->sxfert = __le16_to_cpu(id->sxfert); + id->sal = __le16_to_cpu(id->sal); + id->spg = __le32_to_cpu(id->spg); id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2); for (i = 0; i < 22; i++) id->words104_125[i] = __le16_to_cpu(id->words104_125[i]); diff -urN linux-2.4.19-p7-pristine/arch/ppc64/kernel/setup.c linux-2.4.19-p7/arch/ppc64/kernel/setup.c --- linux-2.4.19-p7-pristine/arch/ppc64/kernel/setup.c Tue Apr 16 03:14:57 2002 +++ linux-2.4.19-p7/arch/ppc64/kernel/setup.c Tue Apr 16 23:16:56 2002 @@ -631,13 +631,19 @@ id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); id->csf_default = __le16_to_cpu(id->csf_default); id->dma_ultra = __le16_to_cpu(id->dma_ultra); - id->word89 = __le16_to_cpu(id->word89); - id->word90 = __le16_to_cpu(id->word90); + id->trseuc = __le16_to_cpu(id->trseuc); + id->trsEuc = __le16_to_cpu(id->trsEuc); id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); - id->word92 = __le16_to_cpu(id->word92); + id->mprc = __le16_to_cpu(id->mprc); id->hw_config = __le16_to_cpu(id->hw_config); - for (i = 0; i < 32; i++) - id->words94_125[i] = __le16_to_cpu(id->words94_125[i]); + id->acoustic = __le16_to_cpu(id->acoustic); + id->msrqs = __le16_to_cpu(id->msrqs); + id->sxfert = __le16_to_cpu(id->sxfert); + id->sal = __le16_to_cpu(id->sal); + id->spg = __le32_to_cpu(id->spg); + id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2); + for (i = 0; i < 22; i++) + id->words104_125[i] = __le16_to_cpu(id->words104_125[i]); id->last_lun = __le16_to_cpu(id->last_lun); id->word127 = __le16_to_cpu(id->word127); id->dlf = __le16_to_cpu(id->dlf); @@ -647,8 +653,14 @@ id->word156 = __le16_to_cpu(id->word156); for (i = 0; i < 3; i++) id->words157_159[i] = __le16_to_cpu(id->words157_159[i]); - for (i = 0; i < 96; i++) - id->words160_255[i] = __le16_to_cpu(id->words160_255[i]); + id->cfa_power = __le16_to_cpu(id->cfa_power); + for (i = 0; i < 14; i++) + id->words161_175[i] = __le16_to_cpu(id->words161_175[i]); + for (i = 0; i < 31; i++) + id->words176_205[i] = __le16_to_cpu(id->words176_205[i]); + for (i = 0; i < 48; i++) + id->words206_254[i] = __le16_to_cpu(id->words206_254[i]); + id->integrity_word = __le16_to_cpu(id->integrity_word); } diff -urN linux-2.4.19-p7-pristine/drivers/block/ll_rw_blk.c linux-2.4.19-p7/drivers/block/ll_rw_blk.c --- linux-2.4.19-p7-pristine/drivers/block/ll_rw_blk.c Tue Apr 16 03:15:07 2002 +++ linux-2.4.19-p7/drivers/block/ll_rw_blk.c Tue Apr 16 02:30:25 2002 @@ -920,6 +920,7 @@ req->bh = bh; req->buffer = bh->b_data; req->current_nr_sectors = count; + req->hard_cur_sectors = count; req->sector = req->hard_sector = sector; req->nr_sectors = req->hard_nr_sectors += count; blk_started_io(count); @@ -979,6 +980,7 @@ req->hard_sector = req->sector = sector; req->hard_nr_sectors = req->nr_sectors = count; req->current_nr_sectors = count; + req->hard_cur_sectors = count; req->nr_segments = 1; /* Always 1 for a new request. */ req->nr_hw_segments = 1; /* Always 1 for a new request. */ req->buffer = bh->b_data; @@ -1286,6 +1288,7 @@ req->nr_sectors = req->hard_nr_sectors; req->current_nr_sectors = bh->b_size >> 9; + req->hard_cur_sectors = req->current_nr_sectors; if (req->nr_sectors < req->current_nr_sectors) { req->nr_sectors = req->current_nr_sectors; printk("end_request: buffer-list destroyed\n"); diff -urN linux-2.4.19-p7-pristine/drivers/ide/Config.in linux-2.4.19-p7/drivers/ide/Config.in --- linux-2.4.19-p7-pristine/drivers/ide/Config.in Tue Apr 16 03:15:15 2002 +++ linux-2.4.19-p7/drivers/ide/Config.in Tue Apr 16 03:35:24 2002 @@ -34,7 +34,7 @@ dep_tristate ' SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE $CONFIG_SCSI bool ' IDE Taskfile Access' CONFIG_IDE_TASK_IOCTL -# bool ' IDE Taskfile IO' CONFIG_IDE_TASKFILE_IO + bool ' IDE Taskfile IO' CONFIG_IDE_TASKFILE_IO comment 'IDE chipset support/bugfixes' if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then diff -urN linux-2.4.19-p7-pristine/drivers/ide/Makefile linux-2.4.19-p7/drivers/ide/Makefile --- linux-2.4.19-p7-pristine/drivers/ide/Makefile Tue Apr 16 03:15:15 2002 +++ linux-2.4.19-p7/drivers/ide/Makefile Tue Apr 16 23:16:56 2002 @@ -10,7 +10,7 @@ O_TARGET := idedriver.o -export-objs := ide.o ide-features.o ide-probe.o ide-taskfile.o ataraid.o +export-objs := ide-taskfile.o ide.o ide-probe.o ataraid.o list-multi := ide-mod.o ide-probe-mod.o obj-y := @@ -46,6 +46,7 @@ ide-obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o ide-obj-$(CONFIG_BLK_DEV_ADMA) += ide-adma.o ide-obj-$(CONFIG_BLK_DEV_IDEDMA_PCI) += ide-dma.o +ide-obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ide-m8xx.o ide-obj-$(CONFIG_BLK_DEV_IDEPCI) += ide-pci.o ide-obj-$(CONFIG_BLK_DEV_ISAPNP) += ide-pnp.o ide-obj-$(CONFIG_BLK_DEV_IDE_PMAC) += ide-pmac.o @@ -67,7 +68,6 @@ ide-obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o ide-obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o ide-obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o -ide-obj-$(CONFIG_BLK_DEV_MPC8xx_IDE) += ide-m8xx.o # The virtualised raid layers MUST come after the ide itself or bad stuff # will happen. @@ -77,7 +77,7 @@ ide-obj-$(CONFIG_PROC_FS) += ide-proc.o -ide-mod-objs := ide.o ide-features.o ide-taskfile.o $(ide-obj-y) +ide-mod-objs := ide-taskfile.o ide.o $(ide-obj-y) ide-probe-mod-objs := ide-probe.o ide-geometry.o include $(TOPDIR)/Rules.make diff -urN linux-2.4.19-p7-pristine/drivers/ide/aec62xx.c linux-2.4.19-p7/drivers/ide/aec62xx.c --- linux-2.4.19-p7-pristine/drivers/ide/aec62xx.c Tue Jun 20 07:52:36 2000 +++ linux-2.4.19-p7/drivers/ide/aec62xx.c Fri Apr 19 14:01:04 2002 @@ -1,8 +1,7 @@ /* - * linux/drivers/ide/aec62xx.c Version 0.09 June. 9, 2000 + * linux/drivers/ide/aec62xx.c Version 0.11 March 27, 2002 * - * Copyright (C) 1999-2000 Andre Hedrick (andre@linux-ide.org) - * May be copied or modified under the terms of the GNU General Public License + * Copyright (C) 1999-2002 Andre Hedrick * */ @@ -48,154 +47,209 @@ static int aec62xx_get_info(char *, char **, off_t, int); extern int (*aec62xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; -static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count) -{ - char *p = buffer; +#define AEC_MAX_DEVS 5 - u32 bibma = pci_resource_start(bmide_dev, 4); - u8 c0 = 0, c1 = 0; - u8 art = 0, uart = 0; +static struct pci_dev *aec_devs[AEC_MAX_DEVS]; +static int n_aec_devs; - switch(bmide_dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP850UF: - p += sprintf(p, "\n AEC6210 Chipset.\n"); - break; - case PCI_DEVICE_ID_ARTOP_ATP860: - p += sprintf(p, "\n AEC6260 No Bios Chipset.\n"); - break; - case PCI_DEVICE_ID_ARTOP_ATP860R: - p += sprintf(p, "\n AEC6260 Chipset.\n"); - break; - default: - p += sprintf(p, "\n AEC62?? Chipset.\n"); - break; - } +#undef DEBUG_AEC_REGS - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); - - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - (void) pci_read_config_byte(bmide_dev, 0x4a, &art); - p += sprintf(p, " %sabled %sabled\n", - (art&0x02)?" en":"dis",(art&0x04)?" en":"dis"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ",(c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no "); - - switch(bmide_dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP850UF: - (void) pci_read_config_byte(bmide_dev, 0x54, &art); - p += sprintf(p, "DMA Mode: %s(%s) %s(%s) %s(%s) %s(%s)\n", +static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + char *chipset_nums[] = {"error", "error", "error", "error", + "error", "error", "850UF", "860", + "860R", "865", "865R", "error" }; +// char *modes_33[] = {}; +// char *modes_34[] = {}; + int i; + + for (i = 0; i < n_aec_devs; i++) { + struct pci_dev *dev = aec_devs[i]; + // u32 iobase = dev->resource[4].start; + u32 iobase = pci_resource_start(dev, 4); + u8 c0 = inb_p(iobase + 0x02); + u8 c1 = inb_p(iobase + 0x0a); + u8 art = 0; +#ifdef DEBUG_AEC_REGS + u8 uart = 0; +#endif /* DEBUG_AEC_REGS */ + + p += sprintf(p, "\nController: %d\n", i); + p += sprintf(p, "Chipset: AEC%s\n", chipset_nums[dev->device]); + + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + (void) pci_read_config_byte(dev, 0x4a, &art); + p += sprintf(p, " %sabled ", + (art&0x02)?" en":"dis"); + p += sprintf(p, " %sabled\n", + (art&0x04)?" en":"dis"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s ", + (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no "); + p += sprintf(p, " %s %s\n", + (c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no "); + + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { + (void) pci_read_config_byte(dev, 0x54, &art); + p += sprintf(p, "DMA Mode: %s(%s)", (c0&0x20)?((art&0x03)?"UDMA":" DMA"):" PIO", - (art&0x02)?"2":(art&0x01)?"1":"0", + (art&0x02)?"2":(art&0x01)?"1":"0"); + p += sprintf(p, " %s(%s)", (c0&0x40)?((art&0x0c)?"UDMA":" DMA"):" PIO", - (art&0x08)?"2":(art&0x04)?"1":"0", + (art&0x08)?"2":(art&0x04)?"1":"0"); + p += sprintf(p, " %s(%s)", (c1&0x20)?((art&0x30)?"UDMA":" DMA"):" PIO", - (art&0x20)?"2":(art&0x10)?"1":"0", + (art&0x20)?"2":(art&0x10)?"1":"0"); + p += sprintf(p, " %s(%s)\n", (c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO", (art&0x80)?"2":(art&0x40)?"1":"0"); - (void) pci_read_config_byte(bmide_dev, 0x40, &art); +#ifdef DEBUG_AEC_REGS + (void) pci_read_config_byte(dev, 0x40, &art); p += sprintf(p, "Active: 0x%02x", art); - (void) pci_read_config_byte(bmide_dev, 0x42, &art); + (void) pci_read_config_byte(dev, 0x42, &art); p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(bmide_dev, 0x44, &art); + (void) pci_read_config_byte(dev, 0x44, &art); p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(bmide_dev, 0x46, &art); + (void) pci_read_config_byte(dev, 0x46, &art); p += sprintf(p, " 0x%02x\n", art); - (void) pci_read_config_byte(bmide_dev, 0x41, &art); + (void) pci_read_config_byte(dev, 0x41, &art); p += sprintf(p, "Recovery: 0x%02x", art); - (void) pci_read_config_byte(bmide_dev, 0x43, &art); + (void) pci_read_config_byte(dev, 0x43, &art); p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(bmide_dev, 0x45, &art); + (void) pci_read_config_byte(dev, 0x45, &art); p += sprintf(p, " 0x%02x", art); - (void) pci_read_config_byte(bmide_dev, 0x47, &art); + (void) pci_read_config_byte(dev, 0x47, &art); p += sprintf(p, " 0x%02x\n", art); - break; - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - (void) pci_read_config_byte(bmide_dev, 0x44, &art); - p += sprintf(p, "DMA Mode: %s(%s) %s(%s)", +#endif /* DEBUG_AEC_REGS */ + } else { + /* + * case PCI_DEVICE_ID_ARTOP_ATP860: + * case PCI_DEVICE_ID_ARTOP_ATP860R: + * case PCI_DEVICE_ID_ARTOP_ATP865: + * case PCI_DEVICE_ID_ARTOP_ATP865R: + */ + (void) pci_read_config_byte(dev, 0x44, &art); + p += sprintf(p, "DMA Mode: %s(%s)", (c0&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO", - ((art&0x06)==0x06)?"4":((art&0x05)==0x05)?"4":((art&0x04)==0x04)?"3":((art&0x03)==0x03)?"2":((art&0x02)==0x02)?"1":((art&0x01)==0x01)?"0":"?", + ((art&0x07)==0x07)?"6": + ((art&0x06)==0x06)?"5": + ((art&0x05)==0x05)?"4": + ((art&0x04)==0x04)?"3": + ((art&0x03)==0x03)?"2": + ((art&0x02)==0x02)?"1": + ((art&0x01)==0x01)?"0":"?"); + p += sprintf(p, " %s(%s)", (c0&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO", - ((art&0x60)==0x60)?"4":((art&0x50)==0x50)?"4":((art&0x40)==0x40)?"3":((art&0x30)==0x30)?"2":((art&0x20)==0x20)?"1":((art&0x10)==0x10)?"0":"?"); - (void) pci_read_config_byte(bmide_dev, 0x45, &art); - p += sprintf(p, " %s(%s) %s(%s)\n", + ((art&0x70)==0x70)?"6": + ((art&0x60)==0x60)?"5": + ((art&0x50)==0x50)?"4": + ((art&0x40)==0x40)?"3": + ((art&0x30)==0x30)?"2": + ((art&0x20)==0x20)?"1": + ((art&0x10)==0x10)?"0":"?"); + (void) pci_read_config_byte(dev, 0x45, &art); + p += sprintf(p, " %s(%s)", (c1&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO", - ((art&0x06)==0x06)?"4":((art&0x05)==0x05)?"4":((art&0x04)==0x04)?"3":((art&0x03)==0x03)?"2":((art&0x02)==0x02)?"1":((art&0x01)==0x01)?"0":"?", + ((art&0x07)==0x07)?"6": + ((art&0x06)==0x06)?"5": + ((art&0x05)==0x05)?"4": + ((art&0x04)==0x04)?"3": + ((art&0x03)==0x03)?"2": + ((art&0x02)==0x02)?"1": + ((art&0x01)==0x01)?"0":"?"); + p += sprintf(p, " %s(%s)\n", (c1&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO", - ((art&0x60)==0x60)?"4":((art&0x50)==0x50)?"4":((art&0x40)==0x40)?"3":((art&0x30)==0x30)?"2":((art&0x20)==0x20)?"1":((art&0x10)==0x10)?"0":"?"); - (void) pci_read_config_byte(bmide_dev, 0x40, &art); + ((art&0x70)==0x70)?"6": + ((art&0x60)==0x60)?"5": + ((art&0x50)==0x50)?"4": + ((art&0x40)==0x40)?"3": + ((art&0x30)==0x30)?"2": + ((art&0x20)==0x20)?"1": + ((art&0x10)==0x10)?"0":"?"); +#ifdef DEBUG_AEC_REGS + (void) pci_read_config_byte(dev, 0x40, &art); p += sprintf(p, "Active: 0x%02x", HIGH_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x41, &art); + (void) pci_read_config_byte(dev, 0x41, &art); p += sprintf(p, " 0x%02x", HIGH_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x42, &art); + (void) pci_read_config_byte(dev, 0x42, &art); p += sprintf(p, " 0x%02x", HIGH_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x43, &art); + (void) pci_read_config_byte(dev, 0x43, &art); p += sprintf(p, " 0x%02x\n", HIGH_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x40, &art); + (void) pci_read_config_byte(dev, 0x40, &art); p += sprintf(p, "Recovery: 0x%02x", LOW_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x41, &art); + (void) pci_read_config_byte(dev, 0x41, &art); p += sprintf(p, " 0x%02x", LOW_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x42, &art); + (void) pci_read_config_byte(dev, 0x42, &art); p += sprintf(p, " 0x%02x", LOW_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x43, &art); + (void) pci_read_config_byte(dev, 0x43, &art); p += sprintf(p, " 0x%02x\n", LOW_4(art)); - (void) pci_read_config_byte(bmide_dev, 0x49, &uart); + (void) pci_read_config_byte(dev, 0x49, &uart); p += sprintf(p, "reg49h = 0x%02x ", uart); - (void) pci_read_config_byte(bmide_dev, 0x4a, &uart); + (void) pci_read_config_byte(dev, 0x4a, &uart); p += sprintf(p, "reg4ah = 0x%02x\n", uart); - break; - default: - break; +#endif /* DEBUG_AEC_REGS */ + } } - return p-buffer;/* => must be less than 4k! */ } #endif /* defined(DISPLAY_AEC62xx_TIMINGS) && defined(CONFIG_PROC_FS) */ byte aec62xx_proc = 0; -#ifdef CONFIG_AEC62XX_TUNING - struct chipset_bus_clock_list_entry { byte xfer_speed; - - byte chipset_settings_34; - byte ultra_settings_34; - - byte chipset_settings_33; - byte ultra_settings_33; + byte chipset_settings; + byte ultra_settings; }; -struct chipset_bus_clock_list_entry aec62xx_base [] = { +struct chipset_bus_clock_list_entry aec6xxx_33_base [] = { #ifdef CONFIG_BLK_DEV_IDEDMA - { XFER_UDMA_4, 0x41, 0x04, 0x31, 0x05 }, - { XFER_UDMA_3, 0x41, 0x03, 0x31, 0x04 }, - { XFER_UDMA_2, 0x41, 0x02, 0x31, 0x03 }, - { XFER_UDMA_1, 0x41, 0x01, 0x31, 0x02 }, - { XFER_UDMA_0, 0x41, 0x01, 0x31, 0x01 }, - - { XFER_MW_DMA_2, 0x41, 0x00, 0x31, 0x00 }, - { XFER_MW_DMA_1, 0x42, 0x00, 0x31, 0x00 }, - { XFER_MW_DMA_0, 0x7a, 0x00, 0x0a, 0x00 }, + { XFER_UDMA_6, 0x31, 0x07 }, + { XFER_UDMA_5, 0x31, 0x06 }, + { XFER_UDMA_4, 0x31, 0x05 }, + { XFER_UDMA_3, 0x31, 0x04 }, + { XFER_UDMA_2, 0x31, 0x03 }, + { XFER_UDMA_1, 0x31, 0x02 }, + { XFER_UDMA_0, 0x31, 0x01 }, + + { XFER_MW_DMA_2, 0x31, 0x00 }, + { XFER_MW_DMA_1, 0x31, 0x00 }, + { XFER_MW_DMA_0, 0x0a, 0x00 }, #endif /* CONFIG_BLK_DEV_IDEDMA */ - { XFER_PIO_4, 0x41, 0x00, 0x31, 0x00 }, - { XFER_PIO_3, 0x43, 0x00, 0x33, 0x00 }, - { XFER_PIO_2, 0x78, 0x00, 0x08, 0x00 }, - { XFER_PIO_1, 0x7a, 0x00, 0x0a, 0x00 }, - { XFER_PIO_0, 0x70, 0x00, 0x00, 0x00 }, - { 0, 0x00, 0x00, 0x00, 0x00 } + { XFER_PIO_4, 0x31, 0x00 }, + { XFER_PIO_3, 0x33, 0x00 }, + { XFER_PIO_2, 0x08, 0x00 }, + { XFER_PIO_1, 0x0a, 0x00 }, + { XFER_PIO_0, 0x00, 0x00 }, + { 0, 0x00, 0x00 } }; -extern char *ide_xfer_verbose (byte xfer_rate); +struct chipset_bus_clock_list_entry aec6xxx_34_base [] = { +#ifdef CONFIG_BLK_DEV_IDEDMA + { XFER_UDMA_6, 0x41, 0x06 }, + { XFER_UDMA_5, 0x41, 0x05 }, + { XFER_UDMA_4, 0x41, 0x04 }, + { XFER_UDMA_3, 0x41, 0x03 }, + { XFER_UDMA_2, 0x41, 0x02 }, + { XFER_UDMA_1, 0x41, 0x01 }, + { XFER_UDMA_0, 0x41, 0x01 }, + + { XFER_MW_DMA_2, 0x41, 0x00 }, + { XFER_MW_DMA_1, 0x42, 0x00 }, + { XFER_MW_DMA_0, 0x7a, 0x00 }, +#endif /* CONFIG_BLK_DEV_IDEDMA */ + { XFER_PIO_4, 0x41, 0x00 }, + { XFER_PIO_3, 0x43, 0x00 }, + { XFER_PIO_2, 0x78, 0x00 }, + { XFER_PIO_1, 0x7a, 0x00 }, + { XFER_PIO_0, 0x70, 0x00 }, + { 0, 0x00, 0x00 } +}; /* * TO DO: active tuning and correction of cards without a bios. @@ -203,30 +257,71 @@ static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) { - int bus_speed = system_bus_clock(); - for ( ; chipset_table->xfer_speed ; chipset_table++) if (chipset_table->xfer_speed == speed) { - return ((byte) ((bus_speed <= 33) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34)); + return chipset_table->chipset_settings; } - return 0x00; + return chipset_table->chipset_settings; } static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table) { - int bus_speed = system_bus_clock(); - for ( ; chipset_table->xfer_speed ; chipset_table++) if (chipset_table->xfer_speed == speed) { - return ((byte) ((bus_speed <= 33) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34)); + return chipset_table->ultra_settings; } - return 0x00; + return chipset_table->ultra_settings; +} + +static byte aec62xx_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + byte mode = 0x00; + + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { + mode |= 0x01; + } else if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP860) || + (dev->device == PCI_DEVICE_ID_ARTOP_ATP860R)) { + mode |= 0x02; + } else if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) || + (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R)) { + u32 bmide = pci_resource_start(dev, 4); + if (IN_BYTE(bmide+2) & 0x10) + mode |= 0x04; + else + mode |= 0x03; + } + if (!eighty_ninty_three(drive)) { + mode &= ~0xFE; + mode |= 0x01; + } + return (mode &= ~0xF8); +} + +static byte aec62xx_ratefilter (ide_drive_t *drive, byte speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + byte mode = aec62xx_ratemask(drive); + + switch(mode) { + case 0x04: while (speed > XFER_UDMA_6) speed--; break; + case 0x03: while (speed > XFER_UDMA_5) speed--; break; + case 0x02: while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; } -static int aec6210_tune_chipset (ide_drive_t *drive, byte speed) +static int aec6210_tune_chipset (ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; + byte speed = aec62xx_ratefilter(drive, xferspeed); int err = 0; unsigned short d_conf = 0x0000; byte ultra = 0x00; @@ -236,11 +331,11 @@ byte tmp2 = 0x00; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf); - tmp0 = pci_bus_clock_list(speed, aec62xx_base); + tmp0 = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) dev->driver_data); SPLIT_BYTE(tmp0,tmp1,tmp2); MAKE_WORD(d_conf,tmp1,tmp2); pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf); @@ -249,22 +344,24 @@ tmp2 = 0x00; pci_read_config_byte(dev, 0x54, &ultra); tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn)))); - ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base); + ultra_conf = pci_bus_clock_list_ultra(speed, + (struct chipset_bus_clock_list_entry *) dev->driver_data); tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn)))); pci_write_config_byte(dev, 0x54, tmp2); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); err = ide_config_drive_speed(drive, speed); return(err); } -static int aec6260_tune_chipset (ide_drive_t *drive, byte speed) +static int aec6260_tune_chipset (ide_drive_t *drive, byte xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; byte unit = (drive->select.b.unit & 0x01); byte ultra_pci = hwif->channel ? 0x45 : 0x44; + byte speed = aec62xx_ratefilter(drive, xferspeed); int err = 0; byte drive_conf = 0x00; byte ultra_conf = 0x00; @@ -273,19 +370,21 @@ byte tmp2 = 0x00; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf); - drive_conf = pci_bus_clock_list(speed, aec62xx_base); + drive_conf = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) dev->driver_data); pci_write_config_byte(dev, 0x40|drive->dn, drive_conf); pci_read_config_byte(dev, ultra_pci, &ultra); tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit)))); - ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base); + ultra_conf = pci_bus_clock_list_ultra(speed, + (struct chipset_bus_clock_list_entry *) dev->driver_data); tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit)))); pci_write_config_byte(dev, ultra_pci, tmp2); - __restore_flags(flags); /* local CPU only */ + + local_irq_restore(flags); if (!drive->init_speed) drive->init_speed = speed; @@ -295,123 +394,80 @@ return(err); } - static int aec62xx_tune_chipset (ide_drive_t *drive, byte speed) { - if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { - return ((int) aec6210_tune_chipset(drive, speed)); - } else { - return ((int) aec6260_tune_chipset(drive, speed)); + switch (HWIF(drive)->pci_dev->device) { + case PCI_DEVICE_ID_ARTOP_ATP865: + case PCI_DEVICE_ID_ARTOP_ATP865R: + case PCI_DEVICE_ID_ARTOP_ATP860: + case PCI_DEVICE_ID_ARTOP_ATP860R: + return ((int) aec6260_tune_chipset(drive, speed)); + case PCI_DEVICE_ID_ARTOP_ATP850UF: + return ((int) aec6210_tune_chipset(drive, speed)); + default: + return -1; } } #ifdef CONFIG_BLK_DEV_IDEDMA -static int config_aec6210_chipset_for_dma (ide_drive_t *drive, byte ultra) +static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; + byte mode = aec62xx_ratemask(drive); ide_hwif_t *hwif = HWIF(drive); - byte unit = (drive->select.b.unit & 0x01); - unsigned long dma_base = hwif->dma_base; - byte speed = -1; - - if (drive->media != ide_disk) - return ((int) ide_dma_off_quietly); - - if (((id->dma_ultra & 0x0010) || - (id->dma_ultra & 0x0008) || - (id->dma_ultra & 0x0004)) && (ultra)) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); - } - - outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); - (void) aec6210_tune_chipset(drive, speed); - - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_off : - ((id->dma_ultra >> 8) & 7) ? ide_dma_on : - ((id->dma_mword >> 8) & 7) ? ide_dma_on : - ((id->dma_1word >> 8) & 7) ? ide_dma_on : - ide_dma_off_quietly); -} - -static int config_aec6260_chipset_for_dma (ide_drive_t *drive, byte ultra) -{ - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - byte unit = (drive->select.b.unit & 0x01); - unsigned long dma_base = hwif->dma_base; - byte speed = -1; - byte ultra66 = eighty_ninty_three(drive); + byte unit = (drive->select.b.unit & 0x01); + unsigned long dma_base = hwif->dma_base; + byte speed; if (drive->media != ide_disk) return ((int) ide_dma_off_quietly); - - if ((id->dma_ultra & 0x0010) && (ultra) && (ultra66)) { - speed = XFER_UDMA_4; - } else if ((id->dma_ultra & 0x0008) && (ultra) && (ultra66)) { - speed = XFER_UDMA_3; - } else if ((id->dma_ultra & 0x0004) && (ultra)) { - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_mword & 0x0001) { - speed = XFER_MW_DMA_0; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else if (id->dma_1word & 0x0002) { - speed = XFER_SW_DMA_1; - } else if (id->dma_1word & 0x0001) { - speed = XFER_SW_DMA_0; - } else { - return ((int) ide_dma_off_quietly); + + switch(mode) { + case 0x04: + if (id->dma_ultra & 0x0040) + { speed = XFER_UDMA_6; break; } + case 0x03: + if (id->dma_ultra & 0x0020) + { speed = XFER_UDMA_5; break; } + case 0x02: + if (id->dma_ultra & 0x0010) + { speed = XFER_UDMA_4; break; } + if (id->dma_ultra & 0x0008) + { speed = XFER_UDMA_3; break; } + case 0x01: + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + case 0x00: + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_mword & 0x0001) + { speed = XFER_MW_DMA_0; break; } + if (id->dma_1word & 0x0004) + { speed = XFER_SW_DMA_2; break; } + if (id->dma_1word & 0x0002) + { speed = XFER_SW_DMA_1; break; } + if (id->dma_1word & 0x0001) + { speed = XFER_SW_DMA_0; break; } + default: + return ((int) ide_dma_off_quietly); } outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); - (void) aec6260_tune_chipset(drive, speed); + (void) aec62xx_tune_chipset(drive, speed); - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : + return ((int) ((id->dma_ultra >> 11) & 15) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ((id->dma_1word >> 8) & 7) ? ide_dma_on : ide_dma_off_quietly); } -static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) -{ - switch(HWIF(drive)->pci_dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP850UF: - return config_aec6210_chipset_for_dma(drive, ultra); - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - return config_aec6260_chipset_for_dma(drive, ultra); - default: - return ((int) ide_dma_off_quietly); - } -} - #endif /* CONFIG_BLK_DEV_IDEDMA */ static void aec62xx_tune_drive (ide_drive_t *drive, byte pio) @@ -427,16 +483,7 @@ case 1: speed = XFER_PIO_1; break; default: speed = XFER_PIO_0; break; } - - switch(HWIF(drive)->pci_dev->device) { - case PCI_DEVICE_ID_ARTOP_ATP850UF: - (void) aec6210_tune_chipset(drive, speed); - case PCI_DEVICE_ID_ARTOP_ATP860: - case PCI_DEVICE_ID_ARTOP_ATP860R: - (void) aec6260_tune_chipset(drive, speed); - default: - break; - } + (void) aec62xx_tune_chipset(drive, speed); } #ifdef CONFIG_BLK_DEV_IDEDMA @@ -453,9 +500,9 @@ } dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { - if (id->dma_ultra & 0x001F) { + if (id->dma_ultra & 0x007F) { /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive, 1); + dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && (dma_func != ide_dma_on)) goto try_dma_modes; @@ -465,7 +512,7 @@ if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007)) { /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive, 0); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } @@ -474,7 +521,7 @@ goto no_dma_set; } /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive, 0); + dma_func = config_chipset_for_dma(drive); if (dma_func != ide_dma_on) goto no_dma_set; } else { @@ -502,41 +549,70 @@ switch(HWIF(drive)->pci_dev->device) { case PCI_DEVICE_ID_ARTOP_ATP860: case PCI_DEVICE_ID_ARTOP_ATP860R: -// { -// int i = 0; -// byte reg49h = 0; -// pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, ®49h); -// for (i=0;i<256;i++) -// pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10); -// pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10); -// } -// return 0; + case PCI_DEVICE_ID_ARTOP_ATP865: + case PCI_DEVICE_ID_ARTOP_ATP865R: + printk(" AEC62XX time out "); +#if 0 + { + int i = 0; + byte reg49h = 0; + pci_read_config_byte(HWIF(drive)->pci_dev, 0x49, ®49h); + for (i=0;i<256;i++) + pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h|0x10); + pci_write_config_byte(HWIF(drive)->pci_dev, 0x49, reg49h & ~0x10); + } + return 0; +#endif default: break; } default: break; } +#if 0 + { + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + unsigned long dma_base = hwif->dma_base; + byte tmp1 = 0x00; + byte tmp2 = 0x00; + + pci_read_config_byte(dev, 0x44, &tmp1); + pci_read_config_byte(dev, 0x45, &tmp2); + printk(" AEC6280 r44=%x r45=%x ",tmp1,tmp2); + if (hwif->channel) + dma_base -= 0x08; + tmp1=inb(dma_base+2) & 0x10; + printk(" AEC6280 133=%x ",tmp1); + } +#endif return ide_dmaproc(func, drive); /* use standard DMA stuff */ } #endif /* CONFIG_BLK_DEV_IDEDMA */ -#endif /* CONFIG_AEC62XX_TUNING */ unsigned int __init pci_init_aec62xx (struct pci_dev *dev, const char *name) { + int bus_speed = system_bus_clock(); + if (dev->resource[PCI_ROM_RESOURCE].start) { pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); } + aec_devs[n_aec_devs++] = dev; + #if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) if (!aec62xx_proc) { aec62xx_proc = 1; - bmide_dev = dev; aec62xx_display_info = &aec62xx_get_info; } #endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */ + if (bus_speed <= 33) + dev->driver_data = (void *) aec6xxx_33_base; + else + dev->driver_data = (void *) aec6xxx_34_base; + return dev->irq; } @@ -551,7 +627,6 @@ void __init ide_init_aec62xx (ide_hwif_t *hwif) { -#ifdef CONFIG_AEC62XX_TUNING hwif->tuneproc = &aec62xx_tune_drive; hwif->speedproc = &aec62xx_tune_chipset; #ifdef CONFIG_BLK_DEV_IDEDMA @@ -561,22 +636,37 @@ hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; #endif /* CONFIG_BLK_DEV_IDEDMA */ -#endif /* CONFIG_AEC62XX_TUNING */ } void __init ide_dmacapable_aec62xx (ide_hwif_t *hwif, unsigned long dmabase) { -#ifdef CONFIG_AEC62XX_TUNING unsigned long flags; byte reg54h = 0; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - + spin_lock_irqsave(&io_request_lock, flags); pci_read_config_byte(hwif->pci_dev, 0x54, ®54h); pci_write_config_byte(hwif->pci_dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F)); - - __restore_flags(flags); /* local CPU only */ -#endif /* CONFIG_AEC62XX_TUNING */ + spin_unlock_irqrestore(&io_request_lock, flags); ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device(struct pci_dev *, ide_pci_device_t *); + +void __init aec6x80_device_fixup (struct pci_dev *dev, ide_pci_device_t *d) +{ + u32 bar4reg = pci_resource_start(dev, 4); + + if (IN_BYTE(bar4reg+2) & 0x10) { + strcpy(d->name, "AEC6880"); + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) + strcpy(d->name, "AEC6880R"); + } else { + strcpy(d->name, "AEC6280"); + if (dev->device == PCI_DEVICE_ID_ARTOP_ATP865R) + strcpy(d->name, "AEC6280R"); + } + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); } diff -urN linux-2.4.19-p7-pristine/drivers/ide/ali14xx.c linux-2.4.19-p7/drivers/ide/ali14xx.c --- linux-2.4.19-p7-pristine/drivers/ide/ali14xx.c Sun Jul 15 16:22:23 2001 +++ linux-2.4.19-p7/drivers/ide/ali14xx.c Tue Apr 16 23:16:56 2002 @@ -137,15 +137,14 @@ /* stuff timing parameters into controller registers */ driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); outb_p(regOn, basePort); outReg(param1, regTab[driveNum].reg1); outReg(param2, regTab[driveNum].reg2); outReg(param3, regTab[driveNum].reg3); outReg(param4, regTab[driveNum].reg4); outb_p(regOff, basePort); - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -157,8 +156,7 @@ byte t; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); for (i = 0; i < ALI_NUM_PORTS; ++i) { basePort = ports[i]; regOff = inb(basePort); @@ -169,7 +167,7 @@ dataPort = basePort + 8; t = inReg(0) & 0xf0; outb_p(regOff, basePort); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); if (t != 0x50) return 0; return 1; /* success */ @@ -177,7 +175,7 @@ } outb_p(regOff, basePort); } - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); return 0; } @@ -189,15 +187,14 @@ byte t; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); outb_p(regOn, basePort); for (p = initData; p->reg != 0; ++p) outReg(p->data, p->reg); outb_p(0x01, regPort); t = inb(regPort) & 0x01; outb_p(regOff, basePort); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); return t; } diff -urN linux-2.4.19-p7-pristine/drivers/ide/alim15x3.c linux-2.4.19-p7/drivers/ide/alim15x3.c --- linux-2.4.19-p7-pristine/drivers/ide/alim15x3.c Tue Apr 16 03:15:15 2002 +++ linux-2.4.19-p7/drivers/ide/alim15x3.c Tue Apr 16 23:16:56 2002 @@ -248,7 +248,7 @@ byte s_clc, a_clc, r_clc; unsigned long flags; int bus_speed = system_bus_clock(); - int port = hwif->index ? 0x5c : 0x58; + int port = hwif->channel ? 0x5c : 0x58; int portFIFO = hwif->channel ? 0x55 : 0x54; byte cd_dma_fifo = 0; @@ -272,8 +272,7 @@ if (r_clc >= 16) r_clc = 0; } - __save_flags(flags); - __cli(); + local_irq_save(flags); /* * PIO mode => ATA FIFO on, ATAPI FIFO off @@ -295,7 +294,7 @@ pci_write_config_byte(dev, port, s_clc); pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc); - __restore_flags(flags); + local_irq_restore(flags); /* * setup active rec @@ -405,7 +404,7 @@ if (!drive->init_speed) drive->init_speed = speed; - rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : + rval = (int)( ((id->dma_ultra >> 11) & 7) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ((id->dma_1word >> 8) & 7) ? ide_dma_on : @@ -445,6 +444,8 @@ if ((m5229_revision<=0x20) && (drive->media!=ide_disk)) return hwif->dmaproc(ide_dma_off_quietly, drive); + drive->init_speed = 0; + if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { @@ -505,10 +506,17 @@ } #endif /* CONFIG_BLK_DEV_IDEDMA */ +#define ALI_INIT_CODE_TEST + unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name) { unsigned long fixdma_base = pci_resource_start(dev, 4); +#ifdef ALI_INIT_CODE_TEST + unsigned long flags; + byte tmpbyte; +#endif /* ALI_INIT_CODE_TEST */ + pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision); isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); @@ -535,6 +543,55 @@ } #endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ +#ifdef ALI_INIT_CODE_TEST + local_irq_save(flags); + + if (m5229_revision >= 0xC2) { + /* + * 1543C-B?, 1535, 1535D, 1553 + * Note 1: not all "motherboard" support this detection + * Note 2: if no udma 66 device, the detection may "error". + * but in this case, we will not set the device to + * ultra 66, the detection result is not important + */ + + /* + * enable "Cable Detection", m5229, 0x4b, bit3 + */ + pci_read_config_byte(dev, 0x4b, &tmpbyte); + pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08); + + /* + * set south-bridge's enable bit, m1533, 0x79 + */ + pci_read_config_byte(isa_dev, 0x79, &tmpbyte); + if (m5229_revision == 0xC2) { + /* + * 1543C-B0 (m1533, 0x79, bit 2) + */ + pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04); + } else if (m5229_revision >= 0xC3) { + /* + * 1553/1535 (m1533, 0x79, bit 1) + */ + pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); + } + } else { + /* + * revision 0x20 (1543-E, 1543-F) + * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) + * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7 + */ + pci_read_config_byte(dev, 0x4b, &tmpbyte); + /* + * clear bit 7 + */ + pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); + } + + local_irq_save(flags); +#endif /* ALI_INIT_CODE_TEST */ + return 0; } @@ -552,10 +609,10 @@ unsigned long flags; byte tmpbyte; - __save_flags(flags); - __cli(); + local_irq_save(flags); if (m5229_revision >= 0xC2) { +#ifndef ALI_INIT_CODE_TEST /* * 1543C-B?, 1535, 1535D, 1553 * Note 1: not all "motherboard" support this detection @@ -585,6 +642,7 @@ */ pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); } +#endif /* ALI_INIT_CODE_TEST */ /* * Ultra66 cable detection (from Host View) * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin @@ -605,6 +663,7 @@ */ ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0]; } else { +#ifndef ALI_INIT_CODE_TEST /* * revision 0x20 (1543-E, 1543-F) * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E) @@ -615,6 +674,7 @@ * clear bit 7 */ pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); +#endif /* ALI_INIT_CODE_TEST */ /* * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 */ @@ -633,7 +693,7 @@ pci_write_config_byte(dev, 0x53, tmpbyte); - __restore_flags(flags); + local_irq_restore(flags); return(ata66); } diff -urN linux-2.4.19-p7-pristine/drivers/ide/amd74xx.c linux-2.4.19-p7/drivers/ide/amd74xx.c --- linux-2.4.19-p7-pristine/drivers/ide/amd74xx.c Tue Apr 16 03:15:15 2002 +++ linux-2.4.19-p7/drivers/ide/amd74xx.c Tue Apr 16 23:16:56 2002 @@ -34,7 +34,6 @@ static int amd74xx_get_info(char *, char **, off_t, int); extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int amd74xx_get_info (char *buffer, char **addr, off_t offset, int count) @@ -69,8 +68,6 @@ byte amd74xx_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); - static unsigned int amd74xx_swdma_check (struct pci_dev *dev) { unsigned int class_rev; @@ -345,6 +342,9 @@ { struct hd_driveid *id = drive->id; ide_dma_action_t dma_func = ide_dma_on; + + config_chipset_for_pio(drive); + drive->init_speed = 0; if (id && (id->capability & 1) && HWIF(drive)->autodma) { /* Consult the list of known "bad" drives */ diff -urN linux-2.4.19-p7-pristine/drivers/ide/cmd640.c linux-2.4.19-p7/drivers/ide/cmd640.c --- linux-2.4.19-p7-pristine/drivers/ide/cmd640.c Fri Feb 16 16:02:36 2001 +++ linux-2.4.19-p7/drivers/ide/cmd640.c Tue Apr 16 23:16:56 2002 @@ -217,11 +217,10 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); outl_p((reg & 0xfc) | cmd640_key, 0xcf8); outb_p(val, (reg & 3) | 0xcfc); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } static byte get_cmd640_reg_pci1 (unsigned short reg) @@ -229,11 +228,10 @@ byte b; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); outl_p((reg & 0xfc) | cmd640_key, 0xcf8); b = inb_p((reg & 3) | 0xcfc); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return b; } @@ -243,12 +241,11 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); outb_p(0x10, 0xcf8); outb_p(val, cmd640_key + reg); outb_p(0, 0xcf8); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } static byte get_cmd640_reg_pci2 (unsigned short reg) @@ -256,12 +253,11 @@ byte b; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); outb_p(0x10, 0xcf8); b = inb_p(cmd640_key + reg); outb_p(0, 0xcf8); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return b; } @@ -271,11 +267,10 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); outb_p(reg, cmd640_key); outb_p(val, cmd640_key + 4); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } static byte get_cmd640_reg_vlb (unsigned short reg) @@ -283,11 +278,10 @@ byte b; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); outb_p(reg, cmd640_key); b = inb_p(cmd640_key + 4); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return b; } @@ -364,8 +358,7 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ udelay(100); @@ -373,11 +366,11 @@ outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ udelay(100); if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) { - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return 0; /* nothing responded */ } } - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return 1; /* success */ } @@ -458,8 +451,7 @@ byte b; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); b = get_cmd640_reg(reg); if (mode) { /* want prefetch on? */ #if CMD640_PREFETCH_MASKS @@ -475,7 +467,7 @@ b |= prefetch_masks[index]; /* disable prefetch */ } put_cmd640_reg(reg, b); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -576,8 +568,7 @@ /* * Now that everything is ready, program the new timings */ - save_flags (flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); /* * Program the address_setup clocks into ARTTIM reg, * and then the active/recovery counts into the DRWTIM reg @@ -586,7 +577,7 @@ setup_count |= get_cmd640_reg(arttim_regs[index]) & 0x3f; put_cmd640_reg(arttim_regs[index], setup_count); put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -692,6 +683,41 @@ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ +static int pci_conf1(void) +{ + u32 tmp; + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); + outb(0x01, 0xCFB); + tmp = inl(0xCF8); + outl(0x80000000, 0xCF8); + if (inl(0xCF8) == 0x80000000) { + outl(tmp, 0xCF8); + spin_unlock_irqrestore(&io_request_lock, flags); + return 1; + } + outl(tmp, 0xCF8); + spin_unlock_irqrestore(&io_request_lock, flags); + return 0; +} + +static int pci_conf2(void) +{ + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); + outb(0x00, 0xCFB); + outb(0x00, 0xCF8); + outb(0x00, 0xCFA); + if (inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00) { + spin_unlock_irqrestore(&io_request_lock, flags); + return 1; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return 0; +} + /* * Probe for a cmd640 chipset, and initialize it if found. Called from ide.c */ @@ -709,9 +735,11 @@ bus_type = "VLB"; } else { cmd640_vlb = 0; - if (probe_for_cmd640_pci1()) + /* Find out what kind of PCI probing is supported otherwise + Justin Gibbs will sulk.. */ + if (pci_conf1() && probe_for_cmd640_pci1()) bus_type = "PCI (type1)"; - else if (probe_for_cmd640_pci2()) + else if (pci_conf2() && probe_for_cmd640_pci2()) bus_type = "PCI (type2)"; else return 0; diff -urN linux-2.4.19-p7-pristine/drivers/ide/cmd64x.c linux-2.4.19-p7/drivers/ide/cmd64x.c --- linux-2.4.19-p7-pristine/drivers/ide/cmd64x.c Tue Apr 16 03:15:15 2002 +++ linux-2.4.19-p7/drivers/ide/cmd64x.c Tue Apr 16 23:16:56 2002 @@ -8,9 +8,10 @@ * Due to massive hardware bugs, UltraDMA is only supported * on the 646U2 and not on the 646U. * - * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) - * Copyright (C) 1998 David S. Miller (davem@redhat.com) - * Copyright (C) 1999-2000 Andre Hedrick + * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) + * Copyright (C) 1998 David S. Miller (davem@redhat.com) + * + * Copyright (C) 1999-2002 Andre Hedrick */ #include @@ -32,7 +33,7 @@ #define CMD_DEBUG 0 #if CMD_DEBUG -#define cmdprintk(x...) printk(##x) +#define cmdprintk(x...) printk(x) #else #define cmdprintk(x...) #endif @@ -85,82 +86,97 @@ #include #include +static char * print_cmd64x_get_info(char *, struct pci_dev *, int); +static char * print_sii_get_info(char *, struct pci_dev *, int); static int cmd64x_get_info(char *, char **, off_t, int); -static int cmd680_get_info(char *, char **, off_t, int); extern int (*cmd64x_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; -static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) +byte cmd64x_proc = 0; + +#define CMD_MAX_DEVS 5 + +static struct pci_dev *cmd_devs[CMD_MAX_DEVS]; +static int n_cmd_devs; + +#undef DEBUG_CMD_REGS + +static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index) { - char *p = buffer; + char *p = buf; + u8 reg53 = 0, reg54 = 0, reg55 = 0, reg56 = 0; /* primary */ u8 reg57 = 0, reg58 = 0, reg5b; /* secondary */ u8 reg72 = 0, reg73 = 0; /* primary */ u8 reg7a = 0, reg7b = 0; /* secondary */ u8 reg50 = 0, reg71 = 0; /* extra */ +#ifdef DEBUG_CMD_REGS u8 hi_byte = 0, lo_byte = 0; +#endif /* DEBUG_CMD_REGS */ - switch(bmide_dev->device) { - case PCI_DEVICE_ID_CMD_649: - p += sprintf(p, "\n CMD649 Chipset.\n"); - break; - case PCI_DEVICE_ID_CMD_648: - p += sprintf(p, "\n CMD648 Chipset.\n"); - break; - case PCI_DEVICE_ID_CMD_646: - p += sprintf(p, "\n CMD646 Chipset.\n"); - break; - case PCI_DEVICE_ID_CMD_643: - p += sprintf(p, "\n CMD643 Chipset.\n"); - break; - default: - p += sprintf(p, "\n CMD64? Chipse.\n"); - break; - } - (void) pci_read_config_byte(bmide_dev, CFR, ®50); - (void) pci_read_config_byte(bmide_dev, ARTTIM0, ®53); - (void) pci_read_config_byte(bmide_dev, DRWTIM0, ®54); - (void) pci_read_config_byte(bmide_dev, ARTTIM1, ®55); - (void) pci_read_config_byte(bmide_dev, DRWTIM1, ®56); - (void) pci_read_config_byte(bmide_dev, ARTTIM2, ®57); - (void) pci_read_config_byte(bmide_dev, DRWTIM2, ®58); - (void) pci_read_config_byte(bmide_dev, DRWTIM3, ®5b); - (void) pci_read_config_byte(bmide_dev, MRDMODE, ®71); - (void) pci_read_config_byte(bmide_dev, BMIDESR0, ®72); - (void) pci_read_config_byte(bmide_dev, UDIDETCR0, ®73); - (void) pci_read_config_byte(bmide_dev, BMIDESR1, ®7a); - (void) pci_read_config_byte(bmide_dev, UDIDETCR1, ®7b); - - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (reg72&0x80)?"dis":" en",(reg7a&0x80)?"dis":" en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", - (reg72&0x20)?"yes":"no ",(reg72&0x40)?"yes":"no ",(reg7a&0x20)?"yes":"no ",(reg7a&0x40)?"yes":"no "); - p += sprintf(p, "DMA Mode: %s(%s) %s(%s) %s(%s) %s(%s)\n", + p += sprintf(p, "\nController: %d\n", index); + p += sprintf(p, "CMD%x Chipset.\n", dev->device); + (void) pci_read_config_byte(dev, CFR, ®50); + (void) pci_read_config_byte(dev, ARTTIM0, ®53); + (void) pci_read_config_byte(dev, DRWTIM0, ®54); + (void) pci_read_config_byte(dev, ARTTIM1, ®55); + (void) pci_read_config_byte(dev, DRWTIM1, ®56); + (void) pci_read_config_byte(dev, ARTTIM2, ®57); + (void) pci_read_config_byte(dev, DRWTIM2, ®58); + (void) pci_read_config_byte(dev, DRWTIM3, ®5b); + (void) pci_read_config_byte(dev, MRDMODE, ®71); + (void) pci_read_config_byte(dev, BMIDESR0, ®72); + (void) pci_read_config_byte(dev, UDIDETCR0, ®73); + (void) pci_read_config_byte(dev, BMIDESR1, ®7a); + (void) pci_read_config_byte(dev, UDIDETCR1, ®7b); + + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled " + " %sabled\n", + (reg72&0x80)?"dis":" en", + (reg7a&0x80)?"dis":" en"); + p += sprintf(p, "--------------- drive0 " + "--------- drive1 -------- drive0 " + "---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s" + " %s %s\n", + (reg72&0x20)?"yes":"no ", (reg72&0x40)?"yes":"no ", + (reg7a&0x20)?"yes":"no ", (reg7a&0x40)?"yes":"no "); + + p += sprintf(p, "DMA Mode: %s(%s) %s(%s)", (reg72&0x20)?((reg73&0x01)?"UDMA":" DMA"):" PIO", - (reg72&0x20)?( ((reg73&0x30)==0x30)?(((reg73&0x35)==0x35)?"3":"0"): - ((reg73&0x20)==0x20)?(((reg73&0x25)==0x25)?"3":"1"): - ((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"): - ((reg73&0x00)==0x00)?(((reg73&0x05)==0x05)?"5":"2"):"X"):"?", + (reg72&0x20)?( + ((reg73&0x30)==0x30)?(((reg73&0x35)==0x35)?"3":"0"): + ((reg73&0x20)==0x20)?(((reg73&0x25)==0x25)?"3":"1"): + ((reg73&0x10)==0x10)?(((reg73&0x15)==0x15)?"4":"2"): + ((reg73&0x00)==0x00)?(((reg73&0x05)==0x05)?"5":"2"): + "X"):"?", (reg72&0x40)?((reg73&0x02)?"UDMA":" DMA"):" PIO", - (reg72&0x40)?( ((reg73&0xC0)==0xC0)?(((reg73&0xC5)==0xC5)?"3":"0"): - ((reg73&0x80)==0x80)?(((reg73&0x85)==0x85)?"3":"1"): - ((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"): - ((reg73&0x00)==0x00)?(((reg73&0x0A)==0x0A)?"5":"2"):"X"):"?", + (reg72&0x40)?( + ((reg73&0xC0)==0xC0)?(((reg73&0xC5)==0xC5)?"3":"0"): + ((reg73&0x80)==0x80)?(((reg73&0x85)==0x85)?"3":"1"): + ((reg73&0x40)==0x40)?(((reg73&0x4A)==0x4A)?"4":"2"): + ((reg73&0x00)==0x00)?(((reg73&0x0A)==0x0A)?"5":"2"): + "X"):"?"); + p += sprintf(p, " %s(%s) %s(%s)\n", (reg7a&0x20)?((reg7b&0x01)?"UDMA":" DMA"):" PIO", - (reg7a&0x20)?( ((reg7b&0x30)==0x30)?(((reg7b&0x35)==0x35)?"3":"0"): - ((reg7b&0x20)==0x20)?(((reg7b&0x25)==0x25)?"3":"1"): - ((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"): - ((reg7b&0x00)==0x00)?(((reg7b&0x05)==0x05)?"5":"2"):"X"):"?", + (reg7a&0x20)?( + ((reg7b&0x30)==0x30)?(((reg7b&0x35)==0x35)?"3":"0"): + ((reg7b&0x20)==0x20)?(((reg7b&0x25)==0x25)?"3":"1"): + ((reg7b&0x10)==0x10)?(((reg7b&0x15)==0x15)?"4":"2"): + ((reg7b&0x00)==0x00)?(((reg7b&0x05)==0x05)?"5":"2"): + "X"):"?", (reg7a&0x40)?((reg7b&0x02)?"UDMA":" DMA"):" PIO", - (reg7a&0x40)?( ((reg7b&0xC0)==0xC0)?(((reg7b&0xC5)==0xC5)?"3":"0"): - ((reg7b&0x80)==0x80)?(((reg7b&0x85)==0x85)?"3":"1"): - ((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"): - ((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"):"X"):"?" ); - p += sprintf(p, "PIO Mode: %s %s %s %s\n", - "?", "?", "?", "?"); + (reg7a&0x40)?( + ((reg7b&0xC0)==0xC0)?(((reg7b&0xC5)==0xC5)?"3":"0"): + ((reg7b&0x80)==0x80)?(((reg7b&0x85)==0x85)?"3":"1"): + ((reg7b&0x40)==0x40)?(((reg7b&0x4A)==0x4A)?"4":"2"): + ((reg7b&0x00)==0x00)?(((reg7b&0x0A)==0x0A)?"5":"2"): + "X"):"?" ); + p += sprintf(p, "PIO Mode: %s %s" + " %s %s\n", + "?", "?", "?", "?"); p += sprintf(p, " %s %s\n", (reg50 & CFR_INTR_CH0) ? "interrupting" : "polling ", (reg57 & ARTTIM23_INTR_CH1) ? "interrupting" : "polling"); @@ -171,32 +187,58 @@ (reg71 & MRDMODE_BLK_CH0) ? "blocked" : "enabled", (reg71 & MRDMODE_BLK_CH1) ? "blocked" : "enabled"); +#ifdef DEBUG_CMD_REGS SPLIT_BYTE(reg50, hi_byte, lo_byte); - p += sprintf(p, "CFR = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg50, hi_byte, lo_byte); + p += sprintf(p, "CFR = 0x%02x, HI = 0x%02x, " + "LOW = 0x%02x\n", reg50, hi_byte, lo_byte); SPLIT_BYTE(reg57, hi_byte, lo_byte); - p += sprintf(p, "ARTTIM23 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg57, hi_byte, lo_byte); + p += sprintf(p, "ARTTIM23 = 0x%02x, HI = 0x%02x, " + "LOW = 0x%02x\n", reg57, hi_byte, lo_byte); SPLIT_BYTE(reg71, hi_byte, lo_byte); - p += sprintf(p, "MRDMODE = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg71, hi_byte, lo_byte); + p += sprintf(p, "MRDMODE = 0x%02x, HI = 0x%02x, " + "LOW = 0x%02x\n", reg71, hi_byte, lo_byte); +#endif /* DEBUG_CMD_REGS */ - return p-buffer; /* => must be less than 4k! */ + return (char *)p; } -static int cmd680_get_info (char *buffer, char **addr, off_t offset, int count) +static char * print_sii_get_info (char *buf, struct pci_dev *dev, int index) +{ + char *p = buf; + + p += sprintf(p, "\nController: %d\n", index); + p += sprintf(p, "SII%x Chipset.\n", dev->device); + + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "PIO Mode: %s %s" + " %s %s\n", + "?", "?", "?", "?"); + return (char *)p; +} + +static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - p += sprintf(p, "\n CMD680 Chipset.\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "PIO Mode: %s %s %s %s\n", - "?", "?", "?", "?"); + int i; + + p += sprintf(p, "\n"); + for (i = 0; i < n_cmd_devs; i++) { + struct pci_dev *dev = cmd_devs[i]; + + if (dev->device <= PCI_DEVICE_ID_CMD_649) + p = print_cmd64x_get_info(p, dev, i); + else + p = print_sii_get_info(p, dev, i); + } return p-buffer; /* => must be less than 4k! */ } #endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ -byte cmd64x_proc = 0; -byte cmd680_proc = 0; - /* * Registers and masks for easy access by drive index: */ @@ -255,8 +297,7 @@ /* * Now that everything is ready, program the new timings */ - __save_flags (flags); - __cli(); + local_irq_save(flags); /* * Program the address_setup clocks into ARTTIM reg, * and then the active/recovery counts into the DRWTIM reg @@ -268,7 +309,7 @@ (byte) ((active_count << 4) | recovery_count)); cmdprintk ("Write %x to %x\n", ((byte) setup_count) | (temp_b & 0x3f), arttim_regs[channel][slave]); cmdprintk ("Write %x to %x\n", (byte) ((active_count << 4) | recovery_count), drwtim_regs[channel][slave]); - __restore_flags(flags); + local_irq_restore(flags); } /* @@ -430,11 +471,14 @@ static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed) { - if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_CMD_680) { - config_cmd680_chipset_for_pio(drive, set_speed); - } else { - config_cmd64x_chipset_for_pio(drive, set_speed); + switch(HWIF(drive)->pci_dev->device) { + case PCI_DEVICE_ID_CMD_680: + config_cmd680_chipset_for_pio(drive, set_speed); + return; + default: + break; } + config_cmd64x_chipset_for_pio(drive, set_speed); } static int cmd64x_tune_chipset (ide_drive_t *drive, byte speed) @@ -450,7 +494,8 @@ u8 regU = 0; u8 regD = 0; - if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return 1; + if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) + return 1; (void) pci_read_config_byte(dev, pciD, ®D); (void) pci_read_config_byte(dev, pciU, ®U); @@ -538,6 +583,11 @@ if ((speed == XFER_UDMA_6) && (scsc & 0x30) == 0x00) { pci_write_config_byte(dev, 0x8A, scsc|0x01); pci_read_config_byte(dev, 0x8A, &scsc); +#if 0 + /* if 133 clock fails, switch to 2xbus clock */ + if (!(scsc & 0x01)) + pci_write_config_byte(dev, 0x8A, scsc|0x10); +#endif } switch(speed) { @@ -750,8 +800,12 @@ static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66) { - if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_CMD_680) - return (config_cmd680_chipset_for_dma(drive)); + switch(HWIF(drive)->pci_dev->device) { + case PCI_DEVICE_ID_CMD_680: + return (config_cmd680_chipset_for_dma(drive)); + default: + break; + } return (config_cmd64x_chipset_for_dma(drive, rev, ultra_66)); } @@ -846,6 +900,18 @@ return ide_dmaproc(func, drive); } +static int cmd64x_alt_dma_status (struct pci_dev *dev) +{ + switch(dev->device) { + case PCI_DEVICE_ID_CMD_648: + case PCI_DEVICE_ID_CMD_649: + return 1; + default: + break; + } + return 0; +} + static int cmd64x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { byte dma_stat = 0; @@ -853,40 +919,44 @@ byte mask = (HWIF(drive)->channel) ? MRDMODE_INTR_CH1 : MRDMODE_INTR_CH0; unsigned long dma_base = HWIF(drive)->dma_base; struct pci_dev *dev = HWIF(drive)->pci_dev; - byte jack_slap = ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0; + byte alt_dma_stat = cmd64x_alt_dma_status(dev); switch (func) { case ide_dma_check: return cmd64x_config_drive_for_dma(drive); case ide_dma_end: /* returns 1 on error, 0 otherwise */ drive->waiting_for_dma = 0; - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - if (jack_slap) { + /* stop DMA */ + outb(inb(dma_base)&~1, dma_base); + /* get DMA status */ + dma_stat = inb(dma_base+2); + /* clear the INTR & ERROR bits */ + outb(dma_stat|6, dma_base+2); + if (alt_dma_stat) { byte dma_intr = 0; byte dma_mask = (HWIF(drive)->channel) ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; byte dma_reg = (HWIF(drive)->channel) ? ARTTIM2 : CFR; (void) pci_read_config_byte(dev, dma_reg, &dma_intr); - /* - * DAMN BMIDE is not connected to PCI space! - * Have to manually jack-slap that bitch! - * To allow the PCI side to read incoming interrupts. - */ - (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); /* clear the INTR bit */ + /* clear the INTR bit */ + (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); } - ide_destroy_dmatable(drive); /* purge DMA mappings */ - return (dma_stat & 7) != 4; /* verify good DMA status */ + /* purge DMA mappings */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4; case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ dma_stat = inb(dma_base+2); (void) pci_read_config_byte(dev, MRDMODE, &dma_alt_stat); #ifdef DEBUG - printk("%s: dma_stat: 0x%02x dma_alt_stat: 0x%02x mask: 0x%02x\n", drive->name, dma_stat, dma_alt_stat, mask); + printk("%s: dma_stat: 0x%02x dma_alt_stat: " + "0x%02x mask: 0x%02x\n", drive->name, + dma_stat, dma_alt_stat, mask); #endif if (!(dma_alt_stat & mask)) { return 0; } - return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ + /* return 1 if INTR asserted */ + return (dma_stat & 4) == 4; default: break; } @@ -909,11 +979,16 @@ return cmd64x_config_drive_for_dma(drive); case ide_dma_end: drive->waiting_for_dma = 0; - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - ide_destroy_dmatable(drive); /* and free any DMA resources */ - return (dma_stat & 7) != 4; /* verify good DMA status */ + /* get DMA status */ + dma_stat = inb(dma_base+2); + /* stop DMA */ + outb(inb(dma_base)&~1, dma_base); + /* clear the INTR & ERROR bits */ + outb(dma_stat|6, dma_base+2); + /* and free any DMA resources */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4; default: break; } @@ -975,6 +1050,13 @@ pci_write_config_byte(dev, 0x84, 0x00); pci_read_config_byte(dev, 0x8A, &tmpbyte); pci_write_config_byte(dev, 0x8A, tmpbyte|0x01); +#if 0 + /* if 133 clock fails, switch to 2xbus clock */ + if (!(tmpbyte & 0x01)) { + pci_read_config_byte(dev, 0x8A, &tmpbyte); + pci_write_config_byte(dev, 0x8A, tmpbyte|0x10); + } +#endif pci_write_config_word(dev, 0xA2, 0x328A); pci_write_config_dword(dev, 0xA4, 0x328A); pci_write_config_dword(dev, 0xA8, 0x4392); @@ -984,13 +1066,15 @@ pci_write_config_dword(dev, 0xB8, 0x4392); pci_write_config_dword(dev, 0xBC, 0x4009); + cmd_devs[n_cmd_devs++] = dev; + #if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) if (!cmd64x_proc) { cmd64x_proc = 1; - bmide_dev = dev; - cmd64x_display_info = &cmd680_get_info; + cmd64x_display_info = &cmd64x_get_info; } #endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ + return 0; } @@ -1072,10 +1156,11 @@ (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0); #endif /* CONFIG_PPC */ + cmd_devs[n_cmd_devs++] = dev; + #if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) if (!cmd64x_proc) { cmd64x_proc = 1; - bmide_dev = dev; cmd64x_display_info = &cmd64x_get_info; } #endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ @@ -1085,8 +1170,12 @@ unsigned int __init pci_init_cmd64x (struct pci_dev *dev, const char *name) { - if (dev->device == PCI_DEVICE_ID_CMD_680) - return cmd680_pci_init (dev, name); + switch(dev->device) { + case PCI_DEVICE_ID_CMD_680: + return cmd680_pci_init (dev, name); + default: + break; + } return cmd64x_pci_init (dev, name); } @@ -1110,9 +1199,12 @@ unsigned int __init ata66_cmd64x (ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; - if (dev->device == PCI_DEVICE_ID_CMD_680) - return cmd680_ata66(hwif); + switch(hwif->pci_dev->device) { + case PCI_DEVICE_ID_CMD_680: + return cmd680_ata66(hwif); + default: + break; + } return cmd64x_ata66(hwif); } diff -urN linux-2.4.19-p7-pristine/drivers/ide/cs5530.c linux-2.4.19-p7/drivers/ide/cs5530.c --- linux-2.4.19-p7-pristine/drivers/ide/cs5530.c Tue Jan 2 16:58:45 2001 +++ linux-2.4.19-p7/drivers/ide/cs5530.c Tue Apr 16 23:16:56 2002 @@ -37,7 +37,6 @@ static int cs5530_get_info(char *, char **, off_t, int); extern int (*cs5530_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int cs5530_get_info (char *buffer, char **addr, off_t offset, int count) @@ -74,8 +73,6 @@ byte cs5530_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); - /* * Set a new transfer mode at the drive */ @@ -286,8 +283,8 @@ return 0; } - save_flags(flags); - cli(); /* all CPUs (there should only be one CPU with this chipset) */ + spin_lock_irqsave(&io_request_lock, flags); + /* all CPUs (there should only be one CPU with this chipset) */ /* * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530: @@ -333,7 +330,7 @@ pci_write_config_byte(master_0, 0x42, 0x00); pci_write_config_byte(master_0, 0x43, 0xc1); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return 0; } diff -urN linux-2.4.19-p7-pristine/drivers/ide/cy82c693.c linux-2.4.19-p7/drivers/ide/cy82c693.c --- linux-2.4.19-p7-pristine/drivers/ide/cy82c693.c Sat May 19 17:43:06 2001 +++ linux-2.4.19-p7/drivers/ide/cy82c693.c Sat Apr 20 01:21:17 2002 @@ -447,3 +447,17 @@ } #endif /* CONFIG_BLK_DEV_IDEDMA */ } + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init cy82c693_device_fixup (struct pci_dev *dev, ide_pci_device_t *d) +{ + if ((!(PCI_FUNC(dev->devfn) & 1) || + (!((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))) + return; /* CY82C693 is more than only a IDE controller */ + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} + diff -urN linux-2.4.19-p7-pristine/drivers/ide/dtc2278.c linux-2.4.19-p7/drivers/ide/dtc2278.c --- linux-2.4.19-p7-pristine/drivers/ide/dtc2278.c Thu Apr 13 22:54:26 2000 +++ linux-2.4.19-p7/drivers/ide/dtc2278.c Tue Apr 16 23:16:57 2002 @@ -77,14 +77,13 @@ pio = ide_get_best_pio_mode(drive, pio, 4, NULL); if (pio >= 3) { - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); /* * This enables PIO mode4 (3?) on the first interface */ sub22(1,0xc3); sub22(0,0xa0); - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); } else { /* we don't know how to set it back again.. */ } @@ -100,8 +99,7 @@ { unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); /* * This enables the second interface */ @@ -117,7 +115,7 @@ sub22(1,0xc3); sub22(0,0xa0); #endif - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); ide_hwifs[0].serialized = 1; ide_hwifs[1].serialized = 1; diff -urN linux-2.4.19-p7-pristine/drivers/ide/hd.c linux-2.4.19-p7/drivers/ide/hd.c --- linux-2.4.19-p7-pristine/drivers/ide/hd.c Mon Oct 15 13:27:42 2001 +++ linux-2.4.19-p7/drivers/ide/hd.c Tue Apr 16 23:16:57 2002 @@ -135,13 +135,12 @@ unsigned long t, flags; int i; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); t = jiffies * 11932; outb_p(0, 0x43); i = inb_p(0x40); i |= inb(0x40) << 8; - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return(t - i); } #endif @@ -876,14 +875,13 @@ target = DEVICE_NR(dev); gdev = &GENDISK_STRUCT; - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); if (DEVICE_BUSY || USAGE > maxusage) { - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); return -EBUSY; } DEVICE_BUSY = 1; - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); max_p = gdev->max_p; start = target << gdev->minor_shift; diff -urN linux-2.4.19-p7-pristine/drivers/ide/hpt34x.c linux-2.4.19-p7/drivers/ide/hpt34x.c --- linux-2.4.19-p7-pristine/drivers/ide/hpt34x.c Sat May 19 17:43:06 2001 +++ linux-2.4.19-p7/drivers/ide/hpt34x.c Fri Apr 19 14:01:04 2002 @@ -56,7 +56,6 @@ static int hpt34x_get_info(char *, char **, off_t, int); extern int (*hpt34x_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count) @@ -92,8 +91,6 @@ byte hpt34x_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); - static void hpt34x_clear_chipset (ide_drive_t *drive) { unsigned int reg1 = 0, tmp1 = 0; @@ -255,6 +252,9 @@ struct hd_driveid *id = drive->id; ide_dma_action_t dma_func = ide_dma_on; + config_chipset_for_pio(drive); + drive->init_speed = 0; + if (id && (id->capability & 1) && HWIF(drive)->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { @@ -335,9 +335,30 @@ drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ - OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - return 0; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); + /* issue cmd to drive */ + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } +#else + if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && + (drive->addressing == 1)) { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } else if (drive->addressing) { + OUT_BYTE((reading == 9) ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); + } else { + OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); + } +#endif + return HWIF(drive)->dmaproc(ide_dma_begin, drive); case ide_dma_end: /* returns 1 on error, 0 otherwise */ drive->waiting_for_dma = 0; outb(inb(dma_base)&~1, dma_base); /* stop DMA */ @@ -364,8 +385,7 @@ unsigned short cmd; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00); pci_read_config_word(dev, PCI_COMMAND, &cmd); @@ -396,7 +416,7 @@ pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->resource[3].start); pci_write_config_word(dev, PCI_COMMAND, cmd); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); #if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) if (!hpt34x_proc) { @@ -434,4 +454,20 @@ hwif->drives[1].autotune = 1; hwif->autodma = 0; #endif /* CONFIG_BLK_DEV_IDEDMA */ +} + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init hpt343_device_fixup (struct pci_dev *dev, ide_pci_device_t *d) +{ + char *chipset_names[] = {"HPT343", "HPT345"}; + unsigned short pcicmd = 0; + + pci_read_config_word(dev, PCI_COMMAND, &pcicmd); + + strcpy(d->name, chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0]); + d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); } diff -urN linux-2.4.19-p7-pristine/drivers/ide/hpt366.c linux-2.4.19-p7/drivers/ide/hpt366.c --- linux-2.4.19-p7-pristine/drivers/ide/hpt366.c Tue Apr 16 03:15:15 2002 +++ linux-2.4.19-p7/drivers/ide/hpt366.c Mon Apr 22 20:28:33 2002 @@ -1,9 +1,8 @@ /* - * linux/drivers/ide/hpt366.c Version 0.22 20 Sep 2001 + * linux/drivers/ide/hpt366.c Version 0.33 April 17, 2002 * - * Copyright (C) 1999-2000 Andre Hedrick + * Copyright (C) 1999-2002 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. - * May be copied or modified under the terms of the GNU General Public License * * Thanks to HighPoint Technologies for their assistance, and hardware. * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his @@ -42,6 +41,7 @@ * Mike Waychison */ + #include #include #include @@ -67,16 +67,14 @@ /* various tuning parameters */ #define HPT_RESET_STATE_ENGINE -/*#define HPT_DELAY_INTERRUPT*/ -/*#define HPT_SERIALIZE_IO*/ +#undef HPT_DELAY_INTERRUPT +#undef HPT_SERIALIZE_IO #if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) #include #include #endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ -extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc); - const char *quirk_drives[] = { "QUANTUM FIREBALLlct08 08", "QUANTUM FIREBALLP KA6.4", @@ -166,9 +164,8 @@ * PIO. * 31 FIFO enable. */ -struct chipset_bus_clock_list_entry forty_base [] = { - - { XFER_UDMA_4, 0x900fd943 }, +struct chipset_bus_clock_list_entry forty_base_hpt366[] = { + { XFER_UDMA_4, 0x900fd943 }, { XFER_UDMA_3, 0x900ad943 }, { XFER_UDMA_2, 0x900bd943 }, { XFER_UDMA_1, 0x9008d943 }, @@ -186,8 +183,7 @@ { 0, 0x0120d9d9 } }; -struct chipset_bus_clock_list_entry thirty_three_base [] = { - +struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = { { XFER_UDMA_4, 0x90c9a731 }, { XFER_UDMA_3, 0x90cfa731 }, { XFER_UDMA_2, 0x90caa731 }, @@ -206,7 +202,7 @@ { 0, 0x0120a7a7 } }; -struct chipset_bus_clock_list_entry twenty_five_base [] = { +struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = { { XFER_UDMA_4, 0x90c98521 }, { XFER_UDMA_3, 0x90cf8521 }, @@ -226,51 +222,9 @@ { 0, 0x01208585 } }; -#if 1 -/* these are the current (4 sep 2001) timings from highpoint */ -struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { - { XFER_UDMA_5, 0x12446231 }, - { XFER_UDMA_4, 0x12446231 }, - { XFER_UDMA_3, 0x126c6231 }, - { XFER_UDMA_2, 0x12486231 }, - { XFER_UDMA_1, 0x124c6233 }, - { XFER_UDMA_0, 0x12506297 }, - - { XFER_MW_DMA_2, 0x22406c31 }, - { XFER_MW_DMA_1, 0x22406c33 }, - { XFER_MW_DMA_0, 0x22406c97 }, - - { XFER_PIO_4, 0x06414e31 }, - { XFER_PIO_3, 0x06414e42 }, - { XFER_PIO_2, 0x06414e53 }, - { XFER_PIO_1, 0x06814e93 }, - { XFER_PIO_0, 0x06814ea7 }, - { 0, 0x06814ea7 } -}; - -/* 2x 33MHz timings */ -struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = { - { XFER_UDMA_5, 0x1488e673 }, - { XFER_UDMA_4, 0x1488e673 }, - { XFER_UDMA_3, 0x1498e673 }, - { XFER_UDMA_2, 0x1490e673 }, - { XFER_UDMA_1, 0x1498e677 }, - { XFER_UDMA_0, 0x14a0e73f }, - - { XFER_MW_DMA_2, 0x2480fa73 }, - { XFER_MW_DMA_1, 0x2480fa77 }, - { XFER_MW_DMA_0, 0x2480fb3f }, - - { XFER_PIO_4, 0x0c82be73 }, - { XFER_PIO_3, 0x0c82be95 }, - { XFER_PIO_2, 0x0c82beb7 }, - { XFER_PIO_1, 0x0d02bf37 }, - { XFER_PIO_0, 0x0d02bf5f }, - { 0, 0x0d02bf5f } -}; -#else /* from highpoint documentation. these are old values */ struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { +/* { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, */ { XFER_UDMA_5, 0x16454e31 }, { XFER_UDMA_4, 0x16454e31 }, { XFER_UDMA_3, 0x166d4e31 }, @@ -309,9 +263,50 @@ { XFER_PIO_0, 0x06914e57 }, { 0, 0x06514e57 } }; -#endif -struct chipset_bus_clock_list_entry fifty_base_hpt370[] = { +/* these are the current (4 sep 2001) timings from highpoint */ +struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = { + { XFER_UDMA_5, 0x12446231 }, + { XFER_UDMA_4, 0x12446231 }, + { XFER_UDMA_3, 0x126c6231 }, + { XFER_UDMA_2, 0x12486231 }, + { XFER_UDMA_1, 0x124c6233 }, + { XFER_UDMA_0, 0x12506297 }, + + { XFER_MW_DMA_2, 0x22406c31 }, + { XFER_MW_DMA_1, 0x22406c33 }, + { XFER_MW_DMA_0, 0x22406c97 }, + + { XFER_PIO_4, 0x06414e31 }, + { XFER_PIO_3, 0x06414e42 }, + { XFER_PIO_2, 0x06414e53 }, + { XFER_PIO_1, 0x06814e93 }, + { XFER_PIO_0, 0x06814ea7 }, + { 0, 0x06814ea7 } +}; + +/* 2x 33MHz timings */ +struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = { + { XFER_UDMA_5, 0x1488e673 }, + { XFER_UDMA_4, 0x1488e673 }, + { XFER_UDMA_3, 0x1498e673 }, + { XFER_UDMA_2, 0x1490e673 }, + { XFER_UDMA_1, 0x1498e677 }, + { XFER_UDMA_0, 0x14a0e73f }, + + { XFER_MW_DMA_2, 0x2480fa73 }, + { XFER_MW_DMA_1, 0x2480fa77 }, + { XFER_MW_DMA_0, 0x2480fb3f }, + + { XFER_PIO_4, 0x0c82be73 }, + { XFER_PIO_3, 0x0c82be95 }, + { XFER_PIO_2, 0x0c82beb7 }, + { XFER_PIO_1, 0x0d02bf37 }, + { XFER_PIO_0, 0x0d02bf5f }, + { 0, 0x0d02bf5f } +}; + +struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = { { XFER_UDMA_5, 0x12848242 }, { XFER_UDMA_4, 0x12ac8242 }, { XFER_UDMA_3, 0x128c8242 }, @@ -331,6 +326,144 @@ { 0, 0x0ac1f48a } }; +struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = { + { XFER_UDMA_6, 0x1c81dc62 }, + { XFER_UDMA_5, 0x1c6ddc62 }, + { XFER_UDMA_4, 0x1c8ddc62 }, + { XFER_UDMA_3, 0x1c8edc62 }, /* checkme */ + { XFER_UDMA_2, 0x1c91dc62 }, + { XFER_UDMA_1, 0x1c9adc62 }, /* checkme */ + { XFER_UDMA_0, 0x1c82dc62 }, /* checkme */ + + { XFER_MW_DMA_2, 0x2c829262 }, + { XFER_MW_DMA_1, 0x2c829266 }, /* checkme */ + { XFER_MW_DMA_0, 0x2c82922e }, /* checkme */ + + { XFER_PIO_4, 0x0c829c62 }, + { XFER_PIO_3, 0x0c829c84 }, + { XFER_PIO_2, 0x0c829ca6 }, + { XFER_PIO_1, 0x0d029d26 }, + { XFER_PIO_0, 0x0d029d5e }, + { 0, 0x0d029d5e } +}; + +struct chipset_bus_clock_list_entry fifty_base_hpt372[] = { + { XFER_UDMA_5, 0x12848242 }, + { XFER_UDMA_4, 0x12ac8242 }, + { XFER_UDMA_3, 0x128c8242 }, + { XFER_UDMA_2, 0x120c8242 }, + { XFER_UDMA_1, 0x12148254 }, + { XFER_UDMA_0, 0x121882ea }, + + { XFER_MW_DMA_2, 0x22808242 }, + { XFER_MW_DMA_1, 0x22808254 }, + { XFER_MW_DMA_0, 0x228082ea }, + + { XFER_PIO_4, 0x0a81f442 }, + { XFER_PIO_3, 0x0a81f443 }, + { XFER_PIO_2, 0x0a81f454 }, + { XFER_PIO_1, 0x0ac1f465 }, + { XFER_PIO_0, 0x0ac1f48a }, + { 0, 0x0a81f443 } +}; + +struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = { + { XFER_UDMA_6, 0x1c869c62 }, + { XFER_UDMA_5, 0x1cae9c62 }, + { XFER_UDMA_4, 0x1c8a9c62 }, + { XFER_UDMA_3, 0x1c8e9c62 }, + { XFER_UDMA_2, 0x1c929c62 }, + { XFER_UDMA_1, 0x1c9a9c62 }, + { XFER_UDMA_0, 0x1c829c62 }, + + { XFER_MW_DMA_2, 0x2c829c62 }, + { XFER_MW_DMA_1, 0x2c829c66 }, + { XFER_MW_DMA_0, 0x2c829d2e }, + + { XFER_PIO_4, 0x0c829c62 }, + { XFER_PIO_3, 0x0c829c84 }, + { XFER_PIO_2, 0x0c829ca6 }, + { XFER_PIO_1, 0x0d029d26 }, + { XFER_PIO_0, 0x0d029d5e }, + { 0, 0x0d029d26 } +}; + +struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = { + { XFER_UDMA_6, 0x12808242 }, + { XFER_UDMA_5, 0x12848242 }, + { XFER_UDMA_4, 0x12ac8242 }, + { XFER_UDMA_3, 0x128c8242 }, + { XFER_UDMA_2, 0x120c8242 }, + { XFER_UDMA_1, 0x12148254 }, + { XFER_UDMA_0, 0x121882ea }, + + { XFER_MW_DMA_2, 0x22808242 }, + { XFER_MW_DMA_1, 0x22808254 }, + { XFER_MW_DMA_0, 0x228082ea }, + + { XFER_PIO_4, 0x0a81f442 }, + { XFER_PIO_3, 0x0a81f443 }, + { XFER_PIO_2, 0x0a81f454 }, + { XFER_PIO_1, 0x0ac1f465 }, + { XFER_PIO_0, 0x0ac1f48a }, + { 0, 0x06814e93 } +}; + +#if 0 +struct chipset_bus_clock_list_entry fifty_base_hpt374[] = { + { XFER_UDMA_6, }, + { XFER_UDMA_5, }, + { XFER_UDMA_4, }, + { XFER_UDMA_3, }, + { XFER_UDMA_2, }, + { XFER_UDMA_1, }, + { XFER_UDMA_0, }, + { XFER_MW_DMA_2, }, + { XFER_MW_DMA_1, }, + { XFER_MW_DMA_0, }, + { XFER_PIO_4, }, + { XFER_PIO_3, }, + { XFER_PIO_2, }, + { XFER_PIO_1, }, + { XFER_PIO_0, }, + { 0, } +}; +#endif +#if 0 +struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = { + { XFER_UDMA_6, 0x12406231 }, /* checkme */ + { XFER_UDMA_5, 0x12446231 }, + 0x14846231 + { XFER_UDMA_4, 0x16814ea7 }, + 0x14886231 + { XFER_UDMA_3, 0x16814ea7 }, + 0x148c6231 + { XFER_UDMA_2, 0x16814ea7 }, + 0x148c6231 + { XFER_UDMA_1, 0x16814ea7 }, + 0x14906231 + { XFER_UDMA_0, 0x16814ea7 }, + 0x14986231 + { XFER_MW_DMA_2, 0x16814ea7 }, + 0x26514e21 + { XFER_MW_DMA_1, 0x16814ea7 }, + 0x26514e97 + { XFER_MW_DMA_0, 0x16814ea7 }, + 0x26514e97 + { XFER_PIO_4, 0x06814ea7 }, + 0x06514e21 + { XFER_PIO_3, 0x06814ea7 }, + 0x06514e22 + { XFER_PIO_2, 0x06814ea7 }, + 0x06514e33 + { XFER_PIO_1, 0x06814ea7 }, + 0x06914e43 + { XFER_PIO_0, 0x06814ea7 }, + 0x06914e57 + { 0, 0x06814ea7 } +}; +#endif + #define HPT366_DEBUG_DRIVE_INFO 0 #define HPT370_ALLOW_ATA100_5 1 #define HPT366_ALLOW_ATA66_4 1 @@ -345,26 +478,26 @@ static struct pci_dev *hpt_devs[HPT366_MAX_DEVS]; static int n_hpt_devs; -static unsigned int pci_rev_check_hpt3xx(struct pci_dev *dev); -static unsigned int pci_rev2_check_hpt3xx(struct pci_dev *dev); +static unsigned int hpt_minimum_revision(struct pci_dev *dev, int level); + byte hpt366_proc = 0; byte hpt363_shared_irq; byte hpt363_shared_pin; -extern char *ide_xfer_verbose (byte xfer_rate); #if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) static int hpt366_get_info(char *, char **, off_t, int); extern int (*hpt366_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static int hpt366_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - char *chipset_nums[] = {"366", "366", "368", "370", "370A"}; + char *chipset_nums[] = {"366", "366", "368", + "370", "370A", "372", + "??", "374" }; int i; p += sprintf(p, "\n " - "HighPoint HPT366/368/370\n"); + "HighPoint HPT366/368/370/372/374\n"); for (i = 0; i < n_hpt_devs; i++) { struct pci_dev *dev = hpt_devs[i]; unsigned long iobase = dev->resource[4].start; @@ -388,7 +521,7 @@ (c0 & 0x80) ? "no" : "yes", (c1 & 0x80) ? "no" : "yes"); - if (pci_rev_check_hpt3xx(dev)) { + if (hpt_minimum_revision(dev, 3)) { u8 cbl; cbl = inb_p(iobase + 0x7b); outb_p(cbl | 1, iobase + 0x7b); @@ -437,20 +570,26 @@ } #endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ -static unsigned int pci_rev_check_hpt3xx (struct pci_dev *dev) -{ - unsigned int class_rev; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - return ((int) (class_rev > 0x02) ? 1 : 0); -} +/* + * fixme: it really needs to be a switch. + */ -static unsigned int pci_rev2_check_hpt3xx (struct pci_dev *dev) +static unsigned int hpt_minimum_revision (struct pci_dev *dev, int revision) { unsigned int class_rev; pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; - return ((int) (class_rev > 0x01) ? 1 : 0); + revision--; +#if 1 + /* + * Oh the JOY of finding this card !! + */ + if (dev->device == PCI_DEVICE_ID_TTI_HPT372) { + class_rev = (class_rev < 5) ? 5 : class_rev; + } else { + } +#endif + return ((int) (class_rev > revision) ? 1 : 0); } static int check_in_drive_lists (ide_drive_t *drive, const char **list) @@ -484,46 +623,33 @@ static void hpt366_tune_chipset (ide_drive_t *drive, byte speed) { + struct pci_dev *dev = HWIF(drive)->pci_dev; byte regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; - byte regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; - /* - * since the channel is always 0 it does not matter. - */ - unsigned int reg1 = 0; unsigned int reg2 = 0; +#if 0 byte drive_fast = 0; /* - * Disable the "fast interrupt" prediction. + * Disable the "fast interrupt" prediction. */ - pci_read_config_byte(HWIF(drive)->pci_dev, regfast, &drive_fast); - if (drive_fast & 0x02) - pci_write_config_byte(HWIF(drive)->pci_dev, regfast, drive_fast & ~0x20); - - pci_read_config_dword(HWIF(drive)->pci_dev, regtime, ®1); - /* detect bus speed by looking at control reg timing: */ - switch((reg1 >> 8) & 7) { - case 5: - reg2 = pci_bus_clock_list(speed, forty_base); - break; - case 9: - reg2 = pci_bus_clock_list(speed, twenty_five_base); - break; - default: - case 7: - reg2 = pci_bus_clock_list(speed, thirty_three_base); - break; - } + pci_read_config_byte(dev, 0x51, &drive_fast); #if 0 - /* this is a nice idea ... */ - list_conf = pci_bus_clock_list(speed, - (struct chipset_bus_clock_list_entry *) - dev->sysdata); + if (drive_fast & 0x02) + pci_write_config_byte(dev, 0x51, drive_fast & ~0x20); +#else + if (drive_fast & 0x80) + pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); #endif +#endif + + reg2 = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) dev->driver_data); /* - * Disable on-chip PIO FIFO/buffer (to avoid problems handling I/O errors later) + * Disable on-chip PIO FIFO/buffer + * (to avoid problems handling I/O errors later) */ + pci_read_config_dword(dev, regtime, ®1); if (speed >= XFER_MW_DMA_0) { reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000); } else { @@ -531,7 +657,12 @@ } reg2 &= ~0x80000000; - pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2); + pci_write_config_dword(dev, regtime, reg2); +} + +static void hpt368_tune_chipset (ide_drive_t *drive, byte speed) +{ + hpt366_tune_chipset(drive, speed); } static void hpt370_tune_chipset (ide_drive_t *drive, byte speed) @@ -561,11 +692,11 @@ new_fast |= 0x01; #endif if (new_fast != drive_fast) - pci_write_config_byte(HWIF(drive)->pci_dev, regfast, new_fast); + pci_write_config_byte(dev, regfast, new_fast); list_conf = pci_bus_clock_list(speed, (struct chipset_bus_clock_list_entry *) - dev->sysdata); + dev->driver_data); pci_read_config_dword(dev, drive_pci, &drive_conf); list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); @@ -577,19 +708,60 @@ pci_write_config_dword(dev, drive_pci, list_conf); } +static void hpt372_tune_chipset (ide_drive_t *drive, byte speed) +{ + byte regfast = (HWIF(drive)->channel) ? 0x55 : 0x51; + unsigned int list_conf = 0; + unsigned int drive_conf = 0; + unsigned int conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; + byte drive_pci = 0x40 + (drive->dn * 4); + byte drive_fast = 0; + struct pci_dev *dev = HWIF(drive)->pci_dev; + + /* + * Disable the "fast interrupt" prediction. + * don't holdoff on interrupts. (== 0x01 despite what the docs say) + */ + pci_read_config_byte(dev, regfast, &drive_fast); + drive_fast &= ~0x07; + pci_write_config_byte(dev, regfast, drive_fast); + + list_conf = pci_bus_clock_list(speed, + (struct chipset_bus_clock_list_entry *) + dev->driver_data); + pci_read_config_dword(dev, drive_pci, &drive_conf); + list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); + if (speed < XFER_MW_DMA_0) + list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ + pci_write_config_dword(dev, drive_pci, list_conf); +} + +static void hpt374_tune_chipset (ide_drive_t *drive, byte speed) +{ + hpt372_tune_chipset(drive, speed); +} + static int hpt3xx_tune_chipset (ide_drive_t *drive, byte speed) { + struct pci_dev *dev = HWIF(drive)->pci_dev; + if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return -1; if (!drive->init_speed) drive->init_speed = speed; - if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) { + if (hpt_minimum_revision(dev, 7)) + hpt374_tune_chipset(drive, speed); + else if (hpt_minimum_revision(dev, 5)) + hpt372_tune_chipset(drive, speed); + else if (hpt_minimum_revision(dev, 3)) hpt370_tune_chipset(drive, speed); - } else { + else if (hpt_minimum_revision(dev, 2)) + hpt368_tune_chipset(drive, speed); + else hpt366_tune_chipset(drive, speed); - } + drive->current_speed = speed; return ((int) ide_config_drive_speed(drive, speed)); } @@ -659,18 +831,32 @@ */ static int config_chipset_for_dma (ide_drive_t *drive) { + struct pci_dev *dev = HWIF(drive)->pci_dev; struct hd_driveid *id = drive->id; byte speed = 0x00; byte ultra66 = eighty_ninty_three(drive); int rval; + config_chipset_for_pio(drive); + drive->init_speed = 0; + if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return ((int) ide_dma_off_quietly); +#if 0 + if ((id->dma_ultra & 0x0040) && + (hpt_minimum_revision(dev,5)) && + (ultra66)) { + speed = XFER_UDMA_6; + if (hpt_minimum_revision(dev,7)) + speed = XFER_UDMA_5; + } else if ((id->dma_ultra & 0x0020) && +#else if ((id->dma_ultra & 0x0020) && +#endif (!check_in_drive_lists(drive, bad_ata100_5)) && (HPT370_ALLOW_ATA100_5) && - (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) && + (hpt_minimum_revision(dev,3)) && (ultra66)) { speed = XFER_UDMA_5; } else if ((id->dma_ultra & 0x0010) && @@ -703,7 +889,8 @@ (void) hpt3xx_tune_chipset(drive, speed); - rval = (int)( ((id->dma_ultra >> 11) & 7) ? ide_dma_on : + rval = (int)( ((id->dma_ultra >> 14) & 3) ? ide_dma_on : + ((id->dma_ultra >> 11) & 7) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : ide_dma_off_quietly); @@ -717,21 +904,22 @@ void hpt3xx_intrproc (ide_drive_t *drive) { - if (drive->quirk_list) { - /* drives in the quirk_list may not like intr setups/cleanups */ - } else { - OUT_BYTE((drive)->ctl|2, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]); - } + if (drive->quirk_list) + return; + /* drives in the quirk_list may not like intr setups/cleanups */ + OUT_BYTE((drive)->ctl|2, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]); } void hpt3xx_maskproc (ide_drive_t *drive, int mask) { + struct pci_dev *dev = HWIF(drive)->pci_dev; + if (drive->quirk_list) { - if (pci_rev_check_hpt3xx(HWIF(drive)->pci_dev)) { + if (hpt_minimum_revision(dev,3)) { byte reg5a = 0; - pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, ®5a); + pci_read_config_byte(dev, 0x5a, ®5a); if (((reg5a & 0x10) >> 4) != mask) - pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); + pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); } else { if (mask) { disable_irq(HWIF(drive)->irq); @@ -758,7 +946,7 @@ } dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { - if (id->dma_ultra & 0x002F) { + if (id->dma_ultra & 0x007F) { /* Force if Capable UltraDMA */ dma_func = config_chipset_for_dma(drive); if ((id->field_valid & 2) && @@ -802,8 +990,9 @@ */ int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { + struct pci_dev *dev = HWIF(drive)->pci_dev; + unsigned long dma_base = HWIF(drive)->dma_base; byte reg50h = 0, reg52h = 0, reg5ah = 0, dma_stat = 0; - unsigned long dma_base = HWIF(drive)->dma_base; switch (func) { case ide_dma_check: @@ -812,21 +1001,24 @@ dma_stat = inb(dma_base+2); return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ case ide_dma_lostirq: - pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, ®50h); - pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, ®52h); - pci_read_config_byte(HWIF(drive)->pci_dev, 0x5a, ®5ah); - printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n", + pci_read_config_byte(dev, 0x50, ®50h); + pci_read_config_byte(dev, 0x52, ®52h); + pci_read_config_byte(dev, 0x5a, ®5ah); + printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x," + " reg5ah=0x%02x\n", drive->name, ide_dmafunc_verbose(func), reg50h, reg52h, reg5ah); if (reg5ah & 0x10) - pci_write_config_byte(HWIF(drive)->pci_dev, 0x5a, reg5ah & ~0x10); - /* fall through to a reset */ + pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); #if 0 + /* how about we flush and reset, mmmkay? */ + pci_write_config_byte(dev, 0x51, 0x1F); + /* fall through to a reset */ case ide_dma_begin: case ide_dma_end: /* reset the chips state over and over.. */ - pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, 0x13); + pci_write_config_byte(dev, 0x51, 0x13); #endif break; case ide_dma_timeout: @@ -838,10 +1030,11 @@ int hpt370_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - unsigned long dma_base = hwif->dma_base; - byte regstate = hwif->channel ? 0x54 : 0x50; - byte reginfo = hwif->channel ? 0x56 : 0x52; + struct pci_dev *dev = HWIF(drive)->pci_dev; + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + byte regstate = hwif->channel ? 0x54 : 0x50; + byte reginfo = hwif->channel ? 0x56 : 0x52; byte dma_stat; switch (func) { @@ -865,11 +1058,10 @@ case ide_dma_timeout: case ide_dma_lostirq: - pci_read_config_byte(hwif->pci_dev, reginfo, - &dma_stat); + pci_read_config_byte(dev, reginfo, &dma_stat); printk("%s: %d bytes in FIFO\n", drive->name, dma_stat); - pci_write_config_byte(hwif->pci_dev, regstate, 0x37); + pci_write_config_byte(dev, regstate, 0x37); udelay(10); dma_stat = inb(dma_base); outb(dma_stat & ~0x1, dma_base); /* stop dma */ @@ -880,7 +1072,7 @@ #ifdef HPT_RESET_STATE_ENGINE case ide_dma_begin: #endif - pci_write_config_byte(hwif->pci_dev, regstate, 0x37); + pci_write_config_byte(dev, regstate, 0x37); udelay(10); break; @@ -889,6 +1081,43 @@ } return ide_dmaproc(func, drive); /* use standard DMA stuff */ } + +int hpt374_dmaproc (ide_dma_action_t func, ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + byte mscreg = hwif->channel ? 0x54 : 0x50; +// byte reginfo = hwif->channel ? 0x56 : 0x52; + byte dma_stat; + + switch (func) { + case ide_dma_check: + return config_drive_xfer_rate(drive); + case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ + dma_stat = inb(dma_base+2); +#if 0 /* do not set unless you know what you are doing */ + if (dma_stat & 4) { + byte stat = GET_STAT(); + outb(dma_base+2, dma_stat & 0xE4); + } +#endif + /* return 1 if INTR asserted */ + return (dma_stat & 4) == 4; + case ide_dma_end: + { + byte bwsr_mask = hwif->channel ? 0x02 : 0x01; + byte bwsr_stat, msc_stat; + pci_read_config_byte(dev, 0x6a, &bwsr_stat); + pci_read_config_byte(dev, mscreg, &msc_stat); + if ((bwsr_stat & bwsr_mask) == bwsr_mask) + pci_write_config_byte(dev, mscreg, msc_stat|0x30); + } + default: + break; + } + return ide_dmaproc(func, drive); /* use standard DMA stuff */ +} #endif /* CONFIG_BLK_DEV_IDEDMA */ /* @@ -949,7 +1178,8 @@ #define TRISTATE_BIT 0x8000 static int hpt370_busproc(ide_drive_t * drive, int state) { - ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; byte tristate, resetmask, bus_reg; u16 tri_reg; @@ -969,8 +1199,8 @@ } /* grab status */ - pci_read_config_word(hwif->pci_dev, tristate, &tri_reg); - pci_read_config_byte(hwif->pci_dev, 0x59, &bus_reg); + pci_read_config_word(dev, tristate, &tri_reg); + pci_read_config_byte(dev, 0x59, &bus_reg); /* set the state. we don't set it if we don't need to do so. * make sure that the drive knows that it has failed if it's off */ @@ -1000,19 +1230,26 @@ bus_reg |= resetmask; break; } - pci_write_config_byte(hwif->pci_dev, 0x59, bus_reg); - pci_write_config_word(hwif->pci_dev, tristate, tri_reg); + pci_write_config_byte(dev, 0x59, bus_reg); + pci_write_config_word(dev, tristate, tri_reg); return 0; } -static void __init init_hpt370(struct pci_dev *dev) +static void __init init_hpt37x(struct pci_dev *dev) { int adjust, i; u16 freq; u32 pll; byte reg5bh; +#if 1 + byte reg5ah = 0; + pci_read_config_byte(dev, 0x5a, ®5ah); + /* interrupt force enable */ + pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10)); +#endif + /* * default to pci clock. make sure MA15/16 are set to output * to prevent drives having problems with 40-pin cables. @@ -1027,18 +1264,39 @@ freq &= 0x1FF; if (freq < 0x9c) { pll = F_LOW_PCI_33; - dev->sysdata = (void *) thirty_three_base_hpt370; - printk("HPT370: using 33MHz PCI clock\n"); + if (hpt_minimum_revision(dev,7)) + dev->driver_data = (void *) thirty_three_base_hpt374; + else if (hpt_minimum_revision(dev,5)) + dev->driver_data = (void *) thirty_three_base_hpt372; + else if (hpt_minimum_revision(dev,4)) + dev->driver_data = (void *) thirty_three_base_hpt370a; + else + dev->driver_data = (void *) thirty_three_base_hpt370; + printk("HPT37X: using 33MHz PCI clock\n"); } else if (freq < 0xb0) { pll = F_LOW_PCI_40; } else if (freq < 0xc8) { pll = F_LOW_PCI_50; - dev->sysdata = (void *) fifty_base_hpt370; - printk("HPT370: using 50MHz PCI clock\n"); + if (hpt_minimum_revision(dev,7)) + BUG(); + else if (hpt_minimum_revision(dev,5)) + dev->driver_data = (void *) fifty_base_hpt372; + else if (hpt_minimum_revision(dev,4)) + dev->driver_data = (void *) fifty_base_hpt370a; + else + dev->driver_data = (void *) fifty_base_hpt370a; + printk("HPT37X: using 50MHz PCI clock\n"); } else { pll = F_LOW_PCI_66; - dev->sysdata = (void *) sixty_six_base_hpt370; - printk("HPT370: using 66MHz PCI clock\n"); + if (hpt_minimum_revision(dev,7)) + BUG(); + else if (hpt_minimum_revision(dev,5)) + dev->driver_data = (void *) sixty_six_base_hpt372; + else if (hpt_minimum_revision(dev,4)) + dev->driver_data = (void *) sixty_six_base_hpt370a; + else + dev->driver_data = (void *) sixty_six_base_hpt370; + printk("HPT37X: using 66MHz PCI clock\n"); } /* @@ -1048,8 +1306,8 @@ * don't like to use the PLL because it will cause glitches * on PRST/SRST when the HPT state engine gets reset. */ - if (dev->sysdata) - goto init_hpt370_done; + if (dev->driver_data) + goto init_hpt37X_done; /* * adjust PLL based upon PCI clock, enable it, and wait for @@ -1076,9 +1334,16 @@ pci_write_config_dword(dev, 0x5c, pll & ~0x100); pci_write_config_byte(dev, 0x5b, 0x21); - dev->sysdata = (void *) fifty_base_hpt370; - printk("HPT370: using 50MHz internal PLL\n"); - goto init_hpt370_done; + if (hpt_minimum_revision(dev,7)) + BUG(); + else if (hpt_minimum_revision(dev,5)) + dev->driver_data = (void *) fifty_base_hpt372; + else if (hpt_minimum_revision(dev,4)) + dev->driver_data = (void *) fifty_base_hpt370a; + else + dev->driver_data = (void *) fifty_base_hpt370a; + printk("HPT37X: using 50MHz internal PLL\n"); + goto init_hpt37X_done; } } pll_recal: @@ -1088,13 +1353,46 @@ pll += (adjust >> 1); } -init_hpt370_done: +init_hpt37X_done: /* reset state engine */ pci_write_config_byte(dev, 0x50, 0x37); pci_write_config_byte(dev, 0x54, 0x37); udelay(100); } +static void __init init_hpt366 (struct pci_dev *dev) +{ + unsigned int reg1 = 0; +#if 0 + byte drive_fast = 0; + + /* + * Disable the "fast interrupt" prediction. + */ + pci_read_config_byte(dev, 0x51, &drive_fast); + if (drive_fast & 0x80) + pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); +#endif + pci_read_config_dword(dev, 0x40, ®1); + + /* detect bus speed by looking at control reg timing: */ + switch((reg1 >> 8) & 7) { + case 5: + dev->driver_data = (void *) forty_base_hpt366; + break; + case 9: + dev->driver_data = (void *) twenty_five_base_hpt366; + break; + case 7: + default: + dev->driver_data = (void *) thirty_three_base_hpt366; + break; + } + + if (!dev->driver_data) + BUG(); +} + unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name) { byte test = 0; @@ -1118,10 +1416,11 @@ if (test != 0x08) pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - if (pci_rev_check_hpt3xx(dev)) { - init_hpt370(dev); + if (hpt_minimum_revision(dev, 3)) { + init_hpt37x(dev); hpt_devs[n_hpt_devs++] = dev; } else { + init_hpt366(dev); hpt_devs[n_hpt_devs++] = dev; } @@ -1137,7 +1436,7 @@ unsigned int __init ata66_hpt366 (ide_hwif_t *hwif) { - byte ata66 = 0; + byte ata66 = 0; byte regmask = (hwif->channel) ? 0x01 : 0x02; pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66); @@ -1151,13 +1450,12 @@ void __init ide_init_hpt366 (ide_hwif_t *hwif) { - int hpt_rev; - - hwif->tuneproc = &hpt3xx_tune_drive; - hwif->speedproc = &hpt3xx_tune_chipset; - hwif->quirkproc = &hpt3xx_quirkproc; - hwif->intrproc = &hpt3xx_intrproc; - hwif->maskproc = &hpt3xx_maskproc; + struct pci_dev *dev = hwif->pci_dev; + hwif->tuneproc = &hpt3xx_tune_drive; + hwif->speedproc = &hpt3xx_tune_chipset; + hwif->quirkproc = &hpt3xx_quirkproc; + hwif->intrproc = &hpt3xx_intrproc; + hwif->maskproc = &hpt3xx_maskproc; #ifdef HPT_SERIALIZE_IO /* serialize access to this device */ @@ -1165,31 +1463,34 @@ hwif->serialized = hwif->mate->serialized = 1; #endif - hpt_rev = pci_rev_check_hpt3xx(hwif->pci_dev); - if (hpt_rev) { - /* set up ioctl for power status. note: power affects both - * drives on each channel */ - hwif->busproc = &hpt370_busproc; - } - - if (pci_rev2_check_hpt3xx(hwif->pci_dev)) { - /* do nothing now but will split device types */ - hwif->resetproc = &hpt3xx_reset; -/* - * don't do until we can parse out the cobalt box argh ... - * hwif->busproc = &hpt3xx_tristate; - */ - } - #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { - if (hpt_rev) { + if (hpt_minimum_revision(dev,3)) { byte reg5ah = 0; pci_read_config_byte(hwif->pci_dev, 0x5a, ®5ah); if (reg5ah & 0x10) /* interrupt force enable */ pci_write_config_byte(hwif->pci_dev, 0x5a, reg5ah & ~0x10); - hwif->dmaproc = &hpt370_dmaproc; + /* + * set up ioctl for power status. + * note: power affects both + * drives on each channel + */ + hwif->resetproc = &hpt3xx_reset; + hwif->busproc = &hpt370_busproc; + + if (hpt_minimum_revision(dev,7)) + hwif->dmaproc = &hpt374_dmaproc; + else if (hpt_minimum_revision(dev,5)) + hwif->dmaproc = &hpt374_dmaproc; + else if (hpt_minimum_revision(dev,3)) + hwif->dmaproc = &hpt370_dmaproc; + } else if (hpt_minimum_revision(dev,2)) { + hwif->resetproc = &hpt3xx_reset; + hwif->busproc = &hpt3xx_tristate; + hwif->dmaproc = &hpt366_dmaproc; } else { + hwif->resetproc = &hpt3xx_reset; + hwif->busproc = &hpt3xx_tristate; hwif->dmaproc = &hpt366_dmaproc; } if (!noautodma) @@ -1216,8 +1517,7 @@ byte secondary = hwif->channel ? 0x4f : 0x47; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); dma_new = dma_old; pci_read_config_byte(hwif->pci_dev, primary, &masterdma); @@ -1227,7 +1527,119 @@ if (slavedma & 0x30) dma_new |= 0x40; if (dma_new != dma_old) outb(dma_new, dmabase+2); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); ide_setup_dma(hwif, dmabase, 8); } + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init hpt374_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) +{ + struct pci_dev *dev2 = NULL, *findev; + ide_pci_device_t *d2; + + if (PCI_FUNC(dev->devfn) & 1) + return; + + pci_for_each_dev(findev) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + ((findev->devfn - dev->devfn) == 1) && + (PCI_FUNC(findev->devfn) & 1)) { + dev2 = findev; + break; + } + } + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); + if (!dev2) { + return; + } else { + byte irq = 0, irq2 = 0; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); + if (irq != irq2) { + pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, irq); + dev2->irq = dev->irq; + printk("%s: pci-config space interrupt fixed.\n", + d->name); + } + } + d2 = d; + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d2->name, dev2->bus->number, dev2->devfn); + ide_setup_pci_device(dev2, d2); + +} + +void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) +{ + struct pci_dev *dev2 = NULL, *findev; + ide_pci_device_t *d2; + unsigned char pin1 = 0, pin2 = 0; + unsigned int class_rev; + char *chipset_names[] = {"HPT366", "HPT366", "HPT368", + "HPT370", "HPT370A", "HPT372"}; + + if (PCI_FUNC(dev->devfn) & 1) + return; + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + + strcpy(d->name, chipset_names[class_rev]); + + switch(class_rev) { + case 5: + case 4: + case 3: printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); + return; + default: break; + } + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); + pci_for_each_dev(findev) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + ((findev->devfn - dev->devfn) == 1) && + (PCI_FUNC(findev->devfn) & 1)) { + dev2 = findev; + pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); + hpt363_shared_pin = (pin1 != pin2) ? 1 : 0; + hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0; + if (hpt363_shared_pin && hpt363_shared_irq) { + d->bootable = ON_BOARD; + printk("%s: onboard version of chipset, " + "pin1=%d pin2=%d\n", d->name, + pin1, pin2); +#if 0 + /* + * This is the third undocumented detection + * method and is generally required for the + * ABIT-BP6 boards. + */ + pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq); + printk("PCI: %s: Fixing interrupt %d pin %d " + "to ZERO \n", d->name, dev2->irq, pin2); + pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0); +#endif + } + break; + } + } + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); + if (!dev2) + return; + d2 = d; + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d2->name, dev2->bus->number, dev2->devfn); + ide_setup_pci_device(dev2, d2); +} + diff -urN linux-2.4.19-p7-pristine/drivers/ide/ht6560b.c linux-2.4.19-p7/drivers/ide/ht6560b.c --- linux-2.4.19-p7-pristine/drivers/ide/ht6560b.c Thu Apr 13 22:54:26 2000 +++ linux-2.4.19-p7/drivers/ide/ht6560b.c Tue Apr 16 23:16:57 2002 @@ -134,8 +134,7 @@ static byte current_timing = 0; byte select, timing; - __save_flags (flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); select = HT_CONFIG(drive); timing = HT_TIMING(drive); @@ -159,7 +158,7 @@ printk("ht6560b: %s: select=%#x timing=%#x\n", drive->name, select, timing); #endif } - __restore_flags (flags); /* local CPU only */ + local_irq_restore(flags); } /* @@ -257,8 +256,7 @@ unsigned long flags; int t = HT_PREFETCH_MODE << 8; - save_flags (flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); /* * Prefetch mode and unmask irq seems to conflict @@ -272,7 +270,7 @@ drive->no_unmask = 0; } - restore_flags (flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); #ifdef DEBUG printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis")); @@ -293,13 +291,12 @@ timing = ht_pio2timings(drive, pio); - save_flags (flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); drive->drive_data &= 0xff00; drive->drive_data |= timing; - restore_flags (flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); #ifdef DEBUG printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing); diff -urN linux-2.4.19-p7-pristine/drivers/ide/icside.c linux-2.4.19-p7/drivers/ide/icside.c --- linux-2.4.19-p7-pristine/drivers/ide/icside.c Thu Oct 25 13:53:47 2001 +++ linux-2.4.19-p7/drivers/ide/icside.c Mon Apr 22 20:28:33 2002 @@ -26,8 +26,6 @@ #include #include -extern char *ide_xfer_verbose (byte xfer_rate); - /* * Maximum number of interfaces per card */ @@ -334,14 +332,14 @@ rq = HWGROUP(drive)->rq; for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 1); } return ide_stopped; } printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); } - return ide_error(drive, "dma_intr", stat); + return DRIVER(drive)->error(drive, "dma_intr", stat); } /* @@ -534,10 +532,29 @@ if (drive->media != ide_disk) return 0; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &icside_dmaintr, WAIT_CMD, NULL); - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, - IDE_COMMAND_REG); - + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } +#else + if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && + (drive->addressing == 1)) { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } else if (drive->addressing) { + OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); + } else { + OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); + } +#endif +// return HWIF(drive)->dmaproc(ide_dma_begin, drive); case ide_dma_begin: enable_dma(hwif->hw.dma); return 0; diff -urN linux-2.4.19-p7-pristine/drivers/ide/ide-cd.c linux-2.4.19-p7/drivers/ide/ide-cd.c --- linux-2.4.19-p7-pristine/drivers/ide/ide-cd.c Tue Apr 16 03:15:15 2002 +++ linux-2.4.19-p7/drivers/ide/ide-cd.c Mon Apr 22 20:57:00 2002 @@ -540,7 +540,113 @@ } -static void cdrom_end_request (int uptodate, ide_drive_t *drive) +/* + * This is our end_request replacement function. + */ +static int ide_cdrom_end_request (ide_drive_t *drive, int uptodate) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&io_request_lock, flags); + rq = HWGROUP(drive)->rq; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + } + + if (!end_that_request_first(rq, uptodate, drive->name)) { + add_blkdev_randomness(MAJOR(rq->rq_dev)); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return ret; +} + +/* + * Error reporting, in human readable form (luxurious, but a memory hog). + */ +byte ide_cdrom_dump_status (ide_drive_t *drive, const char *msg, byte stat) +{ + unsigned long flags; + byte err = 0; + + local_irq_set(flags); + printk("%s: %s: status=0x%02x", drive->name, msg, stat); +#if FANCY_STATUS_DUMPS + printk(" { "); + if (stat & BUSY_STAT) + printk("Busy "); + else { + if (stat & READY_STAT) printk("DriveReady "); + if (stat & WRERR_STAT) printk("DeviceFault "); + if (stat & SEEK_STAT) printk("SeekComplete "); + if (stat & DRQ_STAT) printk("DataRequest "); + if (stat & ECC_STAT) printk("CorrectedError "); + if (stat & INDEX_STAT) printk("Index "); + if (stat & ERR_STAT) printk("Error "); + } + printk("}"); +#endif /* FANCY_STATUS_DUMPS */ + printk("\n"); + if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { + err = GET_ERR(); + printk("%s: %s: error=0x%02x", drive->name, msg, err); +#if FANCY_STATUS_DUMPS +#endif /* FANCY_STATUS_DUMPS */ + printk("\n"); + } + local_irq_restore(flags); + return err; +} + +/* + * ide_error() takes action based on the error returned by the drive. + */ +ide_startstop_t ide_cdrom_error (ide_drive_t *drive, const char *msg, byte stat) +{ + struct request *rq; + byte err; + + err = ide_cdrom_dump_status(drive, msg, stat); + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) + return ide_stopped; + /* retry only "normal" I/O: */ + if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) { + rq->errors = 1; + ide_end_drive_cmd(drive, stat, err); + return ide_stopped; + } + + if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { + /* other bits are useless when BUSY */ + rq->errors |= ERROR_RESET; + } + if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) + /* force an abort */ + OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); + if (rq->errors >= ERROR_MAX) { + DRIVER(drive)->end_request(drive, 0); + } else { + if ((rq->errors & ERROR_RESET) == ERROR_RESET) { + ++rq->errors; + return ide_do_reset(drive); + } + ++rq->errors; + } + return ide_stopped; +} + +static void cdrom_end_request (ide_drive_t *drive, int uptodate) { struct request *rq = HWGROUP(drive)->rq; @@ -554,7 +660,7 @@ if (!rq->current_nr_sectors) uptodate = 1; - ide_end_request (uptodate, HWGROUP(drive)); + ide_cdrom_end_request(drive, uptodate); } @@ -591,8 +697,8 @@ pc = (struct packet_command *) rq->buffer; pc->stat = 1; - cdrom_end_request (1, drive); - *startstop = ide_error (drive, "request sense failure", stat); + cdrom_end_request(drive, 1); + *startstop = DRIVER(drive)->error(drive, "request sense failure", stat); return 1; } else if (rq->cmd == PACKET_COMMAND) { @@ -628,7 +734,7 @@ } pc->stat = 1; - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); if ((stat & ERR_STAT) != 0) cdrom_queue_request_sense(drive, wait, pc->sense, pc); @@ -641,7 +747,7 @@ /* Fail the request. */ printk ("%s: tray open\n", drive->name); - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); } else if (sense_key == UNIT_ATTENTION) { /* Media change. */ cdrom_saw_media_change (drive); @@ -650,21 +756,21 @@ But be sure to give up if we've retried too many times. */ if (++rq->errors > ERROR_MAX) - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); } else if (sense_key == ILLEGAL_REQUEST || sense_key == DATA_PROTECT) { /* No point in retrying after an illegal request or data protect error.*/ ide_dump_status (drive, "command error", stat); - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); } else if ((err & ~ABRT_ERR) != 0) { /* Go to the default handler for other errors. */ - *startstop = ide_error (drive, "cdrom_decode_status", stat); + *startstop = DRIVER(drive)->error(drive, "cdrom_decode_status", stat); return 1; } else if ((++rq->errors > ERROR_MAX)) { /* We've racked up too many retries. Abort. */ - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); } /* If we got a CHECK_CONDITION status, @@ -745,6 +851,8 @@ (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, handler, WAIT_CMD, cdrom_timer_expiry); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ return ide_started; @@ -786,6 +894,9 @@ return startstop; } + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + /* Arm the interrupt handler. */ ide_set_handler (drive, handler, timeout, cdrom_timer_expiry); @@ -879,7 +990,7 @@ drive->name, ireason); } - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); return -1; } @@ -910,11 +1021,11 @@ if (!dma_error) { for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); + ide_cdrom_end_request(drive, 1); } return ide_stopped; } else - return ide_error (drive, "dma error", stat); + return DRIVER(drive)->error(drive, "dma error", stat); } /* Read the interrupt reason and the transfer length. */ @@ -928,9 +1039,9 @@ if (rq->current_nr_sectors > 0) { printk ("%s: cdrom_read_intr: data underrun (%ld blocks)\n", drive->name, rq->current_nr_sectors); - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); } else - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); return ide_stopped; } @@ -950,7 +1061,7 @@ printk (" Trying to limit transfer sizes\n"); CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1; } - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); return ide_stopped; } @@ -979,7 +1090,7 @@ /* If we've filled the present buffer but there's another chained buffer after it, move on. */ if (rq->current_nr_sectors == 0 && rq->nr_sectors) - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); /* If the buffers are full, cache the rest of the data in our internal buffer. */ @@ -1007,8 +1118,10 @@ } } - /* Done moving data! - Wait for another interrupt. */ + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + + /* Done moving data! Wait for another interrupt. */ ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL); return ide_started; } @@ -1031,7 +1144,7 @@ rq->sector >= info->sector_buffered && rq->sector < info->sector_buffered + info->nsectors_buffered) { if (rq->current_nr_sectors == 0) - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); memcpy (rq->buffer, info->buffer + @@ -1046,13 +1159,13 @@ /* If we've satisfied the current request, terminate it successfully. */ if (rq->nr_sectors == 0) { - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); return -1; } /* Move on to the next buffer if needed. */ if (rq->current_nr_sectors == 0) - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); /* If this condition does not hold, then the kluge i use to represent the number of sectors to skip at the start of a transfer @@ -1062,7 +1175,7 @@ (rq->sector % SECTORS_PER_FRAME) != 0) { printk ("%s: cdrom_read_from_buffer: buffer botch (%ld)\n", drive->name, rq->sector); - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); return -1; } @@ -1101,7 +1214,7 @@ (rq->sector % CD_FRAMESIZE != 0)) { printk ("%s: cdrom_start_read_continuation: buffer botch (%lu)\n", drive->name, rq->current_nr_sectors); - cdrom_end_request (0, drive); + cdrom_end_request(drive, 0); return ide_stopped; } sector -= nskip; @@ -1147,7 +1260,7 @@ return startstop; CDROM_CONFIG_FLAGS(drive)->seeking = 1; - if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) { + if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) { if (--retry == 0) { /* * this condition is far too common, to bother @@ -1337,7 +1450,7 @@ } if (pc->buflen == 0) - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); else { /* Comment this out, because this always happens right after a reset occurs, and it is annoying to @@ -1347,7 +1460,7 @@ drive->name, pc->buflen); */ pc->stat = 1; - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); } return ide_stopped; } @@ -1398,6 +1511,9 @@ pc->stat = 1; } + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + /* Now we wait for another interrupt. */ ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry); return ide_started; @@ -1522,7 +1638,7 @@ drive->name, ireason); } - cdrom_end_request(0, drive); + cdrom_end_request(drive, 0); return 1; } @@ -1554,12 +1670,12 @@ */ if (dma) { if (dma_error) - return ide_error(drive, "dma error", stat); + return DRIVER(drive)->error(drive, "dma error", stat); rq = HWGROUP(drive)->rq; for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); + ide_cdrom_end_request(drive, 1); } return ide_stopped; } @@ -1579,7 +1695,7 @@ drive->name, rq->current_nr_sectors); uptodate = 0; } - cdrom_end_request(uptodate, drive); + cdrom_end_request(drive, uptodate); return ide_stopped; } @@ -1620,9 +1736,12 @@ * current buffer complete, move on */ if (rq->current_nr_sectors == 0 && rq->nr_sectors) - cdrom_end_request (1, drive); + cdrom_end_request(drive, 1); } + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + /* re-arm handler */ ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL); return ide_started; @@ -1662,7 +1781,7 @@ * writes *must* be 2kB frame aligned */ if ((rq->nr_sectors & 3) || (rq->sector & 3)) { - cdrom_end_request(0, drive); + cdrom_end_request(drive, 0); return ide_stopped; } @@ -1698,11 +1817,10 @@ case WRITE: case READ: { if (CDROM_CONFIG_FLAGS(drive)->seeking) { - unsigned long elpased = jiffies - info->start_seek; int stat = GET_STAT(); if ((stat & SEEK_STAT) != SEEK_STAT) { - if (elpased < IDECD_SEEK_TIMEOUT) { + if (time_before(jiffies, info->start_seek + IDECD_SEEK_TIMEOUT)) { ide_stall_queue(drive, IDECD_SEEK_TIMER); return ide_stopped; } @@ -1728,13 +1846,13 @@ } case RESET_DRIVE_COMMAND: { - cdrom_end_request(1, drive); + cdrom_end_request(drive, 1); return ide_do_reset(drive); } default: { printk("ide-cd: bad cmd %d\n", rq->cmd); - cdrom_end_request(0, drive); + cdrom_end_request(drive, 0); return ide_stopped; } } @@ -2963,6 +3081,7 @@ return 0; } +int ide_cdrom_init(void); int ide_cdrom_reinit (ide_drive_t *drive); static ide_driver_t ide_cdrom_driver = { @@ -2970,13 +3089,21 @@ version: IDECD_VERSION, media: ide_cdrom, busy: 0, +#ifdef CONFIG_IDEDMA_ONLYDISK + supports_dma: 0, +#else supports_dma: 1, +#endif supports_dsc_overlap: 1, cleanup: ide_cdrom_cleanup, standby: NULL, + suspend: NULL, + resume: NULL, flushcache: NULL, do_request: ide_do_rw_cdrom, - end_request: NULL, + end_request: ide_cdrom_end_request, + sense: ide_cdrom_dump_status, + error: ide_cdrom_error, ioctl: ide_cdrom_ioctl, open: ide_cdrom_open, release: ide_cdrom_release, @@ -2986,12 +3113,12 @@ capacity: ide_cdrom_capacity, special: NULL, proc: NULL, + init: ide_cdrom_init, reinit: ide_cdrom_reinit, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; -int ide_cdrom_init(void); static ide_module_t ide_cdrom_module = { IDE_DRIVER_MODULE, ide_cdrom_init, diff -urN linux-2.4.19-p7-pristine/drivers/ide/ide-disk.c linux-2.4.19-p7/drivers/ide/ide-disk.c --- linux-2.4.19-p7-pristine/drivers/ide/ide-disk.c Tue Apr 16 03:15:16 2002 +++ linux-2.4.19-p7/drivers/ide/ide-disk.c Mon Apr 22 20:56:48 2002 @@ -1,5 +1,9 @@ /* - * linux/drivers/ide/ide-disk.c Version 1.10 June 9, 2000 + * linux/drivers/ide/ide-disk.c Version 1.16 April 7, 2002 + * + * Copyright (C) 1998-2002 Linux ATA Developemt + * Andre Hedrick + * * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -29,9 +33,14 @@ * Version 1.10 request queue changes, Ultra DMA 100 * Version 1.11 added 48-bit lba * Version 1.12 adding taskfile io access method + * Version 1.13 added standby and flush-cache for notifier + * Version 1.14 added acoustic-wcache + * Version 1.15 convert all calls to ide_raw_taskfile + * since args will return register content. + * Version 1.16 added suspend-resume-checkpower */ -#define IDEDISK_VERSION "1.12" +#define IDEDISK_VERSION "1.16" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -61,42 +70,14 @@ #define IS_PDC4030_DRIVE (0) /* auto-NULLs out pdc4030 code */ #endif -#ifdef CONFIG_IDE_TASKFILE_IO -# undef __TASKFILE__IO /* define __TASKFILE__IO */ -#else /* CONFIG_IDE_TASKFILE_IO */ -# undef __TASKFILE__IO -#endif /* CONFIG_IDE_TASKFILE_IO */ - -#ifndef __TASKFILE__IO - -static void idedisk_bswap_data (void *buffer, int wcount) +static inline u32 idedisk_read_24 (ide_drive_t *drive) { - u16 *p = buffer; - - while (wcount--) { - *p = *p << 8 | *p >> 8; p++; - *p = *p << 8 | *p >> 8; p++; - } + return (IN_BYTE(IDE_HCYL_REG)<<16) | + (IN_BYTE(IDE_LCYL_REG)<<8) | + IN_BYTE(IDE_SECTOR_REG); } -static inline void idedisk_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - ide_input_data(drive, buffer, wcount); - if (drive->bswap) - idedisk_bswap_data(buffer, wcount); -} - -static inline void idedisk_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - if (drive->bswap) { - idedisk_bswap_data(buffer, wcount); - ide_output_data(drive, buffer, wcount); - idedisk_bswap_data(buffer, wcount); - } else - ide_output_data(drive, buffer, wcount); -} - -#endif /* __TASKFILE__IO */ +static int idedisk_end_request(ide_drive_t *drive, int uptodate); /* * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity" @@ -148,7 +129,7 @@ return 0; /* lba_capacity value may be bad */ } -#ifndef __TASKFILE__IO +#ifndef CONFIG_IDE_TASKFILE_IO /* * read_intr() is the handler for disk read/multread interrupts @@ -163,9 +144,11 @@ /* new way for dealing with premature shared PCI interrupts */ if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "read_intr", stat); + return DRIVER(drive)->error(drive, "read_intr", stat); } /* no data yet, so wait for another interrupt */ + if (HWGROUP(drive)->handler != NULL) + BUG(); ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); return ide_started; } @@ -179,7 +162,7 @@ msect -= nsect; } else nsect = 1; - idedisk_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); + taskfile_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); #ifdef DEBUG printk("%s: read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n", drive->name, rq->sector, rq->sector+nsect-1, @@ -190,11 +173,18 @@ rq->errors = 0; i = (rq->nr_sectors -= nsect); if (((long)(rq->current_nr_sectors -= nsect)) <= 0) - ide_end_request(1, HWGROUP(drive)); + idedisk_end_request(drive, 1); + /* + * Another BH Page walker and DATA INTERGRITY Questioned on ERROR. + * If passed back up on multimode read, BAD DATA could be ACKED + * to FILE SYSTEMS above ... + */ if (i > 0) { if (msect) goto read_next; - ide_set_handler (drive, &read_intr, WAIT_CMD, NULL); + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); + ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); return ide_started; } return ide_stopped; @@ -225,17 +215,19 @@ i = --rq->nr_sectors; --rq->current_nr_sectors; if (((long)rq->current_nr_sectors) <= 0) - ide_end_request(1, hwgroup); + idedisk_end_request(drive, 1); if (i > 0) { - idedisk_output_data (drive, rq->buffer, SECTOR_WORDS); - ide_set_handler (drive, &write_intr, WAIT_CMD, NULL); + taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); return ide_started; } return ide_stopped; } return ide_stopped; /* the original code did this here (?) */ } - return ide_error(drive, "write_intr", stat); + return DRIVER(drive)->error(drive, "write_intr", stat); } /* @@ -248,6 +240,11 @@ * and IRQ context. The IRQ can happen any time after we've output the * full "mcount" number of sectors, so we must make sure we update the * state _before_ we output the final part of the data! + * + * The update and return to BH is a BLOCK Layer Fakey to get more data + * to satisfy the hardware atomic segment. If the hardware atomic segment + * is shorter or smaller than the BH segment then we should be OKAY. + * This is only valid if we can rewind the rq->current_nr_sectors counter. */ int ide_multwrite (ide_drive_t *drive, unsigned int mcount) { @@ -286,7 +283,7 @@ * Ok, we're all setup for the interrupt * re-entering us on the last transfer. */ - idedisk_output_data(drive, buffer, nsect<<7); + taskfile_output_data(drive, buffer, nsect<<7); } while (mcount); return 0; @@ -311,7 +308,9 @@ if (rq->nr_sectors) { if (ide_multwrite(drive, drive->mult_count)) return ide_stopped; - ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL); + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); return ide_started; } } else { @@ -323,18 +322,18 @@ rq = hwgroup->rq; for (i = rq->nr_sectors; i > 0;){ i -= rq->current_nr_sectors; - ide_end_request(1, hwgroup); + idedisk_end_request(drive, 1); } return ide_stopped; } } return ide_stopped; /* the original code did this here (?) */ } - return ide_error(drive, "multwrite_intr", stat); + return DRIVER(drive)->error(drive, "multwrite_intr", stat); } -#endif /* __TASKFILE__IO */ +#endif /* CONFIG_IDE_TASKFILE_IO */ -#ifdef __TASKFILE__IO +#ifdef CONFIG_IDE_TASKFILE_IO static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block); static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block); @@ -353,7 +352,7 @@ goto good_command; printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd); - ide_end_request(0, HWGROUP(drive)); + idedisk_end_request(drive, 0); return ide_stopped; good_command: @@ -400,88 +399,63 @@ static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - ide_task_t args; - + ide_task_t args; + int sectors; task_ioreg_t command = get_command(drive, rq->cmd); unsigned int track = (block / drive->sect); unsigned int sect = (block % drive->sect) + 1; unsigned int head = (track % drive->head); unsigned int cyl = (track / drive->head); - memset(&taskfile, 0, sizeof(task_struct_t)); - memset(&hobfile, 0, sizeof(hob_struct_t)); - - taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors; - taskfile.sector_number = sect; - taskfile.low_cylinder = cyl; - taskfile.high_cylinder = (cyl>>8); - taskfile.device_head = head; - taskfile.device_head |= drive->select.all; - taskfile.command = command; - #ifdef DEBUG printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); - if (lba) printk("LBAsect=%lld, ", block); - else printk("CHS=%d/%d/%d, ", cyl, head, sect); + printk("CHS=%d/%d/%d, ", cyl, head, sect); printk("sectors=%ld, ", rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); #endif - memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); - memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr)); - args.command_type = ide_cmd_type_parser(&args); - args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile); - args.handler = ide_handler_parser(&taskfile, &hobfile); - args.posthandler = NULL; - args.rq = (struct request *) rq; - args.block = block; - rq->special = NULL; - rq->special = (ide_task_t *)&args; + memset(&args, 0, sizeof(ide_task_t)); + sectors = (rq->nr_sectors == 256) ? 0x00 : rq->nr_sectors; + args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; + args.tfRegister[IDE_SECTOR_OFFSET] = sect; + args.tfRegister[IDE_LCYL_OFFSET] = cyl; + args.tfRegister[IDE_HCYL_OFFSET] = (cyl>>8); + args.tfRegister[IDE_SELECT_OFFSET] = head; + args.tfRegister[IDE_SELECT_OFFSET] |= drive->select.all; + args.tfRegister[IDE_COMMAND_OFFSET] = command; + args.command_type = ide_cmd_type_parser(&args); + args.rq = (struct request *) rq; + rq->special = (ide_task_t *)&args; return do_rw_taskfile(drive, &args); } static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - ide_task_t args; - + ide_task_t args; + int sectors; task_ioreg_t command = get_command(drive, rq->cmd); - memset(&taskfile, 0, sizeof(task_struct_t)); - memset(&hobfile, 0, sizeof(hob_struct_t)); - - taskfile.sector_count = (rq->nr_sectors==256)?0x00:rq->nr_sectors; - taskfile.sector_number = block; - taskfile.low_cylinder = (block>>=8); - taskfile.high_cylinder = (block>>=8); - taskfile.device_head = ((block>>8)&0x0f); - taskfile.device_head |= drive->select.all; - taskfile.command = command; - - #ifdef DEBUG printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); - if (lba) printk("LBAsect=%lld, ", block); - else printk("CHS=%d/%d/%d, ", cyl, head, sect); + printk("LBAsect=%lld, ", block); printk("sectors=%ld, ", rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); #endif - memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); - memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr)); - args.command_type = ide_cmd_type_parser(&args); - args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile); - args.handler = ide_handler_parser(&taskfile, &hobfile); - args.posthandler = NULL; - args.rq = (struct request *) rq; - args.block = block; - rq->special = NULL; - rq->special = (ide_task_t *)&args; + memset(&args, 0, sizeof(ide_task_t)); + sectors = (rq->nr_sectors == 256) ? 0x00 : rq->nr_sectors; + args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; + args.tfRegister[IDE_SECTOR_OFFSET] = block; + args.tfRegister[IDE_LCYL_OFFSET] = (block>>=8); + args.tfRegister[IDE_HCYL_OFFSET] = (block>>=8); + args.tfRegister[IDE_SELECT_OFFSET] = ((block>>8)&0x0f); + args.tfRegister[IDE_SELECT_OFFSET] |= drive->select.all; + args.tfRegister[IDE_COMMAND_OFFSET] = command; + args.command_type = ide_cmd_type_parser(&args); + args.rq = (struct request *) rq; + rq->special = (ide_task_t *)&args; return do_rw_taskfile(drive, &args); } @@ -493,57 +467,40 @@ static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long long block) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - ide_task_t args; - + ide_task_t args; + int sectors; task_ioreg_t command = get_command(drive, rq->cmd); - memset(&taskfile, 0, sizeof(task_struct_t)); - memset(&hobfile, 0, sizeof(hob_struct_t)); - - taskfile.sector_count = rq->nr_sectors; - hobfile.sector_count = (rq->nr_sectors>>8); - - if (rq->nr_sectors == 65536) { - taskfile.sector_count = 0x00; - hobfile.sector_count = 0x00; - } - - taskfile.sector_number = block; /* low lba */ - taskfile.low_cylinder = (block>>=8); /* mid lba */ - taskfile.high_cylinder = (block>>=8); /* hi lba */ - hobfile.sector_number = (block>>=8); /* low lba */ - hobfile.low_cylinder = (block>>=8); /* mid lba */ - hobfile.high_cylinder = (block>>=8); /* hi lba */ - taskfile.device_head = drive->select.all; - hobfile.device_head = taskfile.device_head; - hobfile.control = (drive->ctl|0x80); - taskfile.command = command; - #ifdef DEBUG printk("%s: %sing: ", drive->name, (rq->cmd==READ) ? "read" : "writ"); - if (lba) printk("LBAsect=%lld, ", block); - else printk("CHS=%d/%d/%d, ", cyl, head, sect); + printk("LBAsect=%lld, ", block); printk("sectors=%ld, ", rq->nr_sectors); printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); #endif - memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); - memcpy(args.hobRegister, &hobfile, sizeof(struct hd_drive_hob_hdr)); - args.command_type = ide_cmd_type_parser(&args); - args.prehandler = ide_pre_handler_parser(&taskfile, &hobfile); - args.handler = ide_handler_parser(&taskfile, &hobfile); - args.posthandler = NULL; - args.rq = (struct request *) rq; - args.block = block; - rq->special = NULL; - rq->special = (ide_task_t *)&args; + memset(&args, 0, sizeof(ide_task_t)); + sectors = (rq->nr_sectors == 65536) ? 0 : rq->nr_sectors; + args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; + args.tfRegister[IDE_SECTOR_OFFSET] = block; /* low lba */ + args.tfRegister[IDE_LCYL_OFFSET] = (block>>=8); /* mid lba */ + args.tfRegister[IDE_HCYL_OFFSET] = (block>>=8); /* hi lba */ + args.tfRegister[IDE_SELECT_OFFSET] = drive->select.all; + args.tfRegister[IDE_COMMAND_OFFSET] = command; + args.hobRegister[IDE_NSECTOR_OFFSET_HOB]= sectors >> 8; + args.hobRegister[IDE_SECTOR_OFFSET_HOB] = (block>>=8); /* low lba */ + args.hobRegister[IDE_LCYL_OFFSET_HOB] = (block>>=8); /* mid lba */ + args.hobRegister[IDE_HCYL_OFFSET_HOB] = (block>>=8); /* hi lba */ + args.hobRegister[IDE_SELECT_OFFSET_HOB] = drive->select.all; + args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80); + args.command_type = ide_cmd_type_parser(&args); + args.rq = (struct request *) rq; + rq->special = (ide_task_t *)&args; return do_rw_taskfile(drive, &args); } -#else /* !__TASKFILE__IO */ +#else /* !CONFIG_IDE_TASKFILE_IO */ + /* * do_rw_disk() issues READ and WRITE commands to a disk, * using LBA if supported, or CHS otherwise, to address sectors. @@ -647,6 +604,8 @@ if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive))) return ide_started; #endif /* CONFIG_BLK_DEV_IDEDMA */ + if (HWGROUP(drive)->handler != NULL) + BUG(); ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) { OUT_BYTE(drive->mult_count ? WIN_MULTREAD_EXT : WIN_READ_EXT, IDE_COMMAND_REG); @@ -672,7 +631,7 @@ return startstop; } if (!drive->unmask) - __cli(); /* local CPU only */ + local_irq_disable(); if (drive->mult_count) { ide_hwgroup_t *hwgroup = HWGROUP(drive); /* @@ -683,8 +642,12 @@ * before returning. Fortunately, this NEVER happens (right?). * * Except when you get an error it seems... + * + * MAJOR DATA INTEGRITY BUG !!! only if we error */ hwgroup->wrq = *rq; /* scratchpad */ + if (HWGROUP(drive)->handler != NULL) + BUG(); ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); if (ide_multwrite(drive, drive->mult_count)) { unsigned long flags; @@ -695,34 +658,35 @@ return ide_stopped; } } else { - ide_set_handler (drive, &write_intr, WAIT_CMD, NULL); - idedisk_output_data(drive, rq->buffer, SECTOR_WORDS); + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); + taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); } return ide_started; } printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd); - ide_end_request(0, HWGROUP(drive)); + idedisk_end_request(drive, 0); return ide_stopped; } -#endif /* __TASKFILE__IO */ +#endif /* CONFIG_IDE_TASKFILE_IO */ static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *drive) { MOD_INC_USE_COUNT; if (drive->removable && drive->usage == 1) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.command = WIN_DOORLOCK; + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK; + args.command_type = ide_cmd_type_parser(&args); check_disk_change(inode->i_rdev); /* * Ignore the return code from door_lock, * since the open() has already succeeded, * and the door_lock is irrelevant at this point. */ - if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL)) + if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; } return 0; @@ -733,13 +697,12 @@ static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive) { if (drive->removable && !drive->usage) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.command = WIN_DOORUNLOCK; + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK; + args.command_type = ide_cmd_type_parser(&args); invalidate_bdev(inode->i_bdev, 0); - if (drive->doorlocking && ide_wait_taskfile(drive, &taskfile, &hobfile, NULL)) + if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; } if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) @@ -761,6 +724,190 @@ current_capacity(drive)); } +static int idedisk_end_request (ide_drive_t *drive, int uptodate) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&io_request_lock, flags); + rq = HWGROUP(drive)->rq; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + } + + if (!end_that_request_first(rq, uptodate, drive->name)) { + add_blkdev_randomness(MAJOR(rq->rq_dev)); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return ret; +} + +static byte idedisk_dump_status (ide_drive_t *drive, const char *msg, byte stat) +{ + unsigned long flags; + byte err = 0; + + local_irq_set(flags); + printk("%s: %s: status=0x%02x", drive->name, msg, stat); +#if FANCY_STATUS_DUMPS + printk(" { "); + if (stat & BUSY_STAT) + printk("Busy "); + else { + if (stat & READY_STAT) printk("DriveReady "); + if (stat & WRERR_STAT) printk("DeviceFault "); + if (stat & SEEK_STAT) printk("SeekComplete "); + if (stat & DRQ_STAT) printk("DataRequest "); + if (stat & ECC_STAT) printk("CorrectedError "); + if (stat & INDEX_STAT) printk("Index "); + if (stat & ERR_STAT) printk("Error "); + } + printk("}"); +#endif /* FANCY_STATUS_DUMPS */ + printk("\n"); + if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) { + err = GET_ERR(); + printk("%s: %s: error=0x%02x", drive->name, msg, err); +#if FANCY_STATUS_DUMPS + printk(" { "); + if (err & ABRT_ERR) printk("DriveStatusError "); + if (err & ICRC_ERR) printk("%s", (err & ABRT_ERR) ? "BadCRC " : "BadSector "); + if (err & ECC_ERR) printk("UncorrectableError "); + if (err & ID_ERR) printk("SectorIdNotFound "); + if (err & TRK0_ERR) printk("TrackZeroNotFound "); + if (err & MARK_ERR) printk("AddrMarkNotFound "); + printk("}"); + if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) { + if ((drive->id->command_set_2 & 0x0400) && + (drive->id->cfs_enable_2 & 0x0400) && + (drive->addressing == 1)) { + __u64 sectors = 0; + u32 low = 0, high = 0; + low = idedisk_read_24(drive); + OUT_BYTE(drive->ctl|0x80, IDE_CONTROL_REG); + high = idedisk_read_24(drive); + sectors = ((__u64)high << 24) | low; + printk(", LBAsect=%llu, high=%d, low=%d", + (unsigned long long) sectors, + high, low); + } else { + byte cur = IN_BYTE(IDE_SELECT_REG); + if (cur & 0x40) { /* using LBA? */ + printk(", LBAsect=%ld", (unsigned long) + ((cur&0xf)<<24) + |(IN_BYTE(IDE_HCYL_REG)<<16) + |(IN_BYTE(IDE_LCYL_REG)<<8) + | IN_BYTE(IDE_SECTOR_REG)); + } else { + printk(", CHS=%d/%d/%d", + (IN_BYTE(IDE_HCYL_REG)<<8) + + IN_BYTE(IDE_LCYL_REG), + cur & 0xf, + IN_BYTE(IDE_SECTOR_REG)); + } + } + if (HWGROUP(drive) && HWGROUP(drive)->rq) + printk(", sector=%ld", HWGROUP(drive)->rq->sector); + } + } +#endif /* FANCY_STATUS_DUMPS */ + printk("\n"); + local_irq_restore(flags); + return err; +} + +ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, byte stat) +{ + struct request *rq; + byte err; + int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; + + err = idedisk_dump_status(drive, msg, stat); + + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) + return ide_stopped; + /* retry only "normal" I/O: */ + switch (rq->cmd) { + case IDE_DRIVE_CMD: + case IDE_DRIVE_TASK: + case IDE_DRIVE_TASKFILE: + rq->errors = 1; + ide_end_drive_cmd(drive, stat, err); + return ide_stopped; +#if 0 + case IDE_DRIVE_TASKFILE: + rq->errors = 1; + ide_end_taskfile(drive, stat, err); + return ide_stopped; +#endif + default: + break; + } + + if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { + /* other bits are useless when BUSY */ + rq->errors |= ERROR_RESET; + } else if (stat & ERR_STAT) { + /* err has different meaning on cdrom and tape */ + if (err == ABRT_ERR) { + if (drive->select.b.lba && + /* some newer drives don't support WIN_SPECIFY */ + IN_BYTE(IDE_COMMAND_REG) == WIN_SPECIFY) + return ide_stopped; + } else if ((err & (ABRT_ERR | ICRC_ERR)) == (ABRT_ERR | ICRC_ERR)) { + /* UDMA crc error, just retry the operation */ + drive->crc_count++; + } else if (err & (BBD_ERR | ECC_ERR)) + /* retries won't help these */ + rq->errors = ERROR_MAX; + else if (err & TRK0_ERR) + /* help it find track zero */ + rq->errors |= ERROR_RECAL; + } + if ((stat & DRQ_STAT) && rq->cmd != WRITE) { + /* + * try_to_flush_leftover_data() is invoked in response to + * a drive unexpectedly having its DRQ_STAT bit set. As + * an alternative to resetting the drive, this routine + * tries to clear the condition by read a sector's worth + * of data from the drive. Of course, this may not help + * if the drive is *waiting* for data from *us*. + */ + while (i > 0) { + u32 buffer[16]; + unsigned int wcount = (i > 16) ? 16 : i; + i -= wcount; + ata_input_data(drive, buffer, wcount); + } + } + if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) + /* force an abort */ + OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); + if (rq->errors >= ERROR_MAX) + DRIVER(drive)->end_request(drive, 0); + else { + if ((rq->errors & ERROR_RESET) == ERROR_RESET) { + ++rq->errors; + return ide_do_reset(drive); + } + if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) + drive->special.b.recalibrate = 1; + ++rq->errors; + } + return ide_stopped; +} + /* * Queries for true maximum capacity of the drive. * Returns maximum LBA address (> 0) of the drive, 0 if failed. @@ -778,8 +925,7 @@ memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_SELECT_OFFSET] = 0x40; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX; - args.handler = task_no_data_intr; - + args.command_type = ide_cmd_type_parser(&args); /* submit command request */ ide_raw_taskfile(drive, &args, NULL); @@ -804,8 +950,7 @@ args.tfRegister[IDE_SELECT_OFFSET] = 0x40; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_READ_NATIVE_MAX_EXT; - args.handler = task_no_data_intr; - + args.command_type = ide_cmd_type_parser(&args); /* submit command request */ ide_raw_taskfile(drive, &args, NULL); @@ -841,7 +986,7 @@ args.tfRegister[IDE_HCYL_OFFSET] = ((addr_req >> 16) & 0xff); args.tfRegister[IDE_SELECT_OFFSET] = ((addr_req >> 24) & 0x0f) | 0x40; args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SET_MAX; - args.handler = task_no_data_intr; + args.command_type = ide_cmd_type_parser(&args); /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, read new maximum address value */ @@ -873,7 +1018,7 @@ args.hobRegister[IDE_HCYL_OFFSET_HOB] = ((addr_req >>= 8) & 0xff); args.hobRegister[IDE_SELECT_OFFSET_HOB] = 0x40; args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80); - args.handler = task_no_data_intr; + args.command_type = ide_cmd_type_parser(&args); /* submit command request */ ide_raw_taskfile(drive, &args, NULL); /* if OK, compute maximum address value */ @@ -949,6 +1094,7 @@ drive->name, set_max_ext, capacity_2); #endif /* CONFIG_IDEDISK_STROKE */ } + drive->cyl = (unsigned int) capacity_2 / (drive->head * drive->sect); drive->bios_cyl = drive->cyl; drive->capacity48 = capacity_2; drive->capacity = (unsigned long) capacity_2; @@ -979,7 +1125,7 @@ drive->capacity = capacity; if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400)) { - drive->capacity48 = id->lba_capacity_2; + drive->capacity48 = id->lba_capacity_2; drive->head = 255; drive->sect = 63; drive->cyl = (unsigned long)(drive->capacity48) / (drive->head * drive->sect); @@ -998,47 +1144,40 @@ special_t *s = &drive->special; if (s->b.set_geometry) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - ide_handler_t *handler = NULL; - - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - s->b.set_geometry = 0; - taskfile.sector_number = drive->sect; - taskfile.low_cylinder = drive->cyl; - taskfile.high_cylinder = drive->cyl>>8; - taskfile.device_head = ((drive->head-1)|drive->select.all)&0xBF; if (!IS_PDC4030_DRIVE) { - taskfile.sector_count = drive->sect; - taskfile.command = WIN_SPECIFY; - handler = ide_handler_parser(&taskfile, &hobfile); + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; + args.tfRegister[IDE_SECTOR_OFFSET] = drive->sect; + args.tfRegister[IDE_LCYL_OFFSET] = drive->cyl; + args.tfRegister[IDE_HCYL_OFFSET] = drive->cyl>>8; + args.tfRegister[IDE_SELECT_OFFSET] = ((drive->head-1)|drive->select.all)&0xBF; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY; + args.command_type = ide_cmd_type_parser(&args); + do_rw_taskfile(drive, &args); } - do_taskfile(drive, &taskfile, &hobfile, handler); } else if (s->b.recalibrate) { s->b.recalibrate = 0; if (!IS_PDC4030_DRIVE) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.sector_count = drive->sect; - taskfile.command = WIN_RESTORE; - do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile)); + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE; + args.command_type = ide_cmd_type_parser(&args); + do_rw_taskfile(drive, &args); } } else if (s->b.set_multmode) { s->b.set_multmode = 0; if (drive->id && drive->mult_req > drive->id->max_multsect) drive->mult_req = drive->id->max_multsect; if (!IS_PDC4030_DRIVE) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.sector_count = drive->mult_req; - taskfile.command = WIN_SETMULT; - do_taskfile(drive, &taskfile, &hobfile, ide_handler_parser(&taskfile, &hobfile)); + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT; + args.command_type = ide_cmd_type_parser(&args); + do_rw_taskfile(drive, &args); } } else if (s->all) { int special = s->all; @@ -1068,45 +1207,44 @@ static int smart_enable(ide_drive_t *drive) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.feature = SMART_ENABLE; - taskfile.low_cylinder = SMART_LCYL_PASS; - taskfile.high_cylinder = SMART_HCYL_PASS; - taskfile.command = WIN_SMART; - return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); + ide_task_t args; + + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_FEATURE_OFFSET] = SMART_ENABLE; + args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; + args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; + args.command_type = ide_cmd_type_parser(&args); + return ide_raw_taskfile(drive, &args, NULL); } static int get_smart_values(ide_drive_t *drive, byte *buf) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.feature = SMART_READ_VALUES; - taskfile.sector_count = 0x01; - taskfile.low_cylinder = SMART_LCYL_PASS; - taskfile.high_cylinder = SMART_HCYL_PASS; - taskfile.command = WIN_SMART; + ide_task_t args; + + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_FEATURE_OFFSET] = SMART_READ_VALUES; + args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; + args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; + args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; + args.command_type = ide_cmd_type_parser(&args); (void) smart_enable(drive); - return ide_wait_taskfile(drive, &taskfile, &hobfile, buf); + return ide_raw_taskfile(drive, &args, buf); } static int get_smart_thresholds(ide_drive_t *drive, byte *buf) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.feature = SMART_READ_THRESHOLDS; - taskfile.sector_count = 0x01; - taskfile.low_cylinder = SMART_LCYL_PASS; - taskfile.high_cylinder = SMART_HCYL_PASS; - taskfile.command = WIN_SMART; + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_FEATURE_OFFSET] = SMART_READ_THRESHOLDS; + args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; + args.tfRegister[IDE_LCYL_OFFSET] = SMART_LCYL_PASS; + args.tfRegister[IDE_HCYL_OFFSET] = SMART_HCYL_PASS; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SMART; + args.command_type = ide_cmd_type_parser(&args); (void) smart_enable(drive); - return ide_wait_taskfile(drive, &taskfile, &hobfile, buf); + return ide_raw_taskfile(drive, &args, buf); } static int proc_idedisk_read_cache @@ -1175,23 +1313,12 @@ #endif /* CONFIG_PROC_FS */ +/* + * This is tightly woven into the driver->do_special can not touch. + * DON'T do it again until a total personality rewrite is committed. + */ static int set_multcount(ide_drive_t *drive, int arg) { -#ifdef __TASKFILE__IO - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - - if (drive->special.b.set_multmode) - return -EBUSY; - - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.sector_count = drive->mult_req; - taskfile.command = WIN_SETMULT; - drive->mult_req = arg; - drive->special.b.set_multmode = 1; - ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); -#else /* !__TASKFILE__IO */ struct request rq; if (drive->special.b.set_multmode) @@ -1201,7 +1328,6 @@ drive->mult_req = arg; drive->special.b.set_multmode = 1; (void) ide_do_drive_cmd (drive, &rq, ide_wait); -#endif /* __TASKFILE__IO */ return (drive->mult_count == arg) ? 0 : -EIO; } @@ -1217,57 +1343,110 @@ static int write_cache (ide_drive_t *drive, int arg) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.feature = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; - taskfile.command = WIN_SETFEATURES; + ide_task_t args; if (!(drive->id->cfs_enable_2 & 0x3000)) return 1; - (void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? + SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; + args.command_type = ide_cmd_type_parser(&args); + (void) ide_raw_taskfile(drive, &args, NULL); + drive->wcache = arg; return 0; } +static int call_idedisk_standby (ide_drive_t *drive, int arg) +{ + ide_task_t args; + byte standby = (arg) ? WIN_STANDBYNOW2 : WIN_STANDBYNOW1; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_COMMAND_OFFSET] = standby; + args.command_type = ide_cmd_type_parser(&args); + return ide_raw_taskfile(drive, &args, NULL); +} + static int do_idedisk_standby (ide_drive_t *drive) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - taskfile.command = WIN_STANDBYNOW1; - return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); + return call_idedisk_standby(drive, 0); +} + +static int call_idedisk_suspend (ide_drive_t *drive, int arg) +{ + ide_task_t args; + byte suspend = (arg) ? WIN_SLEEPNOW2 : WIN_SLEEPNOW1; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_COMMAND_OFFSET] = suspend; + args.command_type = ide_cmd_type_parser(&args); + return ide_raw_taskfile(drive, &args, NULL); +} + +static int do_idedisk_suspend (ide_drive_t *drive) +{ + if (drive->suspend_reset) + return 1; + + return call_idedisk_suspend(drive, 0); +} + +static int call_idedisk_checkpower (ide_drive_t *drive, int arg) +{ + ide_task_t args; + byte ckpw = (arg) ? WIN_CHECKPOWERMODE2 : WIN_CHECKPOWERMODE1; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_COMMAND_OFFSET] = ckpw; + args.command_type = ide_cmd_type_parser(&args); + ide_raw_taskfile(drive, &args, NULL); +#if 0 +if (errno != EIO || args[0] != 0 || args[1] != 0) + state = "unknown"; +else + state = "sleeping"; +} else { + state = (args[2] == 255) ? "active/idle" : "standby"; +#endif + return 0; +} + +static int do_idedisk_checkpower (ide_drive_t *drive) +{ + return call_idedisk_checkpower(drive, 0); +} + +static int do_idedisk_resume (ide_drive_t *drive) +{ + if (!drive->suspend_reset) + return 1; + return 0; } static int do_idedisk_flushcache (ide_drive_t *drive) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - if (drive->id->cfs_enable_2 & 0x2400) { - taskfile.command = WIN_FLUSH_CACHE_EXT; - } else { - taskfile.command = WIN_FLUSH_CACHE; - } - return ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); + ide_task_t args; + + memset(&args, 0, sizeof(ide_task_t)); + if (drive->id->cfs_enable_2 & 0x2400) + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; + else + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; + args.command_type = ide_cmd_type_parser(&args); + return ide_raw_taskfile(drive, &args, NULL); } static int set_acoustic (ide_drive_t *drive, int arg) { - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - - taskfile.feature = (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM; - taskfile.sector_count = arg; + ide_task_t args; - taskfile.command = WIN_SETFEATURES; - (void) ide_wait_taskfile(drive, &taskfile, &hobfile, NULL); + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM : + SETFEATURES_DIS_AAM; + args.tfRegister[IDE_NSECTOR_OFFSET] = arg; + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETFEATURES; + args.command_type = ide_cmd_type_parser(&args); + ide_raw_taskfile(drive, &args, NULL); drive->acoustic = arg; return 0; } @@ -1276,9 +1455,11 @@ { drive->addressing = 0; + if (!HWGROUP(drive)->addressing) + return 0; + if (!(drive->id->cfs_enable_2 & 0x0400)) return -EIO; - drive->addressing = arg; return 0; } @@ -1414,7 +1595,13 @@ drive->no_io_32bit = id->dword_io ? 1 : 0; if (drive->id->cfs_enable_2 & 0x3000) write_cache(drive, (id->cfs_enable_2 & 0x3000)); +#if 1 (void) probe_lba_addressing(drive, 1); +#else + /* if using 48-bit addressing bump the request size up */ + if (probe_lba_addressing(drive, 1)) + blk_queue_max_sectors(&drive->queue, 2048); +#endif } static int idedisk_cleanup (ide_drive_t *drive) @@ -1426,6 +1613,7 @@ return ide_unregister_subdriver(drive); } +int idedisk_init (void); int idedisk_reinit(ide_drive_t *drive); /* @@ -1440,9 +1628,13 @@ supports_dsc_overlap: 0, cleanup: idedisk_cleanup, standby: do_idedisk_standby, + suspend: do_idedisk_suspend, + resume: do_idedisk_resume, flushcache: do_idedisk_flushcache, do_request: do_rw_disk, - end_request: NULL, + end_request: idedisk_end_request, + sense: idedisk_dump_status, + error: idedisk_error, ioctl: NULL, open: idedisk_open, release: idedisk_release, @@ -1452,12 +1644,12 @@ capacity: idedisk_capacity, special: idedisk_special, proc: idedisk_proc, + init: idedisk_init, reinit: idedisk_reinit, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; -int idedisk_init (void); static ide_module_t idedisk_module = { IDE_DRIVER_MODULE, idedisk_init, @@ -1480,7 +1672,8 @@ DRIVER(drive)->busy++; idedisk_setup(drive); if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { - printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); + printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", + drive->name, drive->head); (void) idedisk_cleanup(drive); DRIVER(drive)->busy--; return 1; diff -urN linux-2.4.19-p7-pristine/drivers/ide/ide-dma.c linux-2.4.19-p7/drivers/ide/ide-dma.c --- linux-2.4.19-p7-pristine/drivers/ide/ide-dma.c Tue Apr 16 03:15:16 2002 +++ linux-2.4.19-p7/drivers/ide/ide-dma.c Mon Apr 22 20:28:33 2002 @@ -101,8 +101,6 @@ #define DEFAULT_BMCRBA 0xcc00 /* VIA's default value */ #define DEFAULT_BMALIBA 0xd400 /* ALI's default value */ -extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc); - #ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS struct drive_list_entry { @@ -123,7 +121,6 @@ { "WDC AC11000H" , "ALL" }, { "WDC AC22100H" , "ALL" }, - { "WDC AC31000H" , "ALL" }, { "WDC AC32500H" , "ALL" }, { "WDC AC33100H" , "ALL" }, { "WDC AC31600H" , "ALL" }, @@ -238,14 +235,14 @@ rq = HWGROUP(drive)->rq; for (i = rq->nr_sectors; i > 0;) { i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 1); } return ide_stopped; } printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); } - return ide_error(drive, "dma_intr", stat); + return DRIVER(drive)->error(drive, "dma_intr", stat); } static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq) @@ -291,13 +288,11 @@ unsigned char *virt_addr = rq->buffer; int sector_count = rq->nr_sectors; -// if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA) || -// (args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA_EXT)) if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) hwif->sg_dma_direction = PCI_DMA_TODEVICE; else hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; - +#if 1 if (sector_count > 128) { memset(&sg[nents], 0, sizeof(*sg)); sg[nents].address = virt_addr; @@ -310,7 +305,20 @@ sg[nents].address = virt_addr; sg[nents].length = sector_count * SECTOR_SIZE; nents++; - +#else + while (sector_count > 128) { + memset(&sg[nents], 0, sizeof(*sg)); + sg[nents].address = virt_addr; + sg[nents].length = 128 * SECTOR_SIZE; + nents++; + virt_addr = virt_addr + (128 * SECTOR_SIZE); + sector_count -= 128; + }; + memset(&sg[nents], 0, sizeof(*sg)); + sg[nents].address = virt_addr; + sg[nents].length = sector_count * SECTOR_SIZE; + nents++; +#endif return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); } @@ -498,16 +506,10 @@ static int config_drive_for_dma (ide_drive_t *drive) { - int config_allows_dma = 1; struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); -#ifdef CONFIG_IDEDMA_ONLYDISK - if (drive->media != ide_disk) - config_allows_dma = 0; -#endif - - if (id && (id->capability & 1) && hwif->autodma && config_allows_dma) { + if (id && (id->capability & 1) && hwif->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) return hwif->dmaproc(ide_dma_off, drive); @@ -535,7 +537,7 @@ return hwif->dmaproc(ide_dma_off_quietly, drive); } -#ifndef CONFIG_BLK_DEV_IDEDMA_TIMEOUT +#ifndef __IDEDMA_TIMEOUT /* * 1 dmaing, 2 error, 4 intr */ @@ -553,36 +555,52 @@ if (dma_stat & 2) { /* ERROR */ byte stat = GET_STAT(); - return ide_error(drive, "dma_timer_expiry", stat); + return DRIVER(drive)->error(drive, "dma_timer_expiry", stat); } if (dma_stat & 1) /* DMAing */ return WAIT_CMD; return 0; } -#else /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ -static ide_startstop_t ide_dma_timeout_revovery (ide_drive_t *drive) +#else /* __IDEDMA_TIMEOUT */ +static int ide_dma_timeout_recovery (ide_drive_t *drive) { - ide_hwgroup_t *hwgroup = HWGROUP(drive); - ide_hwif_t *hwif = HWIF(drive); + struct request *rq = HWGROUP(drive)->rq; int enable_dma = drive->using_dma; + int speed = drive->current_speed; unsigned long flags; - ide_startstop_t startstop; spin_lock_irqsave(&io_request_lock, flags); - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); + HWGROUP(drive)->handler = NULL; + del_timer(&HWGROUP(drive)->timer); + HWGROUP(drive)->expiry = NULL; + HWGROUP(drive)->rq = NULL; spin_unlock_irqrestore(&io_request_lock, flags); + (void) HWIF(drive)->dmaproc(ide_dma_off, drive); drive->waiting_for_dma = 0; - startstop = ide_do_reset(drive); + (void) ide_do_reset(drive); + + if (!(drive_is_ready(drive))) { + /* FIXME: Replace hard-coded 100, error handling? */ + int i; + for (i=0; i<100; i++) { + if (drive_is_ready(drive)) + break; + } + } + + if ((HWIF(drive)->speedproc) != NULL) { + HWIF(drive)->speedproc(drive, speed); + drive->current_speed = speed; + } if ((enable_dma) && !(drive->using_dma)) - (void) hwif->dmaproc(ide_dma_on, drive); + (void) HWIF(drive)->dmaproc(ide_dma_on, drive); - return startstop; + return restart_request(drive, rq); } -#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ +#endif /* __IDEDMA_TIMEOUT */ /* * ide_dmaproc() initiates/aborts DMA read/write operations on a drive. @@ -602,7 +620,6 @@ */ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { -// ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); unsigned long dma_base = hwif->dma_base; byte unit = (drive->select.b.unit & 0x01); @@ -626,18 +643,35 @@ case ide_dma_write: SELECT_READ_WRITE(hwif,drive,func); if (!(count = ide_build_dmatable(drive, func))) - return 1; /* try PIO instead of DMA */ - outl(hwif->dmatable_dma, dma_base + 4); /* PRD table */ - outb(reading, dma_base); /* specify r/w */ - outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ + /* try PIO instead of DMA */ + return 1; + /* PRD table */ + outl(hwif->dmatable_dma, dma_base + 4); + /* specify r/w */ + outb(reading, dma_base); + /* clear INTR & ERROR flags */ + outb(inb(dma_base+2)|6, dma_base+2); drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; -#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT - ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, NULL); /* issue cmd to drive */ -#else /* !CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */ -#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ + /* paranoia check */ + if (HWGROUP(drive)->handler != NULL) + BUG(); +#ifndef __IDEDMA_TIMEOUT + ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); +#else /* __IDEDMA_TIMEOUT */ + ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, NULL); +#endif /* __IDEDMA_TIMEOUT */ + /* issue cmd to drive */ + /* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } +#else if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && (drive->addressing == 1)) { ide_task_t *args = HWGROUP(drive)->rq->special; @@ -647,6 +681,7 @@ } else { OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); } +#endif return HWIF(drive)->dmaproc(ide_dma_begin, drive); case ide_dma_begin: /* Note that this is done *after* the cmd has @@ -654,15 +689,20 @@ * The Promise Ultra33 doesn't work correctly when * we do this part before issuing the drive cmd. */ - outb(inb(dma_base)|1, dma_base); /* start DMA */ + outb(inb(dma_base)|1, dma_base); /* start DMA */ return 0; case ide_dma_end: /* returns 1 on error, 0 otherwise */ drive->waiting_for_dma = 0; - outb(inb(dma_base)&~1, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ - ide_destroy_dmatable(drive); /* purge DMA mappings */ - return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ + /* stop DMA */ + outb(inb(dma_base)&~1, dma_base); + /* get DMA status */ + dma_stat = inb(dma_base+2); + /* clear the INTR & ERROR bits */ + outb(dma_stat|6, dma_base+2); + /* purge DMA mappings */ + ide_destroy_dmatable(drive); + /* verify good DMA status */ + return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */ dma_stat = inb(dma_base+2); #if 0 /* do not set unless you know what you are doing */ @@ -671,48 +711,51 @@ outb(dma_base+2, dma_stat & 0xE4); } #endif - return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ + /* return 1 if INTR asserted */ + return (dma_stat & 4) == 4; case ide_dma_bad_drive: case ide_dma_good_drive: return check_drive_lists(drive, (func == ide_dma_good_drive)); case ide_dma_verbose: return report_drive_dmaing(drive); case ide_dma_timeout: - // FIXME: Many IDE chipsets do not permit command file register access - // FIXME: while the bus-master function is still active. - // FIXME: To prevent deadlock with those chipsets, we must be extremely - // FIXME: careful here (and in ide_intr() as well) to NOT access any - // FIXME: registers from the 0x1Fx/0x17x sets before terminating the - // FIXME: bus-master operation via the bus-master control reg. - // FIXME: Otherwise, chipset deadlock will occur, and some systems will - // FIXME: lock up completely!! -#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT + // FIXME: Many IDE chipsets do not permit command file register access + // FIXME: while the bus-master function is still active. + // FIXME: To prevent deadlock with those chipsets, we must be extremely + // FIXME: careful here (and in ide_intr() as well) to NOT access any + // FIXME: registers from the 0x1Fx/0x17x sets before terminating the + // FIXME: bus-master operation via the bus-master control reg. + // FIXME: Otherwise, chipset deadlock will occur, and some systems will + // FIXME: lock up completely!! +#ifdef __IDEDMA_TIMEOUT /* * Have to issue an abort and requeue the request * DMA engine got turned off by a goofy ASIC, and * we have to clean up the mess, and here is as good * as any. Do it globally for all chipsets. */ - outb(0x00, dma_base); /* stop DMA */ - dma_stat = inb(dma_base+2); /* get DMA status */ - outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */ +#if 0 + dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive); +#else + drive->waiting_for_dma = 0; + /* stop DMA */ + outb(inb(dma_base)&~1, dma_base); +// outb(0x00, dma_base); + /* get DMA status */ + dma_stat = inb(dma_base+2); + /* clear the INTR & ERROR bits */ + outb(dma_stat|6, dma_base+2); + /* purge DMA mappings */ + ide_destroy_dmatable(drive); +#endif printk("%s: %s: Lets do it again!" \ "stat = 0x%02x, dma_stat = 0x%02x\n", drive->name, ide_dmafunc_verbose(func), GET_STAT(), dma_stat); if (dma_stat & 0xF0) - return ide_dma_timeout_revovery(drive); - - printk("%s: %s: (restart_request) Lets do it again!" \ - "stat = 0x%02x, dma_stat = 0x%02x\n", - drive->name, ide_dmafunc_verbose(func), - GET_STAT(), dma_stat); - - return restart_request(drive); // BUG: return types do not match!! -//#else -// return HWGROUP(drive)->handler(drive); -#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ + return ide_dma_timeout_recovery(drive); +#endif /* __IDEDMA_TIMEOUT */ case ide_dma_retune: case ide_dma_lostirq: printk("ide_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func), func); @@ -746,7 +789,7 @@ } /* - * This can be called for a dynamically installed interface. Don't __init it + * This can be called for a dynamically installed interface. Don't __init it */ void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports) @@ -840,6 +883,7 @@ case PCI_DEVICE_ID_AL_M5219: case PCI_DEVICE_ID_AMD_VIPER_7409: case PCI_DEVICE_ID_CMD_643: + case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: outb(inb(dma_base+2) & 0x60, dma_base+2); if (inb(dma_base+2) & 0x80) { printk("%s: simplex device: DMA forced\n", name); diff -urN linux-2.4.19-p7-pristine/drivers/ide/ide-features.c linux-2.4.19-p7/drivers/ide/ide-features.c --- linux-2.4.19-p7-pristine/drivers/ide/ide-features.c Tue Apr 16 03:15:16 2002 +++ linux-2.4.19-p7/drivers/ide/ide-features.c Wed Dec 31 16:00:00 1969 @@ -1,376 +0,0 @@ -/* - * linux/drivers/block/ide-features.c Version 0.04 June 9, 2000 - * - * Copyright (C) 1999-2000 Linus Torvalds & authors (see below) - * - * Copyright (C) 1999-2000 Andre Hedrick - * - * Extracts if ide.c to address the evolving transfer rate code for - * the SETFEATURES_XFER callouts. Various parts of any given function - * are credited to previous ATA-IDE maintainers. - * - * Auto-CRC downgrade for Ultra DMA(ing) - * - * May be copied or modified under the terms of the GNU General Public License - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * A Verbose noise maker for debugging on the attempted transfer rates. - */ -char *ide_xfer_verbose (byte xfer_rate) -{ - switch(xfer_rate) { - case XFER_UDMA_7: return("UDMA 7"); - case XFER_UDMA_6: return("UDMA 6"); - case XFER_UDMA_5: return("UDMA 5"); - case XFER_UDMA_4: return("UDMA 4"); - case XFER_UDMA_3: return("UDMA 3"); - case XFER_UDMA_2: return("UDMA 2"); - case XFER_UDMA_1: return("UDMA 1"); - case XFER_UDMA_0: return("UDMA 0"); - case XFER_MW_DMA_2: return("MW DMA 2"); - case XFER_MW_DMA_1: return("MW DMA 1"); - case XFER_MW_DMA_0: return("MW DMA 0"); - case XFER_SW_DMA_2: return("SW DMA 2"); - case XFER_SW_DMA_1: return("SW DMA 1"); - case XFER_SW_DMA_0: return("SW DMA 0"); - case XFER_PIO_4: return("PIO 4"); - case XFER_PIO_3: return("PIO 3"); - case XFER_PIO_2: return("PIO 2"); - case XFER_PIO_1: return("PIO 1"); - case XFER_PIO_0: return("PIO 0"); - case XFER_PIO_SLOW: return("PIO SLOW"); - default: return("XFER ERROR"); - } -} - -/* - * - */ -char *ide_media_verbose (ide_drive_t *drive) -{ - switch (drive->media) { - case ide_scsi: return("scsi "); - case ide_disk: return("disk "); - case ide_optical: return("optical"); - case ide_cdrom: return("cdrom "); - case ide_tape: return("tape "); - case ide_floppy: return("floppy "); - default: return("???????"); - } -} - -/* - * A Verbose noise maker for debugging on the attempted dmaing calls. - */ -char *ide_dmafunc_verbose (ide_dma_action_t dmafunc) -{ - switch (dmafunc) { - case ide_dma_read: return("ide_dma_read"); - case ide_dma_write: return("ide_dma_write"); - case ide_dma_begin: return("ide_dma_begin"); - case ide_dma_end: return("ide_dma_end:"); - case ide_dma_check: return("ide_dma_check"); - case ide_dma_on: return("ide_dma_on"); - case ide_dma_off: return("ide_dma_off"); - case ide_dma_off_quietly: return("ide_dma_off_quietly"); - case ide_dma_test_irq: return("ide_dma_test_irq"); - case ide_dma_bad_drive: return("ide_dma_bad_drive"); - case ide_dma_good_drive: return("ide_dma_good_drive"); - case ide_dma_verbose: return("ide_dma_verbose"); - case ide_dma_retune: return("ide_dma_retune"); - case ide_dma_lostirq: return("ide_dma_lostirq"); - case ide_dma_timeout: return("ide_dma_timeout"); - default: return("unknown"); - } -} - -/* - * - */ -byte ide_auto_reduce_xfer (ide_drive_t *drive) -{ - if (!drive->crc_count) - return drive->current_speed; - drive->crc_count = 0; - - switch(drive->current_speed) { - case XFER_UDMA_7: return XFER_UDMA_6; - case XFER_UDMA_6: return XFER_UDMA_5; - case XFER_UDMA_5: return XFER_UDMA_4; - case XFER_UDMA_4: return XFER_UDMA_3; - case XFER_UDMA_3: return XFER_UDMA_2; - case XFER_UDMA_2: return XFER_UDMA_1; - case XFER_UDMA_1: return XFER_UDMA_0; - /* - * OOPS we do not goto non Ultra DMA modes - * without iCRC's available we force - * the system to PIO and make the user - * invoke the ATA-1 ATA-2 DMA modes. - */ - case XFER_UDMA_0: - default: return XFER_PIO_4; - } -} - -/* - * Update the - */ -int ide_driveid_update (ide_drive_t *drive) -{ - /* - * Re-read drive->id for possible DMA mode - * change (copied from ide-probe.c) - */ - struct hd_driveid *id; - unsigned long timeout, flags; - - SELECT_MASK(HWIF(drive), drive, 1); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl,IDE_CONTROL_REG); - ide_delay_50ms(); - OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG); - timeout = jiffies + WAIT_WORSTCASE; - do { - if (0 < (signed long)(jiffies - timeout)) { - SELECT_MASK(HWIF(drive), drive, 0); - return 0; /* drive timed-out */ - } - ide_delay_50ms(); /* give drive a breather */ - } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT); - ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ - if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { - SELECT_MASK(HWIF(drive), drive, 0); - printk("%s: CHECK for good STATUS\n", drive->name); - return 0; - } - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only; some systems need this */ - SELECT_MASK(HWIF(drive), drive, 0); - id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); - if (!id) { - __restore_flags(flags); /* local CPU only */ - return 0; - } - ide_input_data(drive, id, SECTOR_WORDS); - (void) GET_STAT(); /* clear drive IRQ */ - ide__sti(); /* local CPU only */ - __restore_flags(flags); /* local CPU only */ - ide_fix_driveid(id); - if (id) { - drive->id->dma_ultra = id->dma_ultra; - drive->id->dma_mword = id->dma_mword; - drive->id->dma_1word = id->dma_1word; - /* anything more ? */ - kfree(id); - } - - return 1; -} - -/* - * Verify that we are doing an approved SETFEATURES_XFER with respect - * to the hardware being able to support request. Since some hardware - * can improperly report capabilties, we check to see if the host adapter - * in combination with the device (usually a disk) properly detect - * and acknowledge each end of the ribbon. - */ -int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) -{ - if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && - (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) && - (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) { - if (!HWIF(drive)->udma_four) { - printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", HWIF(drive)->name); - return 1; - } -#ifndef CONFIG_IDEDMA_IVB - if ((drive->id->hw_config & 0x6000) == 0) { -#else /* !CONFIG_IDEDMA_IVB */ - if (((drive->id->hw_config & 0x2000) == 0) || - ((drive->id->hw_config & 0x4000) == 0)) { -#endif /* CONFIG_IDEDMA_IVB */ - printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->name); - return 1; - } - } - return 0; -} - -/* - * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. - * 1 : Safe to update drive->id DMA registers. - * 0 : OOPs not allowed. - */ -int set_transfer (ide_drive_t *drive, ide_task_t *args) -{ - if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && - (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) && - (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) && - (drive->id->dma_ultra || - drive->id->dma_mword || - drive->id->dma_1word)) - return 1; - - return 0; -} - -/* - * All hosts that use the 80c ribbon mus use! - */ -byte eighty_ninty_three (ide_drive_t *drive) -{ - return ((byte) ((HWIF(drive)->udma_four) && -#ifndef CONFIG_IDEDMA_IVB - (drive->id->hw_config & 0x4000) && -#endif /* CONFIG_IDEDMA_IVB */ - (drive->id->hw_config & 0x6000)) ? 1 : 0); -} - -/* - * Similar to ide_wait_stat(), except it never calls ide_error internally. - * This is a kludge to handle the new ide_config_drive_speed() function, - * and should not otherwise be used anywhere. Eventually, the tuneproc's - * should be updated to return ide_startstop_t, in which case we can get - * rid of this abomination again. :) -ml - * - * It is gone.......... - * - * const char *msg == consider adding for verbose errors. - */ -int ide_config_drive_speed (ide_drive_t *drive, byte speed) -{ - ide_hwif_t *hwif = HWIF(drive); - int i, error = 1; - byte stat; - -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) - byte unit = (drive->select.b.unit & 0x01); - outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ - - /* - * Don't use ide_wait_cmd here - it will - * attempt to set_geometry and recalibrate, - * but for some reason these don't work at - * this point (lost interrupt). - */ - /* - * Select the drive, and issue the SETFEATURES command - */ - disable_irq(hwif->irq); /* disable_irq_nosync ?? */ - udelay(1); - SELECT_DRIVE(HWIF(drive), drive); - SELECT_MASK(HWIF(drive), drive, 0); - udelay(1); - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); - OUT_BYTE(speed, IDE_NSECTOR_REG); - OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); - OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); - if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); - udelay(1); - /* - * Wait for drive to become non-BUSY - */ - if ((stat = GET_STAT()) & BUSY_STAT) { - unsigned long flags, timeout; - __save_flags(flags); /* local CPU only */ - ide__sti(); /* local CPU only -- for jiffies */ - timeout = jiffies + WAIT_CMD; - while ((stat = GET_STAT()) & BUSY_STAT) { - if (0 < (signed long)(jiffies - timeout)) - break; - } - __restore_flags(flags); /* local CPU only */ - } - - /* - * Allow status to settle, then read it again. - * A few rare drives vastly violate the 400ns spec here, - * so we'll wait up to 10usec for a "good" status - * rather than expensively fail things immediately. - * This fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - if (OK_STAT((stat = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) { - error = 0; - break; - } - } - - SELECT_MASK(HWIF(drive), drive, 0); - - enable_irq(hwif->irq); - - if (error) { - (void) ide_dump_status(drive, "set_drive_speed_status", stat); - return error; - } - - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - -#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) - if (speed > XFER_PIO_4) { - outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2); - } else { - outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); - } -#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ - - switch(speed) { - case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; - case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; - case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; - case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; - case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; - case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; - case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; - case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; - case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; - case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; - case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; - case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; - case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; - case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; - default: break; - } - return error; -} - -EXPORT_SYMBOL(ide_auto_reduce_xfer); -EXPORT_SYMBOL(ide_driveid_update); -EXPORT_SYMBOL(ide_ata66_check); -EXPORT_SYMBOL(set_transfer); -EXPORT_SYMBOL(eighty_ninty_three); -EXPORT_SYMBOL(ide_config_drive_speed); - diff -urN linux-2.4.19-p7-pristine/drivers/ide/ide-floppy.c linux-2.4.19-p7/drivers/ide/ide-floppy.c --- linux-2.4.19-p7-pristine/drivers/ide/ide-floppy.c Tue Apr 16 03:15:16 2002 +++ linux-2.4.19-p7/drivers/ide/ide-floppy.c Mon Apr 22 20:28:33 2002 @@ -679,17 +679,46 @@ } #endif /* IDEFLOPPY_DEBUG_BUGS */ + +static int idefloppy_end_request (ide_drive_t *drive, int uptodate) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&io_request_lock, flags); + rq = HWGROUP(drive)->rq; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + } + + if (!end_that_request_first(rq, uptodate, drive->name)) { + add_blkdev_randomness(MAJOR(rq->rq_dev)); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return ret; +} + /* - * idefloppy_end_request is used to finish servicing a request. + * idefloppy_do_end_request is used to finish servicing a request. * * For read/write requests, we will call ide_end_request to pass to the * next buffer. */ -static void idefloppy_end_request (byte uptodate, ide_hwgroup_t *hwgroup) +static int idefloppy_do_end_request (ide_drive_t *drive, int uptodate) { - ide_drive_t *drive = hwgroup->drive; idefloppy_floppy_t *floppy = drive->driver_data; - struct request *rq = hwgroup->rq; + struct request *rq = HWGROUP(drive)->rq; int error; #if IDEFLOPPY_DEBUG_LOG @@ -705,13 +734,16 @@ floppy->failed_pc = NULL; /* Why does this happen? */ if (!rq) - return; + return 0; if (!IDEFLOPPY_RQ_CMD (rq->cmd)) { - ide_end_request (uptodate, hwgroup); - return; + /* our real local end request function */ + idefloppy_end_request(drive, uptodate); + return 0; } rq->errors = error; + /* fixme: need to move this local also */ ide_end_drive_cmd (drive, 0, 0); + return 0; } static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount) @@ -724,7 +756,7 @@ if (pc->b_count == bh->b_size) { rq->sector += rq->current_nr_sectors; rq->nr_sectors -= rq->current_nr_sectors; - idefloppy_end_request (1, HWGROUP(drive)); + idefloppy_do_end_request(drive, 1); if ((bh = rq->bh) != NULL) pc->b_count = 0; } @@ -749,7 +781,7 @@ if (!pc->b_count) { rq->sector += rq->current_nr_sectors; rq->nr_sectors -= rq->current_nr_sectors; - idefloppy_end_request (1, HWGROUP(drive)); + idefloppy_do_end_request(drive, 1); if ((bh = rq->bh) != NULL) { pc->b_data = bh->b_data; pc->b_count = bh->b_size; @@ -773,7 +805,7 @@ struct buffer_head *bh = rq->bh; while ((bh = rq->bh) != NULL) - idefloppy_end_request (1, HWGROUP(drive)); + idefloppy_do_end_request(drive, 1); } #endif /* CONFIG_BLK_DEV_IDEDMA */ @@ -836,10 +868,10 @@ #endif /* IDEFLOPPY_DEBUG_LOG */ if (!floppy->pc->error) { idefloppy_analyze_error (drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer); - idefloppy_end_request (1,HWGROUP (drive)); + idefloppy_do_end_request(drive, 1); } else { printk (KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n"); - idefloppy_end_request (0,HWGROUP (drive)); + idefloppy_do_end_request(drive, 0); } } @@ -854,7 +886,7 @@ printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_callback\n"); #endif /* IDEFLOPPY_DEBUG_LOG */ - idefloppy_end_request (floppy->pc->error ? 0:1, HWGROUP(drive)); + idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1); } /* @@ -939,7 +971,7 @@ #endif /* IDEFLOPPY_DEBUG_LOG */ clear_bit (PC_DMA_IN_PROGRESS, &pc->flags); - ide__sti(); /* local CPU only */ + local_irq_enable(); if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */ #if IDEFLOPPY_DEBUG_LOG @@ -985,7 +1017,9 @@ if (temp > pc->buffer_size) { printk (KERN_ERR "ide-floppy: The floppy wants to send us more data than expected - discarding data\n"); idefloppy_discard_data (drive,bcount.all); - ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); return ide_started; } #if IDEFLOPPY_DEBUG_LOG @@ -1007,7 +1041,9 @@ pc->actually_transferred+=bcount.all; /* Update the current position */ pc->current_position+=bcount.all; - ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* And set the interrupt handler again */ return ide_started; } @@ -1031,7 +1067,9 @@ printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); return ide_do_reset (drive); } - ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */ + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */ atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */ return ide_started; } @@ -1079,9 +1117,11 @@ * 25msec is too short, 40 and 50msec work well. idefloppy_pc_intr will * not be actually used until after the packet is moved in about 50 msec. */ - ide_set_handler (drive, + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, &idefloppy_pc_intr, /* service routine for packet command */ - floppy->ticks, /* wait this long before "failing" */ + floppy->ticks, /* wait this long before "failing" */ &idefloppy_transfer_pc2); /* fail == transfer_pc2 */ return ide_started; } @@ -1162,7 +1202,9 @@ } if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { - ide_set_handler (drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL); + if (HWGROUP(drive)->handler != NULL) + BUG(); + ide_set_handler(drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ return ide_started; } else { @@ -1177,7 +1219,7 @@ printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n"); #endif /* IDEFLOPPY_DEBUG_LOG */ - idefloppy_end_request(1, HWGROUP(drive)); + idefloppy_do_end_request(drive, 1); return; } @@ -1310,7 +1352,7 @@ drive->name, floppy->failed_pc->c[0], floppy->sense_key, floppy->asc, floppy->ascq); else printk (KERN_ERR "ide-floppy: %s: I/O error\n", drive->name); - idefloppy_end_request (0, HWGROUP(drive)); + idefloppy_do_end_request(drive, 0); return ide_stopped; } switch (rq->cmd) { @@ -1318,7 +1360,7 @@ case WRITE: if (rq->sector % floppy->bs_factor || rq->nr_sectors % floppy->bs_factor) { printk ("%s: unsupported r/w request size\n", drive->name); - idefloppy_end_request (0, HWGROUP(drive)); + idefloppy_do_end_request(drive, 0); return ide_stopped; } pc = idefloppy_next_pc_storage (drive); @@ -1329,7 +1371,7 @@ break; default: printk (KERN_ERR "ide-floppy: unsupported command %x in request queue\n", rq->cmd); - idefloppy_end_request (0,HWGROUP (drive)); + idefloppy_do_end_request(drive, 0); return ide_stopped; } pc->rq = rq; @@ -1659,10 +1701,9 @@ idefloppy_status_reg_t status; unsigned long flags; - __save_flags(flags); - __cli(); + local_irq_save(flags); status.all=GET_STAT(); - __restore_flags(flags); + local_irq_restore(flags); progress_indication= !status.b.dsc ? 0:0x10000; } @@ -2089,6 +2130,7 @@ #endif /* CONFIG_PROC_FS */ +int idefloppy_init (void); int idefloppy_reinit(ide_drive_t *drive); /* @@ -2099,13 +2141,21 @@ version: IDEFLOPPY_VERSION, media: ide_floppy, busy: 0, +#ifdef CONFIG_IDEDMA_ONLYDISK + supports_dma: 0, +#else supports_dma: 1, +#endif supports_dsc_overlap: 0, cleanup: idefloppy_cleanup, standby: NULL, + suspend: NULL, + resume: NULL, flushcache: NULL, do_request: idefloppy_do_request, - end_request: idefloppy_end_request, + end_request: idefloppy_do_end_request, + sense: NULL, + error: NULL, ioctl: idefloppy_ioctl, open: idefloppy_open, release: idefloppy_release, @@ -2115,12 +2165,12 @@ capacity: idefloppy_capacity, special: NULL, proc: idefloppy_proc, + init: idefloppy_init, reinit: idefloppy_reinit, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; -int idefloppy_init (void); static ide_module_t idefloppy_module = { IDE_DRIVER_MODULE, idefloppy_init, diff -urN linux-2.4.19-p7-pristine/drivers/ide/ide-pci.c linux-2.4.19-p7/drivers/ide/ide-pci.c --- linux-2.4.19-p7-pristine/drivers/ide/ide-pci.c Tue Apr 16 03:15:16 2002 +++ linux-2.4.19-p7/drivers/ide/ide-pci.c Mon Apr 22 18:00:46 2002 @@ -56,6 +56,7 @@ #define DEVID_PDC20268 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268}) #define DEVID_PDC20268R ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20268R}) #define DEVID_PDC20269 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20269}) +#define DEVID_PDC20271 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20271}) #define DEVID_PDC20275 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20275}) #define DEVID_PDC20276 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20276}) #define DEVID_RZ1000 ((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000}) @@ -78,12 +79,16 @@ #define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF}) #define DEVID_AEC6260 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860}) #define DEVID_AEC6260R ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R}) +#define DEVID_AEC6280 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865}) +#define DEVID_AEC6880 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R}) #define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105}) #define DEVID_UM8673F ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F}) #define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A}) #define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF}) #define DEVID_HPT34X ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343}) #define DEVID_HPT366 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT366}) +#define DEVID_HPT372 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT372}) +#define DEVID_HPT374 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT374}) #define DEVID_ALI15X3 ((ide_pci_devid_t){PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229}) #define DEVID_CY82C693 ((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693}) #define DEVID_HINT ((ide_pci_devid_t){0x3388, 0x8013}) @@ -96,21 +101,25 @@ #define DEVID_SLC90E66 ((ide_pci_devid_t){PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1}) #define DEVID_OSB4 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE}) #define DEVID_CSB5 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE}) +#define DEVID_CSB6 ((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE}) #define DEVID_ITE8172G ((ide_pci_devid_t){PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G}) #define IDE_IGNORE ((void *)-1) #define IDE_NO_DRIVER ((void *)-2) #ifdef CONFIG_BLK_DEV_AEC62XX +extern void aec6x80_device_fixup(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_aec62xx(struct pci_dev *, const char *); extern unsigned int ata66_aec62xx(ide_hwif_t *); extern void ide_init_aec62xx(ide_hwif_t *); extern void ide_dmacapable_aec62xx(ide_hwif_t *, unsigned long); +#define ORDER_AEC62XX &aec6x80_device_fixup #define PCI_AEC62XX &pci_init_aec62xx #define ATA66_AEC62XX &ata66_aec62xx #define INIT_AEC62XX &ide_init_aec62xx #define DMA_AEC62XX &ide_dmacapable_aec62xx #else +#define ORDER_AEC62XX NULL #define PCI_AEC62XX NULL #define ATA66_AEC62XX NULL #define INIT_AEC62XX IDE_NO_DRIVER @@ -168,11 +177,14 @@ #endif #ifdef CONFIG_BLK_DEV_CY82C693 +extern void cy82c693_device_fixup(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *); extern void ide_init_cy82c693(ide_hwif_t *); +#define ORDER_CY82C693 &cy82c693_device_fixup #define PCI_CY82C693 &pci_init_cy82c693 #define INIT_CY82C693 &ide_init_cy82c693 #else +#define ORDER_CY82C693 NULL #define PCI_CY82C693 NULL #define INIT_CY82C693 IDE_NO_DRIVER #endif @@ -188,11 +200,14 @@ #endif #ifdef CONFIG_BLK_DEV_HPT34X +extern void hpt343_device_fixup(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *); extern void ide_init_hpt34x(ide_hwif_t *); +#define ORDER_HPT34X &hpt343_device_fixup #define PCI_HPT34X &pci_init_hpt34x #define INIT_HPT34X &ide_init_hpt34x #else +#define ORDER_HPT34X NULL #define PCI_HPT34X NULL #define INIT_HPT34X IDE_IGNORE #endif @@ -200,10 +215,14 @@ #ifdef CONFIG_BLK_DEV_HPT366 extern byte hpt363_shared_irq; extern byte hpt363_shared_pin; +extern void hpt366_device_order_fixup(struct pci_dev *, ide_pci_device_t *); +extern void hpt374_device_order_fixup(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_hpt366(struct pci_dev *, const char *); extern unsigned int ata66_hpt366(ide_hwif_t *); extern void ide_init_hpt366(ide_hwif_t *); extern void ide_dmacapable_hpt366(ide_hwif_t *, unsigned long); +#define ORDER_HPT366 &hpt366_device_order_fixup +#define ORDER_HPT374 &hpt374_device_order_fixup #define PCI_HPT366 &pci_init_hpt366 #define ATA66_HPT366 &ata66_hpt366 #define INIT_HPT366 &ide_init_hpt366 @@ -211,6 +230,8 @@ #else static byte hpt363_shared_irq; static byte hpt363_shared_pin; +#define ORDER_HPT366 NULL +#define ORDER_HPT374 NULL #define PCI_HPT366 NULL #define ATA66_HPT366 NULL #define INIT_HPT366 IDE_NO_DRIVER @@ -225,9 +246,12 @@ #endif #ifdef CONFIG_BLK_DEV_OPTI621 +extern void opti621_device_fixup(struct pci_dev *, ide_pci_device_t *); extern void ide_init_opti621(ide_hwif_t *); +#define ORDER_OPTI621 &opti621_device_fixup #define INIT_OPTI621 &ide_init_opti621 #else +#define ORDER_OPTI621 NULL #define INIT_OPTI621 IDE_NO_DRIVER #endif @@ -248,13 +272,19 @@ #endif #ifdef CONFIG_BLK_DEV_PDC202XX +extern void pdc20265_device_fixup(struct pci_dev *, ide_pci_device_t *); +extern void pdc20270_device_order_fixup(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *); extern unsigned int ata66_pdc202xx(ide_hwif_t *); extern void ide_init_pdc202xx(ide_hwif_t *); +#define ORDER_PDC20265 &pdc20265_device_fixup +#define ORDER_PDC20270 &pdc20270_device_order_fixup #define PCI_PDC202XX &pci_init_pdc202xx #define ATA66_PDC202XX &ata66_pdc202xx #define INIT_PDC202XX &ide_init_pdc202xx #else +#define ORDER_PDC20265 IDE_IGNORE +#define ORDER_PDC20270 IDE_IGNORE #define PCI_PDC202XX IDE_IGNORE #define ATA66_PDC202XX IDE_IGNORE #define INIT_PDC202XX IDE_IGNORE @@ -274,15 +304,19 @@ #endif #ifdef CONFIG_BLK_DEV_IT8172 +extern void it8172_device_fixup(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_it8172(struct pci_dev *, const char *); extern unsigned int ata66_it8172(ide_hwif_t *); extern void ide_init_it8172(ide_hwif_t *); +#define ORDER_IT8172 &it8172_device_fixup #define PCI_IT8172 &pci_init_it8172 +#define ATA66_IT8172 &ata66_it8172 #define INIT_IT8172 &ide_init_it8172 #else +#define ORDER_IT8172 NULL #define PCI_IT8172 NULL #define ATA66_IT8172 NULL -#define INIT_IT8172 NULL +#define INIT_IT8172 IDE_NO_DRIVER #endif #ifdef CONFIG_BLK_DEV_RZ1000 @@ -295,16 +329,22 @@ #define INIT_SAMURAI NULL #ifdef CONFIG_BLK_DEV_SVWKS +extern void serverworks_csb6_fixup(struct pci_dev *, ide_pci_device_t *); extern unsigned int pci_init_svwks(struct pci_dev *, const char *); extern unsigned int ata66_svwks(ide_hwif_t *); extern void ide_init_svwks(ide_hwif_t *); +extern void ide_dmacapable_svwks(ide_hwif_t *, unsigned long); +#define ORDER_SVWKS &serverworks_csb6_fixup #define PCI_SVWKS &pci_init_svwks #define ATA66_SVWKS &ata66_svwks #define INIT_SVWKS &ide_init_svwks +#define DMA_SVWKS &ide_dmacapable_svwks #else +#define ORDER_SVWKS NULL #define PCI_SVWKS NULL #define ATA66_SVWKS NULL #define INIT_SVWKS IDE_NO_DRIVER +#define DMA_SVWKS NULL #endif #ifdef CONFIG_BLK_DEV_SIS5513 @@ -369,104 +409,91 @@ #define DMA_VIA82CXXX NULL #endif -typedef struct ide_pci_enablebit_s { - byte reg; /* byte pci reg holding the enable-bit */ - byte mask; /* mask to isolate the enable-bit */ - byte val; /* value of masked reg when "enabled" */ -} ide_pci_enablebit_t; - -typedef struct ide_pci_device_s { - ide_pci_devid_t devid; - char *name; - unsigned int (*init_chipset)(struct pci_dev *dev, const char *name); - unsigned int (*ata66_check)(ide_hwif_t *hwif); - void (*init_hwif)(ide_hwif_t *hwif); - void (*dma_init)(ide_hwif_t *hwif, unsigned long dmabase); - ide_pci_enablebit_t enablebits[2]; - byte bootable; - unsigned int extra; -} ide_pci_device_t; - static ide_pci_device_t ide_pci_chipsets[] __initdata = { - {DEVID_PIIXa, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIXb, "PIIX", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_MPIIX, "MPIIX", NULL, NULL, INIT_PIIX, NULL, {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX3, "PIIX3", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4E, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4E2, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4U, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4U2, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4NX, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4U3, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4U4, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4U5, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_PIIX4U6, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_MR_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, - {DEVID_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, + {DEVID_PIIXa, "PIIX", NULL, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIXb, "PIIX", NULL, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_MPIIX, "MPIIX", NULL, NULL, NULL, INIT_PIIX, NULL, {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX3, "PIIX3", NULL, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4, "PIIX4", NULL, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4E, "PIIX4", NULL, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4E2, "PIIX4", NULL, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U, "PIIX4", NULL, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U2, "PIIX4", NULL, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4NX, "PIIX4", NULL, PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U3, "PIIX4", NULL, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U4, "PIIX4", NULL, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U5, "PIIX4", NULL, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4U6, "PIIX4", NULL, PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_MR_IDE, "VP_IDE", NULL, PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, + {DEVID_VP_IDE, "VP_IDE", NULL, PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, #ifdef CONFIG_PDC202XX_FORCE - {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 16 }, - {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, - {DEVID_PDC20265,"PDC20265", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 48 }, - {DEVID_PDC20267,"PDC20267", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, + {DEVID_PDC20246,"PDC20246", NULL, PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 16 }, + {DEVID_PDC20262,"PDC20262", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, + {DEVID_PDC20265,"PDC20265", ORDER_PDC20265, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 48 }, + {DEVID_PDC20267,"PDC20267", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 48 }, #else /* !CONFIG_PDC202XX_FORCE */ - {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, - {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_PDC20265,"PDC20265", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, - {DEVID_PDC20267,"PDC20267", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, -#endif - {DEVID_PDC20268,"PDC20268", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - /* Promise used a different PCI ident for the raid card apparently to try and - prevent Linux detecting it and using our own raid code. We want to detect - it for the ataraid drivers, so we have to list both here.. */ - {DEVID_PDC20268R,"PDC20270", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20269,"PDC20269", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20275,"PDC20275", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_PDC20276,"PDC20276", PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_RZ1000, "RZ1000", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_RZ1001, "RZ1001", NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_SAMURAI, "SAMURAI", NULL, NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD640, "CMD640", NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87410, "NS87410", NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, - {DEVID_SIS5513, "SIS5513", PCI_SIS5513, ATA66_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, - {DEVID_CMD643, "CMD643", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD646, "CMD646", PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_CMD648, "CMD648", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CMD649, "CMD649", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, -#ifndef CONFIG_BLK_DEV_CMD680 - {DEVID_CMD680, "CMD680", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, -#else /* CONFIG_BLK_DEV_CMD680 */ - {DEVID_CMD680, "CMD680", PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, -#endif /* !CONFIG_BLK_DEV_CMD680 */ - {DEVID_HT6565, "HT6565", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621, "OPTI621", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_OPTI621X,"OPTI621X", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, - {DEVID_TRM290, "TRM290", NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_NS87415, "NS87415", NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AEC6210, "AEC6210", PCI_AEC62XX, NULL, INIT_AEC62XX, DMA_AEC62XX, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {DEVID_AEC6260, "AEC6260", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, - {DEVID_AEC6260R,"AEC6260R", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, - {DEVID_W82C105, "W82C105", PCI_W82C105, NULL, INIT_W82C105, DMA_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, - {DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HPT34X, "HPT34X", PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, - {DEVID_HPT366, "HPT366", PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 }, - {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CY82C693,"CY82C693", PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CS5530, "CS5530", PCI_CS5530, NULL, INIT_CS5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_AMD7401, "AMD7401", NULL, NULL, NULL, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7409, "AMD7409", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7411, "AMD7411", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_AMD7441, "AMD7441", PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, - {DEVID_PDCADMA, "PDCADMA", PCI_PDCADMA, ATA66_PDCADMA, INIT_PDCADMA, DMA_PDCADMA, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, - {DEVID_SLC90E66,"SLC90E66", PCI_SLC90E66, ATA66_SLC90E66, INIT_SLC90E66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, - {DEVID_OSB4, "ServerWorks OSB4", PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_CSB5, "ServerWorks CSB5", PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, - {DEVID_ITE8172G,"IT8172G", PCI_IT8172, NULL, INIT_IT8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0 }, - {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; + {DEVID_PDC20246,"PDC20246", NULL, PCI_PDC202XX, NULL, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, + {DEVID_PDC20262,"PDC20262", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, + {DEVID_PDC20265,"PDC20265", ORDER_PDC20265, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, + {DEVID_PDC20267,"PDC20267", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, +#endif + {DEVID_PDC20268,"PDC20268", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + /* + * Promise used a different PCI ident for the raid card apparently + * to try and prevent Linux detecting it and using our own raid code. + * We want to detect it for the ataraid drivers, so we have to list + * both here.. + */ + {DEVID_PDC20268R,"PDC20270", ORDER_PDC20270, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_PDC20269,"PDC20269", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_PDC20271,"PDC20271", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_PDC20275,"PDC20275", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_PDC20276,"PDC20276", NULL, PCI_PDC202XX, ATA66_PDC202XX, INIT_PDC202XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_RZ1000, "RZ1000", NULL, NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_RZ1001, "RZ1001", NULL, NULL, NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_SAMURAI, "SAMURAI", NULL, NULL, NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD640, "CMD640", NULL, NULL, NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_NS87410, "NS87410", NULL, NULL, NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0 }, + {DEVID_SIS5513, "SIS5513", NULL, PCI_SIS5513, ATA66_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 0 }, + {DEVID_CMD643, "CMD643", NULL, PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD646, "CMD646", NULL, PCI_CMD64X, NULL, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_CMD648, "CMD648", NULL, PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD649, "CMD649", NULL, PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD680, "CMD680", NULL, PCI_CMD64X, ATA66_CMD64X, INIT_CMD64X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_HT6565, "HT6565", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_OPTI621, "OPTI621", ORDER_OPTI621, NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, + {DEVID_OPTI621X,"OPTI621X", ORDER_OPTI621, NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 }, + {DEVID_TRM290, "TRM290", NULL, NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_NS87415, "NS87415", NULL, NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_AEC6210, "AEC6210", NULL, PCI_AEC62XX, NULL, INIT_AEC62XX, DMA_AEC62XX, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, + {DEVID_AEC6260, "AEC6260", NULL, PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, + {DEVID_AEC6260R,"AEC6260R", NULL, PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, + {DEVID_AEC6280, "AEC6X80", ORDER_AEC62XX, PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 }, + {DEVID_AEC6880, "AEC6X80R", ORDER_AEC62XX, PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 }, + {DEVID_W82C105, "W82C105", NULL, PCI_W82C105, NULL, INIT_W82C105, DMA_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 }, + {DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_HPT34X, "HPT34X", ORDER_HPT34X, PCI_HPT34X, NULL, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 }, + {DEVID_HPT366, "HPT366", ORDER_HPT366, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 240 }, + {DEVID_HPT372, "HPT372", NULL, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_HPT374, "HPT374", ORDER_HPT374, PCI_HPT366, ATA66_HPT366, INIT_HPT366, DMA_HPT366, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_ALI15X3, "ALI15X3", NULL, PCI_ALI15X3, ATA66_ALI15X3, INIT_ALI15X3, DMA_ALI15X3, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CY82C693,"CY82C693", ORDER_CY82C693, PCI_CY82C693, NULL, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CS5530, "CS5530", NULL, PCI_CS5530, NULL, INIT_CS5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_AMD7401, "AMD7401", NULL, NULL, NULL, NULL, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, + {DEVID_AMD7409, "AMD7409", NULL, PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, + {DEVID_AMD7411, "AMD7411", NULL, PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, + {DEVID_AMD7441, "AMD7441", NULL, PCI_AMD74XX, ATA66_AMD74XX, INIT_AMD74XX, DMA_AMD74XX, {{0x40,0x01,0x01}, {0x40,0x02,0x02}}, ON_BOARD, 0 }, + {DEVID_PDCADMA, "PDCADMA", NULL, PCI_PDCADMA, ATA66_PDCADMA, INIT_PDCADMA, DMA_PDCADMA, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_SLC90E66,"SLC90E66", NULL, PCI_SLC90E66, ATA66_SLC90E66, INIT_SLC90E66, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_OSB4, "SvrWks OSB4", NULL, PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CSB5, "SvrWks CSB5", NULL, PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, DMA_SVWKS, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CSB6, "SvrWks CSB6", ORDER_SVWKS, PCI_SVWKS, ATA66_SVWKS, INIT_SVWKS, DMA_SVWKS, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_ITE8172G,"IT8172G", ORDER_IT8172, PCI_IT8172, NULL, INIT_IT8172, NULL, {{0x00,0x00,0x00}, {0x40,0x00,0x01}}, ON_BOARD, 0 }, + {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }}; /* * This allows offboard ide-pci cards the enable a BIOS, verify interrupt @@ -477,6 +504,7 @@ { switch(dev->device) { case PCI_DEVICE_ID_TTI_HPT366: + case PCI_DEVICE_ID_TTI_HPT374: case PCI_DEVICE_ID_PROMISE_20246: case PCI_DEVICE_ID_PROMISE_20262: case PCI_DEVICE_ID_PROMISE_20265: @@ -484,11 +512,17 @@ case PCI_DEVICE_ID_PROMISE_20268: case PCI_DEVICE_ID_PROMISE_20268R: case PCI_DEVICE_ID_PROMISE_20269: + case PCI_DEVICE_ID_PROMISE_20271: case PCI_DEVICE_ID_PROMISE_20275: case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_ARTOP_ATP850UF: case PCI_DEVICE_ID_ARTOP_ATP860: case PCI_DEVICE_ID_ARTOP_ATP860R: + /* + * case PCI_DEVICE_ID_ARTOP_ATP865: + * same device ID value as PCI_DEVICE_ID_TTI_HPT374 + */ + case PCI_DEVICE_ID_ARTOP_ATP865R: return dev->irq; default: break; @@ -526,7 +560,8 @@ if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { if (hwif->chipset == ide_unknown) return hwif; /* match */ - printk("%s: port 0x%04lx already claimed by %s\n", name, io_base, hwif->name); + printk("%s: port 0x%04lx already claimed by %s\n", + name, io_base, hwif->name); return NULL; /* already claimed */ } } @@ -569,9 +604,11 @@ /* * Place both IDE interfaces into PCI "native" mode: */ - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || (progif & 5) != 5) { + if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || + (progif & 5) != 5) { if ((progif & 0xa) != 0xa) { - printk("%s: device not capable of full native PCI mode\n", name); + printk("%s: device not capable of full " + "native PCI mode\n", name); return 1; } printk("%s: placing both ports into native PCI mode\n", name); @@ -606,7 +643,7 @@ * we "know" about, this information is in the ide_pci_device_t struct; * for all other chipsets, we just assume both interfaces are enabled. */ -static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d) +void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d) { unsigned int port, at_least_one_hwif_enabled = 0, autodma = 0, pciirq = 0; unsigned short pcicmd = 0, tried_config = 0; @@ -621,12 +658,14 @@ #endif if (d->init_hwif == IDE_NO_DRIVER) { - printk(KERN_WARNING "%s: detected chipset, but driver not compiled in!\n", d->name); + printk(KERN_WARNING "%s: detected chipset, " + "but driver not compiled in!\n", d->name); d->init_hwif = NULL; } if (pci_enable_device(dev)) { - printk(KERN_WARNING "%s: (ide_setup_pci_device:) Could not enable device.\n", d->name); + printk(KERN_WARNING "%s: (ide_setup_pci_device:) " + "Could not enable device.\n", d->name); return; } @@ -657,14 +696,6 @@ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); class_rev &= 0xff; - - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) { - /* see comments in hpt34x.c on why..... */ - char *chipset_names[] = {"HPT343", "HPT345"}; - strcpy(d->name, chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0]); - d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; - } - printk("%s: chipset revision %d\n", d->name, class_rev); /* @@ -672,27 +703,9 @@ */ pciirq = dev->irq; - if (dev->class >> 8 == PCI_CLASS_STORAGE_RAID) - { - /* By rights we want to ignore these, but the Promise Fastrak - people have some strange ideas about proprietary so we have - to act otherwise on those. The supertrak however we need - to skip */ - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) - { - printk(KERN_INFO "ide: Found promise 20265 in RAID mode.\n"); - if(dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_INTEL && - dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960) - { - printk(KERN_INFO "ide: Skipping Promise PDC20265 attached to I2O RAID controller.\n"); - return; - } - } - /* Its attached to something else, just a random bridge. - Suspect a fastrak and fall through */ - } if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { - printk("%s: not 100%% native mode: will probe irqs later\n", d->name); + printk("%s: not 100%% native mode: " + "will probe irqs later\n", d->name); /* * This allows offboard ide-pci cards the enable a BIOS, * verify interrupt settings of split-mirror pci-config @@ -725,34 +738,50 @@ ide_pci_enablebit_t *e = &(d->enablebits[port]); /* - * If this is a Promise FakeRaid controller, the 2nd controller will be marked as - * disabled while it is actually there and enabled by the bios for raid purposes. + * If this is a Promise FakeRaid controller, + * the 2nd controller will be marked as + * disabled while it is actually there and enabled + * by the bios for raid purposes. * Skip the normal "is it enabled" test for those. */ - if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) && (secondpdc++==1) && (port==1) ) + if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20265)) && + (secondpdc++==1) && (port==1)) goto controller_ok; - if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262)) && (secondpdc++==1) && (port==1) ) + if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262)) && + (secondpdc++==1) && (port==1)) goto controller_ok; - if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val)) + if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || + (tmp & e->mask) != e->val)) continue; /* port not enabled */ controller_ok: - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev < 0x03)) + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && + (port) && (class_rev < 0x03)) + return; + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CSB6) && + (port) && (!(PCI_FUNC(dev->devfn) & 1))) return; - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) { + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || + (dev->class & (port ? 4 : 1)) != 0) { ctl = dev->resource[(2*port)+1].start; base = dev->resource[2*port].start; if (!(ctl & PCI_BASE_ADDRESS_IO_MASK) || !(base & PCI_BASE_ADDRESS_IO_MASK)) { - printk("%s: IO baseregs (BIOS) are reported as MEM, report to .\n", d->name); + printk("%s: IO baseregs (BIOS) are reported " + "as MEM, report to " + ".\n", d->name); #if 0 - /* FIXME! This really should check that it really gets the IO/MEM part right! */ + /* + * FIXME! This really should check that + * it really gets the IO/MEM part right! + */ continue; #endif } } if ((ctl && !base) || (base && !ctl)) { - printk("%s: inconsistent baseregs (BIOS) for port %d, skipping\n", d->name, port); + printk("%s: inconsistent baseregs (BIOS) " + "for port %d, skipping\n", d->name, port); continue; } if (!ctl) @@ -791,7 +820,8 @@ if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDCADMA)) goto bypass_legacy_dma; if (hwif->udma_four) { - printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", d->name); + printk("%s: ATA-66/100 forced bit set (WARNING)!!\n", + d->name); } else { hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0; } @@ -814,13 +844,17 @@ IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268R) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20269) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20271) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20275) || IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20276) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) || IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6280) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6880) || IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) || IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) || + IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT374) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) || IDE_PCI_DEVID_EQ(d->devid, DEVID_CMD646) || @@ -865,102 +899,6 @@ printk("%s: neither IDE port enabled (BIOS)\n", d->name); } -static void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) -{ - struct pci_dev *dev2 = NULL, *findev; - ide_pci_device_t *d2; - - if ((dev->bus->self && - dev->bus->self->vendor == PCI_VENDOR_ID_DEC) && - (dev->bus->self->device == PCI_DEVICE_ID_DEC_21150)) { - if (PCI_SLOT(dev->devfn) & 2) { - return; - } - d->extra = 0; - pci_for_each_dev(findev) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - (PCI_SLOT(findev->devfn) & 2)) { - byte irq = 0, irq2 = 0; - dev2 = findev; - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); - pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); - if (irq != irq2) { - dev2->irq = dev->irq; - pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, irq); - } - - } - } - } - - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - if (!dev2) - return; - d2 = d; - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn); - ide_setup_pci_device(dev2, d2); -} - -static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) -{ - struct pci_dev *dev2 = NULL, *findev; - ide_pci_device_t *d2; - unsigned char pin1 = 0, pin2 = 0; - unsigned int class_rev; - char *chipset_names[] = {"HPT366", "HPT366", "HPT368", "HPT370", "HPT370A", "HPT372"}; - - if (PCI_FUNC(dev->devfn) & 1) - return; - - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; - if (class_rev > 5) - class_rev = 5; - - strcpy(d->name, chipset_names[class_rev]); - - switch(class_rev) { - case 4: - case 3: printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - return; - default: break; - } - - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); - pci_for_each_dev(findev) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - ((findev->devfn - dev->devfn) == 1) && - (PCI_FUNC(findev->devfn) & 1)) { - dev2 = findev; - pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); - hpt363_shared_pin = (pin1 != pin2) ? 1 : 0; - hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0; - if (hpt363_shared_pin && hpt363_shared_irq) { - d->bootable = ON_BOARD; - printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2); -#if 0 - /* I forgot why I did this once, but it fixed something. */ - pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq); - printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2); - pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0); -#endif - } - break; - } - } - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); - ide_setup_pci_device(dev, d); - if (!dev2) - return; - d2 = d; - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn); - ide_setup_pci_device(dev2, d2); -} - /* * ide_scan_pcibus() gets invoked at boot time from ide.c. * It finds all PCI IDE controllers and calls ide_setup_pci_device for them. @@ -972,27 +910,32 @@ devid.vid = dev->vendor; devid.did = dev->device; - for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d); + for (d = ide_pci_chipsets; + d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d); + if (d->init_hwif == IDE_IGNORE) - printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name); - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1)) + printk("%s: ignored by ide_scan_pci_device() " + "(uses own driver)\n", d->name); + else if (d->order_fix) + d->order_fix(dev, d); +#if 0 + else if (((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) && + (!(PCI_FUNC(dev->devfn) & 1))) return; - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) - return; /* CY82C693 is more than only a IDE controller */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_ITE8172G) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) - return; /* IT8172G is also more than only an IDE controller */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1)) +#endif + else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && + (!(PCI_FUNC(dev->devfn) & 1))) return; /* UM8886A/BF pair */ - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366)) - hpt366_device_order_fixup(dev, d); - else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20268R)) - pdc20270_device_order_fixup(dev, d); - else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { + else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || + (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL)) - printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n", - d->name, dev->bus->number, dev->devfn, devid.vid, devid.did); + printk("%s: unknown IDE controller on PCI bus " + "%02x device %02x, VID=%04x, DID=%04x\n", + d->name, dev->bus->number, dev->devfn, + devid.vid, devid.did); else - printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn); + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); ide_setup_pci_device(dev, d); } } diff -urN linux-2.4.19-p7-pristine/drivers/ide/ide-pmac.c linux-2.4.19-p7/drivers/ide/ide-pmac.c --- linux-2.4.19-p7-pristine/drivers/ide/ide-pmac.c Tue Apr 16 03:15:16 2002 +++ linux-2.4.19-p7/drivers/ide/ide-pmac.c Tue Apr 16 23:16:57 2002 @@ -44,7 +44,6 @@ #endif #include "ide_modes.h" -extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc); extern void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq); #define IDE_PMAC_DEBUG @@ -362,41 +361,6 @@ } -/* Note: We don't use the generic routine here because for some - * yet unexplained reasons, it cause some media-bay CD-ROMs to - * lockup the bus. Strangely, this new version of the code is - * almost identical to the generic one and works, I've not yet - * managed to figure out what bit is causing the lockup in the - * generic code, possibly a timing issue... - * - * --BenH - */ -static int __pmac -wait_for_ready(ide_drive_t *drive) -{ - /* Timeout bumped for some powerbooks */ - int timeout = 2000; - byte stat; - - while(--timeout) { - stat = GET_STAT(); - if(!(stat & BUSY_STAT)) { - if (drive->ready_stat == 0) - break; - else if((stat & drive->ready_stat) || (stat & ERR_STAT)) - break; - } - mdelay(1); - } - if((stat & ERR_STAT) || timeout <= 0) { - if (stat & ERR_STAT) { - printk(KERN_ERR "ide_pmac: wait_for_ready, error status: %x\n", stat); - } - return 1; - } - return 0; -} - static int __pmac pmac_ide_do_setfeature(ide_drive_t *drive, byte command) { @@ -410,7 +374,7 @@ SELECT_MASK(HWIF(drive), drive, 0); udelay(1); (void)GET_STAT(); /* Get rid of pending error state */ - if(wait_for_ready(drive)) { + if(wait_for_ready(drive, 2000)) { /* Timeout bumped for some powerbooks */ printk(KERN_ERR "pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n"); goto out; } @@ -420,10 +384,9 @@ OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); udelay(1); - __save_flags(flags); /* local CPU only */ - ide__sti(); /* local CPU only -- for jiffies */ - result = wait_for_ready(drive); - __restore_flags(flags); /* local CPU only */ + local_irq_set(flags); + result = wait_for_ready(drive, 2000); /* Timeout bumped for some powerbooks */ + local_irq_restore(flags); OUT_BYTE(drive->ctl, IDE_CONTROL_REG); if (result) printk(KERN_ERR "pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n"); @@ -1074,8 +1037,6 @@ unsigned char *virt_addr = rq->buffer; int sector_count = rq->nr_sectors; -// if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA) || -// (args->tfRegister[IDE_COMMAND_OFFSET] == WIN_WRITEDMA_EXT)) if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE) pmif->sg_dma_direction = PCI_DMA_TODEVICE; else @@ -1375,12 +1336,14 @@ drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && - (drive->addressing == 1)) { + (drive->addressing)) { ide_task_t *args = HWGROUP(drive)->rq->special; OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); - } else if (drive->addressing) { + } else if (drive->addressing == 1) { OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); } else { OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); diff -urN linux-2.4.19-p7-pristine/drivers/ide/ide-probe.c linux-2.4.19-p7/drivers/ide/ide-probe.c --- linux-2.4.19-p7-pristine/drivers/ide/ide-probe.c Tue Apr 16 03:15:16 2002 +++ linux-2.4.19-p7/drivers/ide/ide-probe.c Fri Apr 19 19:07:39 2002 @@ -43,6 +43,11 @@ #include #include #include + +#ifdef CONFIG_BLK_DEV_IDEPCI +#include +#endif + #include #include #include @@ -62,9 +67,19 @@ printk(KERN_WARNING "(ide-probe::do_identify) Out of memory.\n"); goto err_kmalloc; } - - ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */ - ide__sti(); /* local CPU only */ + /* read 512 bytes of id info */ +#if 1 + ata_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */ +#else + { + unsigned long *ptr = (unsigned long *)id ; + unsigned long lcount = 256/2 ; + // printk("IDE_DATA_REG = %#lx",IDE_DATA_REG); + while( lcount-- ) + *ptr++ = inl(IDE_DATA_REG); + } +#endif + local_irq_enable(); ide_fix_driveid(id); if (id->word156 == 0x4d42) { @@ -235,7 +250,7 @@ timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; timeout += jiffies; do { - if (0 < (signed long)(jiffies - timeout)) { + if (time_after(jiffies, timeout)) { return 1; /* drive timed-out */ } ide_delay_50ms(); /* give drive a breather */ @@ -244,12 +259,12 @@ ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only; some systems need this */ + local_irq_save(flags); + /* local CPU only; some systems need this */ do_identify(drive, cmd); /* drive returned ID */ rc = 0; /* drive responded with ID */ (void) GET_STAT(); /* clear drive IRQ */ - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); } else rc = 2; /* drive refused ID */ return rc; @@ -530,8 +545,7 @@ return; } - __save_flags(flags); /* local CPU only */ - __sti(); /* local CPU only; needed for jiffies and irq probing */ + local_irq_set(flags); /* * Second drive should only exist if first drive was found, * but a lot of cdrom drives are configured as single slaves. @@ -557,10 +571,10 @@ do { ide_delay_50ms(); stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); - } while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies)); + } while ((stat & BUSY_STAT) && time_after(timeout, jiffies)); } - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; if (drive->present) { @@ -614,6 +628,7 @@ } } +#undef __IRQ_HELL_SPIN /* * This routine sets up the irq for an ide interface, and creates a new * hwgroup for the irq/hwif if none was previously assigned. @@ -639,8 +654,11 @@ new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL); - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ +#ifndef __IRQ_HELL_SPIN + save_and_cli(flags); +#else + spin_lock_irqsave(&io_request_lock, flags); +#endif hwif->hwgroup = NULL; #if MAX_HWIFS > 1 @@ -677,7 +695,11 @@ } else { hwgroup = new_hwgroup; if (!hwgroup) { - restore_flags(flags); /* all CPUs */ +#ifndef __IRQ_HELL_SPIN + restore_flags(flags); +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif return 1; } memset(hwgroup, 0, sizeof(ide_hwgroup_t)); @@ -707,11 +729,25 @@ if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) { if (!match) kfree(hwgroup); - restore_flags(flags); /* all CPUs */ +#ifndef __IRQ_HELL_SPIN + restore_flags(flags); +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif return 1; } } +#ifdef CONFIG_BLK_DEV_IDEPCI + /* + * FIXME: some hosts can not support 48 bit proper, + * for now we default it enabled, this will continue to break + * a few systems that are already broken. + */ + hwgroup->addressing = IDE_CHIPSET_IS_PCI(hwif->chipset) ? 1 : 0; +#else + hwgroup->addressing = 1; +#endif /* * Everything is okay, so link us into the hwgroup */ @@ -735,7 +771,12 @@ printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name); #endif } - restore_flags(flags); /* all CPUs; safe now that hwif->hwgroup is set up */ +#ifndef __IRQ_HELL_SPIN + restore_flags(flags); +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif + /* all CPUs; safe now that hwif->hwgroup is set up */ #if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name, @@ -892,7 +933,8 @@ } #ifdef CONFIG_BLK_DEV_HD if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) { - printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", hwif->name); + printk("%s: CANNOT SHARE IRQ WITH OLD " + "HARDDISK DRIVER (hd.c)\n", hwif->name); return (hwif->present = 0); } #endif /* CONFIG_BLK_DEV_HD */ @@ -900,7 +942,8 @@ hwif->present = 0; /* we set it back to 1 if all is ok below */ if (devfs_register_blkdev (hwif->major, hwif->name, ide_fops)) { - printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major); + printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", + hwif->name, hwif->major); return (hwif->present = 0); } @@ -911,7 +954,8 @@ * this port and try that. */ if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) { - printk("%s: Disabled unable to get IRQ %d.\n", hwif->name, i); + printk("%s: Disabled unable to get IRQ %d.\n", + hwif->name, i); (void) unregister_blkdev (hwif->major, hwif->name); return (hwif->present = 0); } diff -urN linux-2.4.19-p7-pristine/drivers/ide/ide-proc.c linux-2.4.19-p7/drivers/ide/ide-proc.c --- linux-2.4.19-p7-pristine/drivers/ide/ide-proc.c Tue Apr 16 03:15:16 2002 +++ linux-2.4.19-p7/drivers/ide/ide-proc.c Tue Apr 16 23:16:57 2002 @@ -160,6 +160,8 @@ static struct proc_dir_entry * proc_ide_root = NULL; +#undef __PROC_HELL + static int proc_ide_write_config (struct file *file, const char *buffer, unsigned long count, void *data) { @@ -181,7 +183,11 @@ * Do one full pass to verify all parameters, * then do another to actually write the regs. */ +#ifndef __PROC_HELL save_flags(flags); /* all CPUs */ +#else + spin_lock_irqsave(&io_request_lock, flags); +#endif do { const char *p; if (for_real) { @@ -190,15 +196,32 @@ ide_hwgroup_t *mategroup = NULL; if (hwif->mate && hwif->mate->hwgroup) mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup); +#ifndef __PROC_HELL cli(); /* all CPUs; ensure all writes are done together */ - while (mygroup->busy || (mategroup && mategroup->busy)) { +#else + spin_lock_irqsave(&io_request_lock, flags); +#endif + while (mygroup->busy || + (mategroup && mategroup->busy)) { +#ifndef __PROC_HELL sti(); /* all CPUs */ - if (0 < (signed long)(jiffies - timeout)) { +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif + if (time_after(jiffies, timeout)) { printk("/proc/ide/%s/config: channel(s) busy, cannot write\n", hwif->name); +#ifndef __PROC_HELL restore_flags(flags); /* all CPUs */ +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif return -EBUSY; } +#ifndef __PROC_HELL cli(); /* all CPUs */ +#else + spin_lock_irqsave(&io_request_lock, flags); +#endif } } p = buffer; @@ -281,7 +304,11 @@ break; } if (rc) { +#ifndef __PROC_HELL restore_flags(flags); /* all CPUs */ +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n", msg, dev->bus->number, dev->devfn, reg, val); printk("proc_ide_write_config: error %d\n", rc); @@ -323,10 +350,18 @@ } } } while (!for_real++); +#ifndef __PROC_HELL restore_flags(flags); /* all CPUs */ +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif return count; parse_error: +#ifndef __PROC_HELL restore_flags(flags); /* all CPUs */ +#else + spin_unlock_irqrestore(&io_request_lock, flags); +#endif printk("parse error\n"); return xx_xx_parse_error(start, startn, msg); } @@ -446,26 +481,13 @@ PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } -static int proc_ide_get_identify(ide_drive_t *drive, byte *buf) -{ - struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; - memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); - memset(&hobfile, 0, sizeof(struct hd_drive_hob_hdr)); - - taskfile.sector_count = 0x01; - taskfile.command = (drive->media == ide_disk) ? WIN_IDENTIFY : WIN_PIDENTIFY ; - - return ide_wait_taskfile(drive, &taskfile, &hobfile, buf); -} - static int proc_ide_read_identify (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *)data; int len = 0, i = 0; - if (drive && !proc_ide_get_identify(drive, page)) { + if (drive && !taskfile_lib_get_identify(drive, page)) { unsigned short *val = (unsigned short *) page; char *out = ((char *)val) + (SECTOR_WORDS * 4); page = out; diff -urN linux-2.4.19-p7-pristine/drivers/ide/ide-tape.c linux-2.4.19-p7/drivers/ide/ide-tape.c --- linux-2.4.19-p7-pristine/drivers/ide/ide-tape.c Tue Apr 16 03:15:16 2002 +++ linux-2.4.19-p7/drivers/ide/ide-tape.c Mon Apr 22 20:28:33 2002 @@ -1835,10 +1835,9 @@ * idetape_end_request is used to finish servicing a request, and to * insert a pending pipeline request into the main device queue. */ -static void idetape_end_request (byte uptodate, ide_hwgroup_t *hwgroup) +static int idetape_end_request (ide_drive_t *drive, int uptodate) { - ide_drive_t *drive = hwgroup->drive; - struct request *rq = hwgroup->rq; + struct request *rq = HWGROUP(drive)->rq; idetape_tape_t *tape = drive->driver_data; unsigned long flags; int error; @@ -1932,6 +1931,7 @@ if (tape->active_data_request == NULL) clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); spin_unlock_irqrestore(&tape->spinlock, flags); + return 0; } static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive) @@ -1944,10 +1944,10 @@ #endif /* IDETAPE_DEBUG_LOG */ if (!tape->pc->error) { idetape_analyze_error (drive, (idetape_request_sense_result_t *) tape->pc->buffer); - idetape_end_request (1, HWGROUP (drive)); + idetape_end_request(drive, 1); } else { printk (KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n"); - idetape_end_request (0, HWGROUP (drive)); + idetape_end_request(drive, 0); } return ide_stopped; } @@ -2090,7 +2090,7 @@ #endif /* IDETAPE_DEBUG_LOG */ clear_bit (PC_DMA_IN_PROGRESS, &pc->flags); - ide__sti(); /* local CPU only */ + local_irq_enable(); #if SIMULATE_ERRORS if ((pc->c[0] == IDETAPE_WRITE_CMD || pc->c[0] == IDETAPE_READ_CMD) && (++error_sim_count % 100) == 0) { @@ -2154,6 +2154,8 @@ if (temp > pc->buffer_size) { printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n"); idetape_discard_data (drive, bcount.all); + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); return ide_started; } @@ -2180,6 +2182,8 @@ if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all); #endif + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* And set the interrupt handler again */ return ide_started; } @@ -2254,6 +2258,8 @@ return ide_do_reset (drive); } tape->cmd_start_time = jiffies; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */ atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */ return ide_started; @@ -2327,6 +2333,8 @@ } #endif /* CONFIG_BLK_DEV_IDEDMA */ if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); return ide_started; @@ -2348,7 +2356,7 @@ printk (KERN_INFO "ide-tape: Reached idetape_pc_callback\n"); #endif /* IDETAPE_DEBUG_LOG */ - idetape_end_request (tape->pc->error ? 0 : 1, HWGROUP(drive)); + idetape_end_request(drive, tape->pc->error ? 0 : 1); return ide_stopped; } @@ -2397,7 +2405,7 @@ if (tape->debug_level >= 1) printk(KERN_INFO "ide-tape: buffer fill callback, %d/%d\n", tape->cur_frames, tape->max_frames); #endif - idetape_end_request (tape->pc->error ? 0 : 1, HWGROUP(drive)); + idetape_end_request(drive, tape->pc->error ? 0 : 1); return ide_stopped; } @@ -2517,9 +2525,9 @@ rq->current_nr_sectors -= blocks; if (!tape->pc->error) - idetape_end_request (1, HWGROUP (drive)); + idetape_end_request(drive, 1); else - idetape_end_request (tape->pc->error, HWGROUP (drive)); + idetape_end_request(drive, tape->pc->error); return ide_stopped; } @@ -2607,6 +2615,38 @@ } /* + * This is our end_request replacement function. + */ +static int idetape_do_end_request (ide_drive_t *drive, int uptodate) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&io_request_lock, flags); + rq = HWGROUP(drive)->rq; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + } + + if (!end_that_request_first(rq, uptodate, drive->name)) { + add_blkdev_randomness(MAJOR(rq->rq_dev)); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return ret; +} + +/* * idetape_do_request is our request handling function. */ static ide_startstop_t idetape_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) @@ -2618,31 +2658,38 @@ #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 5) - printk (KERN_INFO "ide-tape: rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); + printk (KERN_INFO "ide-tape: rq_status: %d, " + "rq_dev: %u, cmd: %d, errors: %d\n", rq->rq_status, + (unsigned int) rq->rq_dev, rq->cmd, rq->errors); if (tape->debug_level >= 2) - printk (KERN_INFO "ide-tape: sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); + printk (KERN_INFO "ide-tape: sector: %ld, " + "nr_sectors: %ld, current_nr_sectors: %ld\n", + rq->sector, rq->nr_sectors, rq->current_nr_sectors); #endif /* IDETAPE_DEBUG_LOG */ if (!IDETAPE_RQ_CMD (rq->cmd)) { /* * We do not support buffer cache originated requests. */ - printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%d)\n", drive->name, rq->cmd); - ide_end_request (0, HWGROUP (drive)); /* Let the common code handle it */ + printk (KERN_NOTICE "ide-tape: %s: Unsupported command in " + "request queue (%d)\n", drive->name, rq->cmd); + idetape_do_end_request(drive, 0); return ide_stopped; } /* * Retry a failed packet command */ - if (tape->failed_pc != NULL && tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { + if (tape->failed_pc != NULL && + tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) { return idetape_issue_packet_command (drive, tape->failed_pc); } #if IDETAPE_DEBUG_BUGS if (postponed_rq != NULL) if (rq != postponed_rq) { - printk (KERN_ERR "ide-tape: ide-tape.c bug - Two DSC requests were queued\n"); - idetape_end_request (0, HWGROUP (drive)); + printk (KERN_ERR "ide-tape: ide-tape.c bug - " + "Two DSC requests were queued\n"); + idetape_end_request(drive, 0); return ide_stopped; } #endif /* IDETAPE_DEBUG_BUGS */ @@ -2770,7 +2817,7 @@ break; case IDETAPE_ABORTED_WRITE_RQ: rq->cmd = IDETAPE_WRITE_RQ; - idetape_end_request (IDETAPE_ERROR_EOD, HWGROUP(drive)); + idetape_end_request(drive, IDETAPE_ERROR_EOD); return ide_stopped; case IDETAPE_ABORTED_READ_RQ: #if IDETAPE_DEBUG_LOG @@ -2778,7 +2825,7 @@ printk(KERN_INFO "ide-tape: %s: detected aborted read rq\n", tape->name); #endif rq->cmd = IDETAPE_READ_RQ; - idetape_end_request (IDETAPE_ERROR_EOD, HWGROUP(drive)); + idetape_end_request(drive, IDETAPE_ERROR_EOD); return ide_stopped; case IDETAPE_PC_RQ1: pc = (idetape_pc_t *) rq->buffer; @@ -2789,7 +2836,7 @@ return ide_stopped; default: printk (KERN_ERR "ide-tape: bug in IDETAPE_RQ_CMD macro\n"); - idetape_end_request (0, HWGROUP (drive)); + idetape_end_request(drive, 0); return ide_stopped; } return idetape_issue_packet_command (drive, pc); @@ -3112,7 +3159,7 @@ if (result->bpu) { printk (KERN_INFO "ide-tape: Block location is unknown to the tape\n"); clear_bit (IDETAPE_ADDRESS_VALID, &tape->flags); - idetape_end_request (0, HWGROUP (drive)); + idetape_end_request(drive, 0); } else { #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) @@ -3123,10 +3170,10 @@ tape->last_frame_position = ntohl (result->last_block); tape->blocks_in_buffer = result->blocks_in_buffer[2]; set_bit (IDETAPE_ADDRESS_VALID, &tape->flags); - idetape_end_request (1, HWGROUP (drive)); + idetape_end_request(drive, 1); } } else { - idetape_end_request (0, HWGROUP (drive)); + idetape_end_request(drive, 0); } return ide_stopped; } @@ -6085,14 +6132,14 @@ int minor = tape->minor; unsigned long flags; - save_flags (flags); /* all CPUs (overkill?) */ - cli(); /* all CPUs (overkill?) */ - if (test_bit (IDETAPE_BUSY, &tape->flags) || tape->first_stage != NULL || tape->merge_stage_size || drive->usage) { - restore_flags(flags); /* all CPUs (overkill?) */ + spin_lock_irqsave(&io_request_lock, flags); + if (test_bit (IDETAPE_BUSY, &tape->flags) || drive->usage || + tape->first_stage != NULL || tape->merge_stage_size) { + spin_unlock_irqrestore(&io_request_lock, flags); return 1; } idetape_chrdevs[minor].drive = NULL; - restore_flags (flags); /* all CPUs (overkill?) */ + spin_unlock_irqrestore(&io_request_lock, flags); DRIVER(drive)->busy = 0; (void) ide_unregister_subdriver (drive); drive->driver_data = NULL; @@ -6132,6 +6179,7 @@ #endif +int idetape_init (void); int idetape_reinit(ide_drive_t *drive); /* @@ -6142,13 +6190,21 @@ version: IDETAPE_VERSION, media: ide_tape, busy: 1, +#ifdef CONFIG_IDEDMA_ONLYDISK + supports_dma: 0, +#else supports_dma: 1, +#endif supports_dsc_overlap: 1, cleanup: idetape_cleanup, standby: NULL, + suspend: NULL, + resume: NULL, flushcache: NULL, do_request: idetape_do_request, end_request: idetape_end_request, + sense: NULL, + error: NULL, ioctl: idetape_blkdev_ioctl, open: idetape_blkdev_open, release: idetape_blkdev_release, @@ -6156,13 +6212,14 @@ revalidate: NULL, pre_reset: idetape_pre_reset, capacity: NULL, + special: NULL, proc: idetape_proc, + init: idetape_init, reinit: idetape_reinit, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; -int idetape_init (void); static ide_module_t idetape_module = { IDE_DRIVER_MODULE, idetape_init, diff -urN linux-2.4.19-p7-pristine/drivers/ide/ide-taskfile.c linux-2.4.19-p7/drivers/ide/ide-taskfile.c --- linux-2.4.19-p7-pristine/drivers/ide/ide-taskfile.c Tue Apr 16 03:15:16 2002 +++ linux-2.4.19-p7/drivers/ide/ide-taskfile.c Sun Apr 28 00:57:58 2002 @@ -1,12 +1,29 @@ /* - * linux/drivers/ide/ide-taskfile.c Version 0.20 Oct 11, 2000 + * linux/drivers/ide/ide-taskfile.c Version 0.33 April 11, 2002 * - * Copyright (C) 2000 Michael Cornwell - * Copyright (C) 2000 Andre Hedrick + * Copyright (C) 2000-2002 Michael Cornwell + * Copyright (C) 2000-2002 Andre Hedrick + * Copyright (C) 2001-2002 Klaus Smolin + * IBM Storage Technology Division * - * May be copied or modified under the terms of the GNU General Public License + * The big the bad and the ugly. * - * IDE_DEBUG(__LINE__); + * Problems to be fixed because of BH interface or the lack therefore. + * + * Fill me in stupid !!! + * + * HOST: + * General refers to the Controller and Driver "pair". + * DATA HANDLER: + * Under the context of Linux it generally refers to an interrupt handler. + * However, it correctly describes the 'HOST' + * DATA BLOCK: + * The amount of data needed to be transfered as predefined in the + * setup of the device. + * STORAGE ATOMIC: + * The 'DATA BLOCK' associated to the 'DATA HANDLER', and can be as + * small as a single sector or as large as the entire command block + * request. */ #include @@ -34,20 +51,41 @@ #include #include -#ifdef CONFIG_IDE_TASKFILE_IO -# define __TASKFILE__IO -#else /* CONFIG_IDE_TASKFILE_IO */ -# undef __TASKFILE__IO -#endif /* CONFIG_IDE_TASKFILE_IO */ - #define DEBUG_TASKFILE 0 /* unset when fixed */ #if DEBUG_TASKFILE -#define DTF(x...) printk(##x) +#define DTF(x...) printk(x) #else #define DTF(x...) #endif +/* + * + */ +#define task_rq_offset(rq) \ + (((rq)->nr_sectors - (rq)->current_nr_sectors) * SECTOR_SIZE) + +/* + * for now, taskfile requests are special :/ + * + * However, upon the creation of the atapi version of packet_command + * data-phase ISR plus it own diagnostics and extensions for direct access + * (ioctl,read,write,rip,stream -- atapi), the kmap/kunmap for PIO will + * come localized. + */ +inline char *task_map_rq (struct request *rq, unsigned long *flags) +{ + if (rq->bh) + return ide_map_buffer(rq, flags); + return rq->buffer + task_rq_offset(rq); +} + +inline void task_unmap_rq (struct request *rq, char *buf, unsigned long *flags) +{ + if (rq->bh) + ide_unmap_buffer(buf, flags); +} + inline u32 task_read_24 (ide_drive_t *drive) { return (IN_BYTE(IDE_HCYL_REG)<<16) | @@ -74,9 +112,9 @@ * to ensure that the reads all happen together. */ static inline void task_vlb_sync (ide_ioreg_t port) { - (void) inb (port); - (void) inb (port); - (void) inb (port); + (void) IN_BYTE (port); + (void) IN_BYTE (port); + (void) IN_BYTE (port); } #endif /* SUPPORT_VLB_SYNC */ @@ -85,17 +123,28 @@ */ void ata_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) { - byte io_32bit = drive->io_32bit; + byte io_32bit; + + /* + * first check if this controller has defined a special function + * for handling polled ide transfers + */ + + if (HWIF(drive)->ideproc) { + HWIF(drive)->ideproc(ideproc_ide_input_data, drive, buffer, wcount); + return; + } + + io_32bit = drive->io_32bit; if (io_32bit) { #if SUPPORT_VLB_SYNC if (io_32bit & 2) { unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); task_vlb_sync(IDE_NSECTOR_REG); insl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); } else #endif /* SUPPORT_VLB_SYNC */ insl(IDE_DATA_REG, buffer, wcount); @@ -118,17 +167,23 @@ */ void ata_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) { - byte io_32bit = drive->io_32bit; + byte io_32bit; + + if (HWIF(drive)->ideproc) { + HWIF(drive)->ideproc(ideproc_ide_output_data, drive, buffer, wcount); + return; + } + + io_32bit = drive->io_32bit; if (io_32bit) { #if SUPPORT_VLB_SYNC if (io_32bit & 2) { unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); task_vlb_sync(IDE_NSECTOR_REG); outsl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); } else #endif /* SUPPORT_VLB_SYNC */ outsl(IDE_DATA_REG, buffer, wcount); @@ -146,15 +201,61 @@ } } +/* + * The following routines are mainly used by the ATAPI drivers. + * + * These routines will round up any request for an odd number of bytes, + * so if an odd bytecount is specified, be sure that there's at least one + * extra byte allocated for the buffer. + */ +void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) +{ + if (HWIF(drive)->ideproc) { + HWIF(drive)->ideproc(ideproc_atapi_input_bytes, drive, buffer, bytecount); + return; + } + + ++bytecount; +#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) + if (MACH_IS_ATARI || MACH_IS_Q40) { + /* Atari has a byte-swapped IDE interface */ + insw_swapw(IDE_DATA_REG, buffer, bytecount / 2); + return; + } +#endif /* CONFIG_ATARI */ + ata_input_data (drive, buffer, bytecount / 4); + if ((bytecount & 0x03) >= 2) + insw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); +} + +void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) +{ + if (HWIF(drive)->ideproc) { + HWIF(drive)->ideproc(ideproc_atapi_output_bytes, drive, buffer, bytecount); + return; + } + + ++bytecount; +#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) + if (MACH_IS_ATARI || MACH_IS_Q40) { + /* Atari has a byte-swapped IDE interface */ + outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2); + return; + } +#endif /* CONFIG_ATARI */ + ata_output_data (drive, buffer, bytecount / 4); + if ((bytecount & 0x03) >= 2) + outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); +} -static inline void taskfile_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) +void taskfile_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) { ata_input_data(drive, buffer, wcount); if (drive->bswap) ata_bswap_data(buffer, wcount); } -static inline void taskfile_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) +void taskfile_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) { if (drive->bswap) { ata_bswap_data(buffer, wcount); @@ -165,102 +266,153 @@ } } -ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) +/* + * Needed for PCI irq sharing + */ +int drive_is_ready (ide_drive_t *drive) { - task_struct_t *taskfile = (task_struct_t *) task->tfRegister; - hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; - struct hd_driveid *id = drive->id; - byte HIHI = (drive->addressing) ? 0xE0 : 0xEF; + byte stat = 0; + if (drive->waiting_for_dma) + return HWIF(drive)->dmaproc(ide_dma_test_irq, drive); +#if 0 + /* need to guarantee 400ns since last command was issued */ + udelay(1); +#endif - /* (ks/hs): Moved to start, do not use for multiple out commands */ - if (task->handler != task_mulout_intr) { - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive), drive, 0); - } +#ifdef CONFIG_IDEPCI_SHARE_IRQ + /* + * We do a passive status test under shared PCI interrupts on + * cards that truly share the ATA side interrupt, but may also share + * an interrupt with another pci card/device. We make no assumptions + * about possible isa-pnp and pci-pnp issues yet. + */ + if (IDE_CONTROL_REG) + stat = GET_ALTSTAT(); + else +#endif /* CONFIG_IDEPCI_SHARE_IRQ */ + stat = GET_STAT(); /* Note: this may clear a pending IRQ!! */ - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - OUT_BYTE(hobfile->feature, IDE_FEATURE_REG); - OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG); - OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG); - OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG); - OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG); - } + if (stat & BUSY_STAT) + return 0; /* drive busy: definitely not interrupting */ + return 1; /* drive ready: *might* be interrupting */ +} - OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); - OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to number of sectors to transfer */ - OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); - /* refers to sector offset or start sector */ - OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); - OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); +/* + * Global for All, and taken from ide-pmac.c + */ +int wait_for_ready (ide_drive_t *drive, int timeout) +{ + byte stat = 0; - OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG); - if (task->handler != NULL) { -#if 0 - ide_set_handler (drive, task->handler, WAIT_CMD, NULL); - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - /* - * warning check for race between handler and prehandler for - * writing first block of data. however since we are well - * inside the boundaries of the seek, we should be okay. - */ - if (task->prehandler != NULL) { - return task->prehandler(drive, task->rq); + while(--timeout) { + stat = GET_STAT(); + if(!(stat & BUSY_STAT)) { + if (drive->ready_stat == 0) + break; + else if((stat & drive->ready_stat) || (stat & ERR_STAT)) + break; } -#else - ide_startstop_t startstop; - - ide_set_handler (drive, task->handler, WAIT_CMD, NULL); - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); + mdelay(1); + } + if((stat & ERR_STAT) || timeout <= 0) { + if (stat & ERR_STAT) { + printk(KERN_ERR "%s: wait_for_ready, error status: %x\n", drive->name, stat); + } + return 1; + } + return 0; +} - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", - drive->name, - drive->mult_count ? "MULTWRITE" : "WRITE"); - return startstop; - } - /* (ks/hs): Fixed Multi Write */ - if ((taskfile->command != WIN_MULTWRITE) && - (taskfile->command != WIN_MULTWRITE_EXT)) { - struct request *rq = HWGROUP(drive)->rq; - /* For Write_sectors we need to stuff the first sector */ - taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); - rq->current_nr_sectors--; - } else { - /* Stuff first sector(s) by implicitly calling the handler */ - if (!(drive_is_ready(drive))) { - /* FIXME: Replace hard-coded 100, error handling? */ - int i; - for (i=0; i<100; i++) { - if (drive_is_ready(drive)) - break; - } +/* + * This routine busy-waits for the drive status to be not "busy". + * It then checks the status for all of the "good" bits and none + * of the "bad" bits, and if all is okay it returns 0. All other + * cases return 1 after invoking ide_error() -- caller should just return. + * + * This routine should get fixed to not hog the cpu during extra long waits.. + * That could be done by busy-waiting for the first jiffy or two, and then + * setting a timer to wake up at half second intervals thereafter, + * until timeout is achieved, before timing out. + */ +int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) { + byte stat; + int i; + unsigned long flags; + + /* bail early if we've exceeded max_failures */ + if (drive->max_failures && (drive->failures > drive->max_failures)) { + *startstop = ide_stopped; + return 1; + } + + udelay(1); /* spec allows drive 400ns to assert "BUSY" */ + if ((stat = GET_STAT()) & BUSY_STAT) { + local_irq_set(flags); + timeout += jiffies; + while ((stat = GET_STAT()) & BUSY_STAT) { + if (time_after(jiffies, timeout)) { + local_irq_restore(flags); + *startstop = DRIVER(drive)->error(drive, "status timeout", stat); + return 1; } - return task->handler(drive); } -#endif - } else { - /* for dma commands we down set the handler */ - if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive))); + local_irq_restore(flags); + } + /* + * Allow status to settle, then read it again. + * A few rare drives vastly violate the 400ns spec here, + * so we'll wait up to 10usec for a "good" status + * rather than expensively fail things immediately. + * This fix courtesy of Matthew Faupel & Niccolo Rigacci. + */ + for (i = 0; i < 10; i++) { + udelay(1); + if (OK_STAT((stat = GET_STAT()), good, bad)) + return 0; } + *startstop = DRIVER(drive)->error(drive, "status error", stat); + return 1; +} - return ide_started; +void debug_taskfile (ide_drive_t *drive, ide_task_t *args) +{ +#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG + printk(KERN_INFO "%s: ", drive->name); +// printk("TF.0=x%02x ", args->tfRegister[IDE_DATA_OFFSET]); + printk("TF.1=x%02x ", args->tfRegister[IDE_FEATURE_OFFSET]); + printk("TF.2=x%02x ", args->tfRegister[IDE_NSECTOR_OFFSET]); + printk("TF.3=x%02x ", args->tfRegister[IDE_SECTOR_OFFSET]); + printk("TF.4=x%02x ", args->tfRegister[IDE_LCYL_OFFSET]); + printk("TF.5=x%02x ", args->tfRegister[IDE_HCYL_OFFSET]); + printk("TF.6=x%02x ", args->tfRegister[IDE_SELECT_OFFSET]); + printk("TF.7=x%02x\n", args->tfRegister[IDE_COMMAND_OFFSET]); + printk(KERN_INFO "%s: ", drive->name); +// printk("HTF.0=x%02x ", args->hobRegister[IDE_DATA_OFFSET_HOB]); + printk("HTF.1=x%02x ", args->hobRegister[IDE_FEATURE_OFFSET_HOB]); + printk("HTF.2=x%02x ", args->hobRegister[IDE_NSECTOR_OFFSET_HOB]); + printk("HTF.3=x%02x ", args->hobRegister[IDE_SECTOR_OFFSET_HOB]); + printk("HTF.4=x%02x ", args->hobRegister[IDE_LCYL_OFFSET_HOB]); + printk("HTF.5=x%02x ", args->hobRegister[IDE_HCYL_OFFSET_HOB]); + printk("HTF.6=x%02x ", args->hobRegister[IDE_SELECT_OFFSET_HOB]); + printk("HTF.7=x%02x\n", args->hobRegister[IDE_CONTROL_OFFSET_HOB]); +#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ } -void do_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, ide_handler_t *handler) +ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task) { + task_struct_t *taskfile = (task_struct_t *) task->tfRegister; + hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; struct hd_driveid *id = drive->id; - byte HIHI = (drive->addressing) ? 0xE0 : 0xEF; + byte HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF; - /* (ks/hs): Moved to start, do not use for multiple out commands */ - if (*handler != task_mulout_intr) { - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive), drive, 0); - } +#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG + void debug_taskfile(drive, task); +#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ + + /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ + SELECT_MASK(HWIF(drive), drive, 0); if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400) && @@ -281,147 +433,19 @@ OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); OUT_BYTE((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG); - if (handler != NULL) { - ide_set_handler (drive, handler, WAIT_CMD, NULL); - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - } else { - /* for dma commands we down set the handler */ - if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive))); - } -} - -#if 0 -ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) -{ - task_struct_t *taskfile = (task_struct_t *) task->tfRegister; - hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; - struct hd_driveid *id = drive->id; - - /* - * (KS) Check taskfile in/out flags. - * If set, then execute as it is defined. - * If not set, then define default settings. - * The default values are: - * write and read all taskfile registers (except data) - * write and read the hob registers (sector,nsector,lcyl,hcyl) - */ - if (task->tf_out_flags.all == 0) { - task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS; - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - task->tf_out_flags.all != (IDE_HOB_STD_OUT_FLAGS << 8); - } - } - - if (task->tf_in_flags.all == 0) { - task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - task->tf_in_flags.all != (IDE_HOB_STD_IN_FLAGS << 8); - } - } - - if (IDE_CONTROL_REG) - OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ - SELECT_MASK(HWIF(drive), drive, 0); - - if (task->tf_out_flags.b.data) { - unsigned short data = taskfile->data + (hobfile->data << 8); - OUT_WORD (data, IDE_DATA_REG); - } - - /* (KS) send hob registers first */ - if (task->tf_out_flags.b.nsector_hob) - OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG); - if (task->tf_out_flags.b.sector_hob) - OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG); - if (task->tf_out_flags.b.lcyl_hob) - OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG); - if (task->tf_out_flags.b.hcyl_hob) - OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG); - - - /* (KS) Send now the standard registers */ - if (task->tf_out_flags.b.error_feature) - OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); - /* refers to number of sectors to transfer */ - if (task->tf_out_flags.b.nsector) - OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to sector offset or start sector */ - if (task->tf_out_flags.b.sector) - OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); - if (task->tf_out_flags.b.lcyl) - OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); - if (task->tf_out_flags.b.hcyl) - OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); - - /* - * (KS) Do not modify the specified taskfile. We want to have a - * universal pass through, so we must execute ALL specified values. - * - * (KS) The drive head register is mandatory. - * Don't care about the out flags ! - */ - OUT_BYTE(taskfile->device_head | drive->select.all, IDE_SELECT_REG); if (task->handler != NULL) { -#if 0 ide_set_handler (drive, task->handler, WAIT_CMD, NULL); OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - /* - * warning check for race between handler and prehandler for - * writing first block of data. however since we are well - * inside the boundaries of the seek, we should be okay. - */ - if (task->prehandler != NULL) { + if (task->prehandler != NULL) return task->prehandler(drive, task->rq); - } -#else - ide_startstop_t startstop; - - ide_set_handler (drive, task->handler, WAIT_CMD, NULL); - - /* - * (KS) The drive command register is also mandatory. - * Don't care about the out flags ! - */ - OUT_BYTE(taskfile->command, IDE_COMMAND_REG); - - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", - drive->name, - drive->mult_count ? "MULTWRITE" : "WRITE"); - return startstop; - } - /* (ks/hs): Fixed Multi Write */ - if ((taskfile->command != WIN_MULTWRITE) && - (taskfile->command != WIN_MULTWRITE_EXT)) { - struct request *rq = HWGROUP(drive)->rq; - /* For Write_sectors we need to stuff the first sector */ - taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); - rq->current_nr_sectors--; - } else { - /* Stuff first sector(s) by implicitly calling the handler */ - if (!(drive_is_ready(drive))) { - /* FIXME: Replace hard-coded 100, error handling? */ - int i; - for (i=0; i<100; i++) { - if (drive_is_ready(drive)) - break; - } - } - return task->handler(drive); - } -#endif - } else { - /* for dma commands we down set the handler */ - if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive))); + return ide_started; } + // if ((rq->cmd == WRITE) && (drive->using_dma)) + /* for dma commands we down set the handler */ + if (drive->using_dma && !(HWIF(drive)->dmaproc(((taskfile->command == WIN_WRITEDMA) || (taskfile->command == WIN_WRITEDMA_EXT)) ? ide_dma_write : ide_dma_read, drive))); return ide_started; } -#endif #if 0 /* @@ -432,8 +456,7 @@ unsigned long flags; byte err = 0; - __save_flags (flags); /* local CPU only */ - ide__sti(); /* local CPU only */ + local_irq_set(flags); printk("%s: %s: status=0x%02x", drive->name, msg, stat); #if FANCY_STATUS_DUMPS printk(" { "); @@ -492,15 +515,16 @@ } } if (HWGROUP(drive)->rq) - printk(", sector=%llu", (__u64) HWGROUP(drive)->rq->sector); + printk(", sector=%lu", (__u64) HWGROUP(drive)->rq->sector); } } #endif /* FANCY_STATUS_DUMPS */ printk("\n"); } - __restore_flags (flags); /* local CPU only */ + local_irq_restore(flags); return err; } +#endif /* * Clean up after success/failure of an explicit taskfile operation. @@ -519,8 +543,14 @@ command = args->tfRegister[IDE_COMMAND_OFFSET]; - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (args->tf_in_flags.b.data) { + unsigned short data = IN_WORD(IDE_DATA_REG); + args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; + args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF; + } args->tfRegister[IDE_ERROR_OFFSET] = err; args->tfRegister[IDE_NSECTOR_OFFSET] = IN_BYTE(IDE_NSECTOR_REG); args->tfRegister[IDE_SECTOR_OFFSET] = IN_BYTE(IDE_SECTOR_REG); @@ -539,8 +569,13 @@ args->hobRegister[IDE_HCYL_OFFSET_HOB] = IN_BYTE(IDE_HCYL_REG); } +#if 0 /* taskfile_settings_update(drive, args, command); */ + if (args->posthandler != NULL) + args->posthandler(drive, args); +#endif + spin_lock_irqsave(&io_request_lock, flags); blkdev_dequeue_request(rq); HWGROUP(drive)->rq = NULL; @@ -548,6 +583,7 @@ spin_unlock_irqrestore(&io_request_lock, flags); } +#if 0 /* * try_to_flush_leftover_data() is invoked in response to a drive * unexpectedly having its DRQ_STAT bit set. As an alternative to @@ -608,10 +644,7 @@ OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */ if (rq->errors >= ERROR_MAX) { - if (drive->driver != NULL) - DRIVER(drive)->end_request(0, HWGROUP(drive)); - else - ide_end_request(0, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 0); } else { if ((rq->errors & ERROR_RESET) == ERROR_RESET) { ++rq->errors; @@ -657,8 +690,10 @@ return ide_stopped; if (stat & (ERR_STAT|DRQ_STAT)) - return ide_error(drive, "set_geometry_intr", stat); + return DRIVER(drive)->error(drive, "set_geometry_intr", stat); + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &set_geometry_intr, WAIT_CMD, NULL); return ide_started; } @@ -671,7 +706,7 @@ byte stat = GET_STAT(); if (!OK_STAT(stat,READY_STAT,BAD_STAT)) - return ide_error(drive, "recal_intr", stat); + return DRIVER(drive)->error(drive, "recal_intr", stat); return ide_stopped; } @@ -683,11 +718,13 @@ ide_task_t *args = HWGROUP(drive)->rq->special; byte stat = GET_STAT(); - ide__sti(); /* local CPU only */ - - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return ide_error(drive, "task_no_data_intr", stat); /* calls ide_end_drive_cmd */ - + local_irq_enable(); + if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { + DTF("%s: command opcode 0x%02x\n", drive->name, + args->tfRegister[IDE_COMMAND_OFFSET]); + return DRIVER(drive)->error(drive, "task_no_data_intr", stat); + /* calls ide_end_drive_cmd */ + } if (args) ide_end_drive_cmd (drive, stat, GET_ERR()); @@ -695,42 +732,85 @@ } /* - * Handler for command with PIO data-in phase + * Handler for command with PIO data-in phase, READ + */ +/* + * FIXME before 2.4 enable ... + * DATA integrity issue upon error. */ ide_startstop_t task_in_intr (ide_drive_t *drive) { byte stat = GET_STAT(); - byte io_32bit = drive->io_32bit; struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; + unsigned long flags; if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "task_in_intr", stat); +#if 0 + DTF("%s: attempting to recover last " \ + "sector counter status=0x%02x\n", + drive->name, stat); + /* + * Expect a BUG BOMB if we attempt to rewind the + * offset in the BH aka PAGE in the current BLOCK + * segment. This is different than the HOST segment. + */ +#endif + if (!rq->bh) + rq->current_nr_sectors++; + return DRIVER(drive)->error(drive, "task_in_intr", stat); } if (!(stat & BUSY_STAT)) { DTF("task_in_intr to Soon wait for next interrupt\n"); - ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL); + if (HWGROUP(drive)->handler == NULL) + ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL); return ide_started; } } - DTF("stat: %02x\n", stat); - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Read: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors); +#if 0 - drive->io_32bit = 0; - taskfile_input_data(drive, pBuf, SECTOR_WORDS); - drive->io_32bit = io_32bit; + /* + * Holding point for a brain dump of a thought :-/ + */ - if (--rq->current_nr_sectors <= 0) { - /* (hs): swapped next 2 lines */ - DTF("Request Ended stat: %02x\n", GET_STAT()); - ide_end_request(1, HWGROUP(drive)); - } else { + if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) { + DTF("%s: READ attempting to recover last " \ + "sector counter status=0x%02x\n", + drive->name, stat); + rq->current_nr_sectors++; + return DRIVER(drive)->error(drive, "task_in_intr", stat); + } + if (!rq->current_nr_sectors) + if (!DRIVER(drive)->end_request(drive, 1)) + return ide_stopped; + + if (--rq->current_nr_sectors <= 0) + if (!DRIVER(drive)->end_request(drive, 1)) + return ide_stopped; +#endif + + pBuf = task_map_rq(rq, &flags); + DTF("Read: %p, rq->current_nr_sectors: %d, stat: %02x\n", + pBuf, (int) rq->current_nr_sectors, stat); + taskfile_input_data(drive, pBuf, SECTOR_WORDS); + task_unmap_rq(rq, pBuf, &flags); + /* + * FIXME :: We really can not legally get a new page/bh + * regardless, if this is the end of our segment. + * BH walking or segment can only be updated after we have a good + * GET_STAT(); return. + */ + if (--rq->current_nr_sectors <= 0) + if (!DRIVER(drive)->end_request(drive, 1)) + return ide_stopped; + /* + * ERM, it is techincally legal to leave/exit here but it makes + * a mess of the code ... + */ + if (HWGROUP(drive)->handler == NULL) ide_set_handler(drive, &task_in_intr, WAIT_CMD, NULL); - return ide_started; - } - return ide_stopped; + return ide_started; } #undef ALTSTAT_SCREW_UP @@ -778,30 +858,37 @@ */ ide_startstop_t task_mulin_intr (ide_drive_t *drive) { - unsigned int msect, nsect; - #ifdef ALTSTAT_SCREW_UP byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "read"); #else byte stat = GET_STAT(); #endif /* ALTSTAT_SCREW_UP */ - - byte io_32bit = drive->io_32bit; struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; + unsigned int msect = drive->mult_count; + unsigned int nsect; + unsigned long flags; if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "task_mulin_intr", stat); + if (!rq->bh) { + rq->current_nr_sectors += drive->mult_count; + /* + * NOTE: could rewind beyond beginning :-/ + */ + } else { + printk("%s: MULTI-READ assume all data " \ + "transfered is bad status=0x%02x\n", + drive->name, stat); + } + return DRIVER(drive)->error(drive, "task_mulin_intr", stat); } /* no data yet, so wait for another interrupt */ - ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL); + if (HWGROUP(drive)->handler == NULL) + ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL); return ide_started; } - /* (ks/hs): Fixed Multi-Sector transfer */ - msect = drive->mult_count; - #ifdef ALTSTAT_SCREW_UP /* * Screw the request we do not support bad data-phase setups! @@ -814,157 +901,237 @@ */ nsect = 1; while (rq->current_nr_sectors) { - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Multiread: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; + pBuf = task_map_rq(rq, &flags); + DTF("Multiread: %p, nsect: %d, " \ + "rq->current_nr_sectors: %ld\n", + pBuf, nsect, rq->current_nr_sectors); +// rq->current_nr_sectors -= nsect; taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; + task_unmap_rq(rq, pBuf, &flags); rq->errors = 0; rq->current_nr_sectors -= nsect; stat = altstat_multi_poll(drive, GET_ALTSTAT(), "read"); } - ide_end_request(1, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 1); return ide_stopped; } #endif /* ALTSTAT_SCREW_UP */ - nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - - DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n", - pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; - taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; - rq->errors = 0; - rq->current_nr_sectors -= nsect; - if (rq->current_nr_sectors != 0) { + do { + nsect = rq->current_nr_sectors; + if (nsect > msect) + nsect = msect; + pBuf = task_map_rq(rq, &flags); + DTF("Multiread: %p, nsect: %d, msect: %d, " \ + " rq->current_nr_sectors: %d\n", + pBuf, nsect, msect, rq->current_nr_sectors); +// rq->current_nr_sectors -= nsect; +// msect -= nsect; + taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); + task_unmap_rq(rq, pBuf, &flags); + rq->errors = 0; + rq->current_nr_sectors -= nsect; + msect -= nsect; + /* + * FIXME :: We really can not legally get a new page/bh + * regardless, if this is the end of our segment. + * BH walking or segment can only be updated after we have a + * good GET_STAT(); return. + */ + if (!rq->current_nr_sectors) { + if (!DRIVER(drive)->end_request(drive, 1)) + return ide_stopped; + } + } while (msect); + if (HWGROUP(drive)->handler == NULL) ide_set_handler(drive, &task_mulin_intr, WAIT_CMD, NULL); - return ide_started; - } - ide_end_request(1, HWGROUP(drive)); - return ide_stopped; + return ide_started; } +/* + * VERIFY ME before 2.4 ... unexpected race is possible based on details + * RMK with 74LS245/373/374 TTL buffer logic because of passthrough. + */ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq) { - ide_task_t *args = rq->special; + char *pBuf = NULL; + unsigned long flags; ide_startstop_t startstop; - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing %s\n", drive->name, drive->mult_count ? "MULTWRITE" : "WRITE"); + if (ide_wait_stat(&startstop, drive, DATA_READY, + drive->bad_wstat, WAIT_DRQ)) { + printk(KERN_ERR "%s: no DRQ after issuing %s\n", + drive->name, + drive->addressing ? "WRITE_EXT" : "WRITE"); return startstop; } - - /* (ks/hs): Fixed Multi Write */ - if ((args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE) && - (args->tfRegister[IDE_COMMAND_OFFSET] != WIN_MULTWRITE_EXT)) { - /* For Write_sectors we need to stuff the first sector */ - taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); - rq->current_nr_sectors--; - return ide_started; - } else { - /* - * (ks/hs): Stuff the first sector(s) - * by implicitly calling the handler - */ - if (!(drive_is_ready(drive))) { - int i; - /* - * (ks/hs): FIXME: Replace hard-coded - * 100, error handling? - */ - for (i=0; i<100; i++) { - if (drive_is_ready(drive)) - break; - } - } - return args->handler(drive); - } + /* For Write_sectors we need to stuff the first sector */ + pBuf = task_map_rq(rq, &flags); +// rq->current_nr_sectors--; + taskfile_output_data(drive, pBuf, SECTOR_WORDS); + rq->current_nr_sectors--; + /* + * WARNING :: Interrupt could happen instantly :-/ + */ + task_unmap_rq(rq, pBuf, &flags); return ide_started; } /* - * Handler for command with PIO data-out phase + * Handler for command with PIO data-out phase WRITE + * + * WOOHOO this is a CORRECT STATE DIAGRAM NOW, */ ide_startstop_t task_out_intr (ide_drive_t *drive) { byte stat = GET_STAT(); - byte io_32bit = drive->io_32bit; struct request *rq = HWGROUP(drive)->rq; char *pBuf = NULL; - - if (!rq->current_nr_sectors) { - ide_end_request(1, HWGROUP(drive)); - return ide_stopped; - } + unsigned long flags; if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) { - return ide_error(drive, "task_out_intr", stat); + DTF("%s: WRITE attempting to recover last " \ + "sector counter status=0x%02x\n", + drive->name, stat); + rq->current_nr_sectors++; + return DRIVER(drive)->error(drive, "task_out_intr", stat); } + /* + * Safe to update request for partial completions. + * We have a good STATUS CHECK!!! + */ + if (!rq->current_nr_sectors) + if (!DRIVER(drive)->end_request(drive, 1)) + return ide_stopped; if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) { rq = HWGROUP(drive)->rq; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("write: %p, rq->current_nr_sectors: %d\n", pBuf, (int) rq->current_nr_sectors); - drive->io_32bit = 0; + pBuf = task_map_rq(rq, &flags); + DTF("write: %p, rq->current_nr_sectors: %d\n", + pBuf, (int) rq->current_nr_sectors); +// rq->current_nr_sectors--; taskfile_output_data(drive, pBuf, SECTOR_WORDS); - drive->io_32bit = io_32bit; + task_unmap_rq(rq, pBuf, &flags); rq->errors = 0; rq->current_nr_sectors--; } - - if (rq->current_nr_sectors <= 0) { - ide_end_request(1, HWGROUP(drive)); - } else { + if (HWGROUP(drive)->handler == NULL) ide_set_handler(drive, &task_out_intr, WAIT_CMD, NULL); - return ide_started; + return ide_started; +} + +ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq) +{ + ide_task_t *args = rq->special; + ide_startstop_t startstop; + +#if 0 + /* + * assign private copy for multi-write + */ + memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request)); +#endif + + if (ide_wait_stat(&startstop, drive, DATA_READY, + drive->bad_wstat, WAIT_DRQ)) { + printk(KERN_ERR "%s: no DRQ after issuing %s\n", + drive->name, + drive->addressing ? "MULTWRITE_EXT" : "MULTWRITE"); + return startstop; } - return ide_stopped; +#if 0 + if (wait_for_ready(drive, 100)) + IDE_DEBUG(__LINE__); //BUG(); +#else + if (!(drive_is_ready(drive))) { + int i; + for (i=0; i<100; i++) { + if (drive_is_ready(drive)) + break; + } + } +#endif + /* + * WARNING :: if the drive as not acked good status we may not + * move the DATA-TRANSFER T-Bar as BSY != 0. + */ + return args->handler(drive); } /* + * FIXME before enabling in 2.4 ... DATA integrity issue upon error. + */ +/* * Handler for command write multiple * Called directly from execute_drive_cmd for the first bunch of sectors, * afterwards only by the ISR */ ide_startstop_t task_mulout_intr (ide_drive_t *drive) { - unsigned int msect, nsect; - #ifdef ALTSTAT_SCREW_UP byte stat = altstat_multi_busy(drive, GET_ALTSTAT(), "write"); #else byte stat = GET_STAT(); #endif /* ALTSTAT_SCREW_UP */ - byte io_32bit = drive->io_32bit; - struct request *rq = HWGROUP(drive)->rq; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - char *pBuf = NULL; + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + ide_startstop_t startstop = ide_stopped; + unsigned int msect = drive->mult_count; + unsigned int nsect; + unsigned long flags; /* * (ks/hs): Handle last IRQ on multi-sector transfer, - * occurs after all data was sent + * occurs after all data was sent in this chunk */ if (rq->current_nr_sectors == 0) { - if (stat & (ERR_STAT|DRQ_STAT)) - return ide_error(drive, "task_mulout_intr", stat); - ide_end_request(1, HWGROUP(drive)); - return ide_stopped; + if (stat & (ERR_STAT|DRQ_STAT)) { + if (!rq->bh) { + rq->current_nr_sectors += drive->mult_count; + /* + * NOTE: could rewind beyond beginning :-/ + */ + } else { + printk("%s: MULTI-WRITE assume all data " \ + "transfered is bad status=0x%02x\n", + drive->name, stat); + } + return DRIVER(drive)->error(drive, "task_mulout_intr", stat); + } + if (!rq->bh) + DRIVER(drive)->end_request(drive, 1); + return startstop; } - + /* + * DON'T be lazy code the above and below togather !!! + */ if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) { if (stat & (ERR_STAT|DRQ_STAT)) { - return ide_error(drive, "task_mulout_intr", stat); + if (!rq->bh) { + rq->current_nr_sectors += drive->mult_count; + /* + * NOTE: could rewind beyond beginning :-/ + */ + } else { + printk("%s: MULTI-WRITE assume all data " \ + "transfered is bad status=0x%02x\n", + drive->name, stat); + } + return DRIVER(drive)->error(drive, "task_mulout_intr", stat); } /* no data yet, so wait for another interrupt */ - if (hwgroup->handler == NULL) + if (HWGROUP(drive)->handler == NULL) ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL); return ide_started; } - /* (ks/hs): See task_mulin_intr */ - msect = drive->mult_count; + if (HWGROUP(drive)->handler != NULL) { + unsigned long lflags; + spin_lock_irqsave(&io_request_lock, lflags); + HWGROUP(drive)->handler = NULL; + del_timer(&HWGROUP(drive)->timer); + spin_unlock_irqrestore(&io_request_lock, lflags); + } #ifdef ALTSTAT_SCREW_UP /* @@ -974,30 +1141,49 @@ if (!msect) { nsect = 1; while (rq->current_nr_sectors) { - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Multiwrite: %p, nsect: %d, rq->current_nr_sectors: %ld\n", pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; + pBuf = task_map_rq(rq, &flags); + DTF("Multiwrite: %p, nsect: %d, " \ + "rq->current_nr_sectors: %d\n", + pBuf, nsect, rq->current_nr_sectors); +// rq->current_nr_sectors -= nsect; taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; + task_unmap_rq(pBuf, &flags); rq->errors = 0; rq->current_nr_sectors -= nsect; stat = altstat_multi_poll(drive, GET_ALTSTAT(), "write"); } - ide_end_request(1, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 1); return ide_stopped; } #endif /* ALTSTAT_SCREW_UP */ - nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; - pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); - DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", - pBuf, nsect, rq->current_nr_sectors); - drive->io_32bit = 0; - taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); - drive->io_32bit = io_32bit; + do { + nsect = rq->current_nr_sectors; + if (nsect > msect) + nsect = msect; + pBuf = task_map_rq(rq, &flags); + DTF("Multiwrite: %p, nsect: %d, msect: %d, " \ + "rq->current_nr_sectors: %ld\n", + pBuf, nsect, msect, rq->current_nr_sectors); + msect -= nsect; +// rq->current_nr_sectors -= nsect; + taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); + task_unmap_rq(rq, pBuf, &flags); + rq->current_nr_sectors -= nsect; + /* + * FIXME :: We really can not legally get a new page/bh + * regardless, if this is the end of our segment. + * BH walking or segment can only be updated after we + * have a good GET_STAT(); return. + */ + if (!rq->current_nr_sectors) { + if (!DRIVER(drive)->end_request(drive, 1)) + if (!rq->bh) + return ide_stopped; + } + } while (msect); rq->errors = 0; - rq->current_nr_sectors -= nsect; - if (hwgroup->handler == NULL) + if (HWGROUP(drive)->handler == NULL) ide_set_handler(drive, &task_mulout_intr, WAIT_CMD, NULL); return ide_started; } @@ -1008,14 +1194,16 @@ switch(taskfile->command) { /* IDE_DRIVE_TASK_RAW_WRITE */ case CFA_WRITE_MULTI_WO_ERASE: + // case WIN_WRITE_LONG: + // case WIN_WRITE_LONG_ONCE: case WIN_MULTWRITE: case WIN_MULTWRITE_EXT: -// case WIN_WRITEDMA: -// case WIN_WRITEDMA_QUEUED: -// case WIN_WRITEDMA_EXT: -// case WIN_WRITEDMA_QUEUED_EXT: + return &pre_task_mulout_intr; + /* IDE_DRIVE_TASK_OUT */ case WIN_WRITE: + // case WIN_WRITE_ONCE: + case WIN_WRITE_EXT: case WIN_WRITE_VERIFY: case WIN_WRITE_BUFFER: case CFA_WRITE_SECT_WO_ERASE: @@ -1025,6 +1213,12 @@ case WIN_SMART: if (taskfile->feature == SMART_WRITE_LOG_SECTOR) return &pre_task_out_intr; + case WIN_WRITEDMA: + // case WIN_WRITEDMA_ONCE: + case WIN_WRITEDMA_QUEUED: + case WIN_WRITEDMA_EXT: + case WIN_WRITEDMA_QUEUED_EXT: + /* IDE_DRIVE_TASK_OUT */ default: break; } @@ -1040,6 +1234,7 @@ case CFA_TRANSLATE_SECTOR: case WIN_READ_BUFFER: case WIN_READ: + // case WIN_READ_ONCE: case WIN_READ_EXT: return &task_in_intr; case WIN_SECURITY_DISABLE: @@ -1051,11 +1246,16 @@ case WIN_WRITE_BUFFER: case WIN_WRITE_VERIFY: case WIN_WRITE: + // case WIN_WRITE_ONCE: case WIN_WRITE_EXT: return &task_out_intr; + // case WIN_READ_LONG: + // case WIN_READ_LONG_ONCE: case WIN_MULTREAD: case WIN_MULTREAD_EXT: return &task_mulin_intr; + // case WIN_WRITE_LONG: + // case WIN_WRITE_LONG_ONCE: case CFA_WRITE_MULTI_WO_ERASE: case WIN_MULTWRITE: case WIN_MULTWRITE_EXT: @@ -1074,13 +1274,16 @@ case CFA_REQ_EXT_ERROR_CODE: case CFA_ERASE_SECTORS: case WIN_VERIFY: + // case WIN_VERIFY_ONCE: case WIN_VERIFY_EXT: case WIN_SEEK: return &task_no_data_intr; case WIN_SPECIFY: return &set_geometry_intr; - case WIN_RESTORE: + case WIN_RECAL: + // case WIN_RESTORE: return &recal_intr; + case WIN_NOP: case WIN_DIAGNOSE: case WIN_FLUSH_CACHE: case WIN_FLUSH_CACHE_EXT: @@ -1111,11 +1314,13 @@ return &task_no_data_intr; #ifdef CONFIG_BLK_DEV_IDEDMA case WIN_READDMA: + // case WIN_READDMA_ONCE: case WIN_IDENTIFY_DMA: case WIN_READDMA_QUEUED: case WIN_READDMA_EXT: case WIN_READDMA_QUEUED_EXT: case WIN_WRITEDMA: + // case WIN_WRITEDMA_ONCE: case WIN_WRITEDMA_QUEUED: case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT: @@ -1130,14 +1335,26 @@ } } +ide_post_handler_t * ide_post_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile) +{ + switch(taskfile->command) { + case WIN_SPECIFY: /* set_geometry_intr */ + case WIN_RESTORE: /* recal_intr */ + case WIN_SETMULT: /* set_multmode_intr */ + default: + return(NULL); + } +} + /* Called by ioctl to feature out type of command being called */ int ide_cmd_type_parser (ide_task_t *args) { struct hd_drive_task_hdr *taskfile = (struct hd_drive_task_hdr *) args->tfRegister; struct hd_drive_hob_hdr *hobfile = (struct hd_drive_hob_hdr *) args->hobRegister; - args->prehandler = ide_pre_handler_parser(taskfile, hobfile); - args->handler = ide_handler_parser(taskfile, hobfile); + args->prehandler = ide_pre_handler_parser(taskfile, hobfile); + args->handler = ide_handler_parser(taskfile, hobfile); + args->posthandler = ide_post_handler_parser(taskfile, hobfile); switch(args->tfRegister[IDE_COMMAND_OFFSET]) { case WIN_IDENTIFY: @@ -1145,18 +1362,28 @@ return IDE_DRIVE_TASK_IN; case CFA_TRANSLATE_SECTOR: case WIN_READ: + // case WIN_READ_ONCE: + case WIN_READ_EXT: case WIN_READ_BUFFER: return IDE_DRIVE_TASK_IN; case WIN_WRITE: + // case WIN_WRITE_ONCE: + case WIN_WRITE_EXT: case WIN_WRITE_VERIFY: case WIN_WRITE_BUFFER: case CFA_WRITE_SECT_WO_ERASE: case WIN_DOWNLOAD_MICROCODE: return IDE_DRIVE_TASK_RAW_WRITE; + // case WIN_READ_LONG: + // case WIN_READ_LONG_ONCE: case WIN_MULTREAD: + case WIN_MULTREAD_EXT: return IDE_DRIVE_TASK_IN; + // case WIN_WRITE_LONG: + // case WIN_WRITE_LONG_ONCE: case CFA_WRITE_MULTI_WO_ERASE: case WIN_MULTWRITE: + case WIN_MULTWRITE_EXT: return IDE_DRIVE_TASK_RAW_WRITE; case WIN_SECURITY_DISABLE: case WIN_SECURITY_ERASE_UNIT: @@ -1178,12 +1405,14 @@ } #ifdef CONFIG_BLK_DEV_IDEDMA case WIN_READDMA: + // case WIN_READDMA_ONCE: case WIN_IDENTIFY_DMA: case WIN_READDMA_QUEUED: case WIN_READDMA_EXT: case WIN_READDMA_QUEUED_EXT: return IDE_DRIVE_TASK_IN; case WIN_WRITEDMA: + // case WIN_WRITEDMA_ONCE: case WIN_WRITEDMA_QUEUED: case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT: @@ -1191,20 +1420,32 @@ #endif case WIN_SETFEATURES: switch(args->tfRegister[IDE_FEATURE_OFFSET]) { + case SETFEATURES_EN_8BIT: + case SETFEATURES_EN_WCACHE: + return IDE_DRIVE_TASK_NO_DATA; case SETFEATURES_XFER: return IDE_DRIVE_TASK_SET_XFER; case SETFEATURES_DIS_DEFECT: case SETFEATURES_EN_APM: case SETFEATURES_DIS_MSN: + case SETFEATURES_DIS_RETRY: + case SETFEATURES_EN_AAM: + case SETFEATURES_RW_LONG: + case SETFEATURES_SET_CACHE: + case SETFEATURES_DIS_RLA: case SETFEATURES_EN_RI: case SETFEATURES_EN_SI: case SETFEATURES_DIS_RPOD: case SETFEATURES_DIS_WCACHE: case SETFEATURES_EN_DEFECT: case SETFEATURES_DIS_APM: + case SETFEATURES_EN_ECC: case SETFEATURES_EN_MSN: + case SETFEATURES_EN_RETRY: case SETFEATURES_EN_RLA: case SETFEATURES_PREFETCH: + case SETFEATURES_4B_RW_LONG: + case SETFEATURES_DIS_AAM: case SETFEATURES_EN_RPOD: case SETFEATURES_DIS_RI: case SETFEATURES_DIS_SI: @@ -1215,6 +1456,7 @@ case CFA_REQ_EXT_ERROR_CODE: case CFA_ERASE_SECTORS: case WIN_VERIFY: + // case WIN_VERIFY_ONCE: case WIN_VERIFY_EXT: case WIN_SEEK: case WIN_SPECIFY: @@ -1254,119 +1496,462 @@ } /* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). + * NOTICE: This is additions from IBM to provide a discrete interface, + * for selective taskregister access operations. Nice JOB Klaus!!! + * Glad to be able to work and co-develop this with you and IBM. */ -void ide_init_drive_taskfile (struct request *rq) +ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task) { - memset(rq, 0, sizeof(*rq)); - rq->cmd = IDE_DRIVE_TASK_NO_DATA; -} + task_struct_t *taskfile = (task_struct_t *) task->tfRegister; + hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister; + struct hd_driveid *id = drive->id; +#if DEBUG_TASKFILE + byte status; +#endif -/* - * This is kept for internal use only !!! - * This is an internal call and nobody in user-space has a damn - * reason to call this taskfile. - * - * ide_raw_taskfile is the one that user-space executes. - */ -int ide_wait_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, byte *buf) -{ - struct request rq; - ide_task_t args; - memset(&args, 0, sizeof(ide_task_t)); +#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG + void debug_taskfile(drive, task); +#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - args.tfRegister[IDE_DATA_OFFSET] = taskfile->data; - args.tfRegister[IDE_FEATURE_OFFSET] = taskfile->feature; - args.tfRegister[IDE_NSECTOR_OFFSET] = taskfile->sector_count; - args.tfRegister[IDE_SECTOR_OFFSET] = taskfile->sector_number; - args.tfRegister[IDE_LCYL_OFFSET] = taskfile->low_cylinder; - args.tfRegister[IDE_HCYL_OFFSET] = taskfile->high_cylinder; - args.tfRegister[IDE_SELECT_OFFSET] = taskfile->device_head; - args.tfRegister[IDE_COMMAND_OFFSET] = taskfile->command; - - args.hobRegister[IDE_DATA_OFFSET_HOB] = hobfile->data; - args.hobRegister[IDE_FEATURE_OFFSET_HOB] = hobfile->feature; - args.hobRegister[IDE_NSECTOR_OFFSET_HOB] = hobfile->sector_count; - args.hobRegister[IDE_SECTOR_OFFSET_HOB] = hobfile->sector_number; - args.hobRegister[IDE_LCYL_OFFSET_HOB] = hobfile->low_cylinder; - args.hobRegister[IDE_HCYL_OFFSET_HOB] = hobfile->high_cylinder; - args.hobRegister[IDE_SELECT_OFFSET_HOB] = hobfile->device_head; - args.hobRegister[IDE_CONTROL_OFFSET_HOB] = hobfile->control; + /* + * (ks) Check taskfile in/out flags. + * If set, then execute as it is defined. + * If not set, then define default settings. + * The default values are: + * write and read all taskfile registers (except data) + * write and read the hob registers (sector,nsector,lcyl,hcyl) + */ + if (task->tf_out_flags.all == 0) { + task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS; + if ((id->command_set_2 & 0x0400) && + (id->cfs_enable_2 & 0x0400) && + (drive->addressing == 1)) { + task->tf_out_flags.all |= (IDE_HOB_STD_OUT_FLAGS << 8); + } + } - ide_init_drive_taskfile(&rq); - /* This is kept for internal use only !!! */ - args.command_type = ide_cmd_type_parser (&args); - if (args.command_type != IDE_DRIVE_TASK_NO_DATA) - rq.current_nr_sectors = rq.nr_sectors = (hobfile->sector_count << 8) | taskfile->sector_count; + if (task->tf_in_flags.all == 0) { + task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS; + if ((id->command_set_2 & 0x0400) && + (id->cfs_enable_2 & 0x0400) && + (drive->addressing == 1)) { + task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8); + } + } - rq.cmd = IDE_DRIVE_TASKFILE; - rq.buffer = buf; - rq.special = &args; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} + /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */ + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ + SELECT_MASK(HWIF(drive), drive, 0); -int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, byte *buf) -{ - struct request rq; - ide_init_drive_taskfile(&rq); - rq.cmd = IDE_DRIVE_TASKFILE; - rq.buffer = buf; +#if DEBUG_TASKFILE + status = GET_STAT(); + if (status & 0x80) { + printk("flagged_taskfile -> Bad status. Status = %02x. wait 100 usec ...\n", status); + udelay(100); + status = GET_STAT(); + printk("flagged_taskfile -> Status = %02x\n", status); + } +#endif - if (args->command_type != IDE_DRIVE_TASK_NO_DATA) - rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET]; + if (task->tf_out_flags.b.data) { + unsigned short data = taskfile->data + (hobfile->data << 8); + OUT_WORD (data, IDE_DATA_REG); + } - rq.special = args; - return ide_do_drive_cmd(drive, &rq, ide_wait); -} + /* (ks) send hob registers first */ + if (task->tf_out_flags.b.nsector_hob) + OUT_BYTE(hobfile->sector_count, IDE_NSECTOR_REG); + if (task->tf_out_flags.b.sector_hob) + OUT_BYTE(hobfile->sector_number, IDE_SECTOR_REG); + if (task->tf_out_flags.b.lcyl_hob) + OUT_BYTE(hobfile->low_cylinder, IDE_LCYL_REG); + if (task->tf_out_flags.b.hcyl_hob) + OUT_BYTE(hobfile->high_cylinder, IDE_HCYL_REG); + + /* (ks) Send now the standard registers */ + if (task->tf_out_flags.b.error_feature) + OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); + /* refers to number of sectors to transfer */ + if (task->tf_out_flags.b.nsector) + OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); + /* refers to sector offset or start sector */ + if (task->tf_out_flags.b.sector) + OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); + if (task->tf_out_flags.b.lcyl) + OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); + if (task->tf_out_flags.b.hcyl) + OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); + /* + * (ks) In the flagged taskfile approch, we will used all specified + * registers and the register value will not be changed. Except the + * select bit (master/slave) in the drive_head register. We must make + * sure that the desired drive is selected. + */ + OUT_BYTE(taskfile->device_head | drive->select.all, IDE_SELECT_REG); + switch(task->data_phase) { -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG -char * ide_ioctl_verbose (unsigned int cmd) -{ - return("unknown"); + case TASKFILE_OUT_DMAQ: + case TASKFILE_OUT_DMA: + HWIF(drive)->dmaproc(ide_dma_write, drive); + break; + + case TASKFILE_IN_DMAQ: + case TASKFILE_IN_DMA: + HWIF(drive)->dmaproc(ide_dma_read, drive); + break; + + default: + if (task->handler == NULL) + return ide_stopped; + + ide_set_handler (drive, task->handler, WAIT_WORSTCASE, NULL); + /* Issue the command */ + OUT_BYTE(taskfile->command, IDE_COMMAND_REG); + if (task->prehandler != NULL) + return task->prehandler(drive, HWGROUP(drive)->rq); + } + + return ide_started; } -char * ide_task_cmd_verbose (byte task) +ide_startstop_t flagged_task_no_data_intr (ide_drive_t *drive) { - return("unknown"); + byte stat = GET_STAT(); + + local_irq_enable(); + + if (!OK_STAT(stat, READY_STAT, BAD_STAT)) { + if (stat & ERR_STAT) { + return DRIVER(drive)->error(drive, "flagged_task_no_data_intr", stat); + } + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_no_data_intr (unexpected phase)", stat); + } + + ide_end_drive_cmd (drive, stat, GET_ERR()); + + return ide_stopped; } -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ /* - * The taskfile glue table - * - * reqtask.data_phase reqtask.req_cmd - * args.command_type args.handler - * - * TASKFILE_P_OUT_DMAQ ?? ?? - * TASKFILE_P_IN_DMAQ ?? ?? - * TASKFILE_P_OUT_DMA ?? ?? - * TASKFILE_P_IN_DMA ?? ?? - * TASKFILE_P_OUT ?? ?? - * TASKFILE_P_IN ?? ?? - * - * TASKFILE_OUT_DMAQ IDE_DRIVE_TASK_RAW_WRITE NULL - * TASKFILE_IN_DMAQ IDE_DRIVE_TASK_IN NULL - * - * TASKFILE_OUT_DMA IDE_DRIVE_TASK_RAW_WRITE NULL - * TASKFILE_IN_DMA IDE_DRIVE_TASK_IN NULL - * - * TASKFILE_IN_OUT ?? ?? - * - * TASKFILE_MULTI_OUT IDE_DRIVE_TASK_RAW_WRITE task_mulout_intr - * TASKFILE_MULTI_IN IDE_DRIVE_TASK_IN task_mulin_intr - * - * TASKFILE_OUT IDE_DRIVE_TASK_RAW_WRITE task_out_intr - * TASKFILE_OUT IDE_DRIVE_TASK_OUT task_out_intr - * - * TASKFILE_IN IDE_DRIVE_TASK_IN task_in_intr - * TASKFILE_NO_DATA IDE_DRIVE_TASK_NO_DATA task_no_data_intr - * - * IDE_DRIVE_TASK_SET_XFER task_no_data_intr - * IDE_DRIVE_TASK_INVALID - * + * Handler for command with PIO data-in phase */ +ide_startstop_t flagged_task_in_intr (ide_drive_t *drive) +{ + byte stat = GET_STAT(); + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + int retries = 5; + + if (rq->current_nr_sectors == 0) + return DRIVER(drive)->error(drive, "flagged_task_in_intr (no data requested)", stat); + + if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { + if (stat & ERR_STAT) { + return DRIVER(drive)->error(drive, "flagged_task_in_intr", stat); + } + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_in_intr (unexpected data phase)", stat); + } + + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + DTF("Read - rq->current_nr_sectors: %d, status: %02x\n", (int) rq->current_nr_sectors, stat); + + taskfile_input_data(drive, pBuf, SECTOR_WORDS); + + if (--rq->current_nr_sectors != 0) { + /* + * (ks) We don't know which command was executed. + * So, we wait the 'WORSTCASE' value. + */ + ide_set_handler(drive, &flagged_task_in_intr, WAIT_WORSTCASE, NULL); + return ide_started; + } + /* + * (ks) Last sector was transfered, wait until drive is ready. + * This can take up to 10 usec. We willl wait max 50 us. + */ + while (((stat = GET_STAT()) & BUSY_STAT) && retries--) + udelay(10); + ide_end_drive_cmd (drive, stat, GET_ERR()); + + return ide_stopped; +} + +ide_startstop_t flagged_task_mulin_intr (ide_drive_t *drive) +{ + byte stat = GET_STAT(); + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + int retries = 5; + unsigned int msect, nsect; + + if (rq->current_nr_sectors == 0) + return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (no data requested)", stat); + + msect = drive->mult_count; + if (msect == 0) + return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (multimode not set)", stat); + + if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { + if (stat & ERR_STAT) { + return DRIVER(drive)->error(drive, "flagged_task_mulin_intr", stat); + } + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (unexpected data phase)", stat); + } + + nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + + DTF("Multiread: %p, nsect: %d , rq->current_nr_sectors: %ld\n", + pBuf, nsect, rq->current_nr_sectors); + + taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS); + + rq->current_nr_sectors -= nsect; + if (rq->current_nr_sectors != 0) { + /* + * (ks) We don't know which command was executed. + * So, we wait the 'WORSTCASE' value. + */ + ide_set_handler(drive, &flagged_task_mulin_intr, WAIT_WORSTCASE, NULL); + return ide_started; + } + + /* + * (ks) Last sector was transfered, wait until drive is ready. + * This can take up to 10 usec. We willl wait max 50 us. + */ + while (((stat = GET_STAT()) & BUSY_STAT) && retries--) + udelay(10); + ide_end_drive_cmd (drive, stat, GET_ERR()); + + return ide_stopped; +} + +/* + * Pre handler for command with PIO data-out phase + */ +ide_startstop_t flagged_pre_task_out_intr (ide_drive_t *drive, struct request *rq) +{ + byte stat = GET_STAT(); + ide_startstop_t startstop; + + if (!rq->current_nr_sectors) { + return DRIVER(drive)->error(drive, "flagged_pre_task_out_intr (write data not specified)", stat); + } + + if (ide_wait_stat(&startstop, drive, DATA_READY, + BAD_W_STAT, WAIT_DRQ)) { + printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name); + return startstop; + } + + taskfile_output_data(drive, rq->buffer, SECTOR_WORDS); + --rq->current_nr_sectors; + + return ide_started; +} + +ide_startstop_t flagged_task_out_intr (ide_drive_t *drive) +{ + byte stat = GET_STAT(); + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + + if (!OK_STAT(stat, DRIVE_READY, BAD_W_STAT)) + return DRIVER(drive)->error(drive, "flagged_task_out_intr", stat); + + if (!rq->current_nr_sectors) { + ide_end_drive_cmd (drive, stat, GET_ERR()); + return ide_stopped; + } + + if (!OK_STAT(stat, DATA_READY, BAD_W_STAT)) { + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_out_intr (unexpected data phase)", stat); + } + + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + DTF("Write - rq->current_nr_sectors: %d, status: %02x\n", + (int) rq->current_nr_sectors, stat); + + taskfile_output_data(drive, pBuf, SECTOR_WORDS); + --rq->current_nr_sectors; + + /* + * (ks) We don't know which command was executed. + * So, we wait the 'WORSTCASE' value. + */ + ide_set_handler(drive, &flagged_task_out_intr, WAIT_WORSTCASE, NULL); + + return ide_started; +} + +ide_startstop_t flagged_pre_task_mulout_intr (ide_drive_t *drive, struct request *rq) +{ + byte stat = GET_STAT(); + char *pBuf = NULL; + ide_startstop_t startstop; + unsigned int msect, nsect; + + if (!rq->current_nr_sectors) + return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (write data not specified)", stat); + + msect = drive->mult_count; + if (msect == 0) + return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (multimode not set)", stat); + + if (ide_wait_stat(&startstop, drive, DATA_READY, + BAD_W_STAT, WAIT_DRQ)) { + printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name); + return startstop; + } + + nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", + pBuf, nsect, rq->current_nr_sectors); + + taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); + + rq->current_nr_sectors -= nsect; + + return ide_started; +} + +ide_startstop_t flagged_task_mulout_intr (ide_drive_t *drive) +{ + byte stat = GET_STAT(); + struct request *rq = HWGROUP(drive)->rq; + char *pBuf = NULL; + unsigned int msect, nsect; + + msect = drive->mult_count; + if (msect == 0) + return DRIVER(drive)->error(drive, "flagged_task_mulout_intr (multimode not set)", stat); + + if (!OK_STAT(stat, DRIVE_READY, BAD_W_STAT)) + return DRIVER(drive)->error(drive, "flagged_task_mulout_intr", stat); + + if (!rq->current_nr_sectors) { + ide_end_drive_cmd (drive, stat, GET_ERR()); + return ide_stopped; + } + + if (!OK_STAT(stat, DATA_READY, BAD_W_STAT)) { + /* + * (ks) Unexpected ATA data phase detected. + * This should not happen. But, it can ! + * I am not sure, which function is best to clean up + * this situation. I choose: ide_error(...) + */ + return DRIVER(drive)->error(drive, "flagged_task_mulout_intr (unexpected data phase)", stat); + } + + nsect = (rq->current_nr_sectors > msect) ? msect : rq->current_nr_sectors; + pBuf = rq->buffer + ((rq->nr_sectors - rq->current_nr_sectors) * SECTOR_SIZE); + DTF("Multiwrite: %p, nsect: %d , rq->current_nr_sectors: %ld\n", + pBuf, nsect, rq->current_nr_sectors); + + taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS); + rq->current_nr_sectors -= nsect; + + /* + * (ks) We don't know which command was executed. + * So, we wait the 'WORSTCASE' value. + */ + ide_set_handler(drive, &flagged_task_mulout_intr, WAIT_WORSTCASE, NULL); + + return ide_started; +} + +/* + * This function is intended to be used prior to invoking ide_do_drive_cmd(). + */ +void ide_init_drive_taskfile (struct request *rq) +{ + memset(rq, 0, sizeof(*rq)); + rq->cmd = IDE_DRIVE_TASK_NO_DATA; +} + +int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, byte *buf) +{ + struct request rq; + + ide_init_drive_taskfile(&rq); + rq.cmd = IDE_DRIVE_TASKFILE; + rq.buffer = buf; + + /* + * (ks) We transfer currently only whole sectors. + * This is suffient for now. But, it would be great, + * if we would find a solution to transfer any size. + * To support special commands like READ LONG. + */ + if (args->command_type != IDE_DRIVE_TASK_NO_DATA) { + if (data_size == 0) + rq.current_nr_sectors = rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET_HOB] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET]; + /* rq.hard_cur_sectors */ + else + rq.current_nr_sectors = rq.nr_sectors = data_size / SECTOR_SIZE; + /* rq.hard_cur_sectors */ + } + + if (args->tf_out_flags.all == 0) { + /* + * clean up kernel settings for driver sanity, regardless. + * except for discrete diag services. + */ + args->posthandler = ide_post_handler_parser( + (struct hd_drive_task_hdr *) args->tfRegister, + (struct hd_drive_hob_hdr *) args->hobRegister); + + } + rq.special = args; + return ide_do_drive_cmd(drive, &rq, ide_wait); +} + +int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, byte *buf) +{ + return ide_diag_taskfile(drive, args, 0, buf); +} + +#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG +char * ide_ioctl_verbose (unsigned int cmd) +{ + return("unknown"); +} + +char * ide_task_cmd_verbose (byte task) +{ + return("unknown"); +} +#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ #define MAX_DMA (256*SECTOR_WORDS) @@ -1374,7 +1959,6 @@ { ide_task_request_t *req_task; ide_task_t args; - byte *outbuf = NULL; byte *inbuf = NULL; task_ioreg_t *argsptr = args.tfRegister; @@ -1383,6 +1967,9 @@ int tasksize = sizeof(struct ide_task_request_s); int taskin = 0; int taskout = 0; + byte io_32bit = drive->io_32bit; + +// printk("IDE Taskfile ...\n"); req_task = kmalloc(tasksize, GFP_KERNEL); if (req_task == NULL) return -ENOMEM; @@ -1423,8 +2010,7 @@ } } - memset(argsptr, 0, HDIO_DRIVE_TASK_HDR_SIZE); - memset(hobsptr, 0, HDIO_DRIVE_HOB_HDR_SIZE); + memset (&args, 0, sizeof (ide_task_t) ); memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE); memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE); @@ -1440,64 +2026,61 @@ ide_task_cmd_verbose(args.tfRegister[IDE_COMMAND_OFFSET])); #endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ + drive->io_32bit = 0; switch(req_task->data_phase) { case TASKFILE_OUT_DMAQ: case TASKFILE_OUT_DMA: - args.prehandler = NULL; - args.handler = NULL; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, outbuf); + err = ide_diag_taskfile(drive, &args, taskout, outbuf); break; case TASKFILE_IN_DMAQ: case TASKFILE_IN_DMA: - args.prehandler = NULL; - args.handler = NULL; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, inbuf); + err = ide_diag_taskfile(drive, &args, taskin, inbuf); break; case TASKFILE_IN_OUT: #if 0 args.prehandler = &pre_task_out_intr; args.handler = &task_out_intr; args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, outbuf); + err = ide_diag_taskfile(drive, &args, taskout, outbuf); args.prehandler = NULL; args.handler = &task_in_intr; args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, inbuf); + err = ide_diag_taskfile(drive, &args, taskin, inbuf); break; #else err = -EFAULT; goto abort; #endif case TASKFILE_MULTI_OUT: - if (drive->mult_count) { - args.prehandler = &pre_task_out_intr; - args.handler = &task_mulout_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, outbuf); - } else { + if (!drive->mult_count) { /* (hs): give up if multcount is not set */ printk("%s: %s Multimode Write " \ "multcount is not set\n", - drive->name, __FUNCTION__); + drive->name, __FUNCTION__); err = -EPERM; goto abort; } + if (args.tf_out_flags.all != 0) { + args.prehandler = &flagged_pre_task_mulout_intr; + args.handler = &flagged_task_mulout_intr; + } else { + args.prehandler = &pre_task_mulout_intr; + args.handler = &task_mulout_intr; + } + err = ide_diag_taskfile(drive, &args, taskout, outbuf); break; case TASKFILE_OUT: - args.prehandler = &pre_task_out_intr; - args.handler = &task_out_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, outbuf); + if (args.tf_out_flags.all != 0) { + args.prehandler = &flagged_pre_task_out_intr; + args.handler = &flagged_task_out_intr; + } else { + args.prehandler = &pre_task_out_intr; + args.handler = &task_out_intr; + } + err = ide_diag_taskfile(drive, &args, taskout, outbuf); break; case TASKFILE_MULTI_IN: - if (drive->mult_count) { - args.prehandler = NULL; - args.handler = &task_mulin_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, inbuf); - } else { + if (!drive->mult_count) { /* (hs): give up if multcount is not set */ printk("%s: %s Multimode Read failure " \ "multcount is not set\n", @@ -1505,23 +2088,30 @@ err = -EPERM; goto abort; } + if (args.tf_out_flags.all != 0) { + args.handler = &flagged_task_mulin_intr; + } else { + args.handler = &task_mulin_intr; + } + err = ide_diag_taskfile(drive, &args, taskin, inbuf); break; case TASKFILE_IN: - args.prehandler = NULL; - args.handler = &task_in_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, inbuf); + if (args.tf_out_flags.all != 0) { + args.handler = &flagged_task_in_intr; + } else { + args.handler = &task_in_intr; + } + err = ide_diag_taskfile(drive, &args, taskin, inbuf); break; case TASKFILE_NO_DATA: - args.prehandler = NULL; - args.handler = &task_no_data_intr; - args.posthandler = NULL; - err = ide_raw_taskfile(drive, &args, NULL); + if (args.tf_out_flags.all != 0) { + args.handler = &flagged_task_no_data_intr; + } else { + args.handler = &task_no_data_intr; + } + err = ide_diag_taskfile(drive, &args, 0, NULL); break; default: - args.prehandler = NULL; - args.handler = NULL; - args.posthandler = NULL; err = -EFAULT; goto abort; } @@ -1555,15 +2145,175 @@ kfree(outbuf); if (inbuf != NULL) kfree(inbuf); + +// printk("IDE Taskfile ioctl ended. rc = %i\n", err); + + drive->io_32bit = io_32bit; + return err; } +int ide_ata66_check (ide_drive_t *drive, ide_task_t *args); +int set_transfer(ide_drive_t *drive, ide_task_t *args); + +/* + * FIXME : this needs to map into at taskfile. + */ +int ide_cmd_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ +#if 1 + int err = 0; + byte args[4], *argbuf = args; + byte xfer_rate = 0; + int argsize = 4; + ide_task_t tfargs; + + if (NULL == (void *) arg) { + struct request rq; + ide_init_drive_cmd(&rq); + return ide_do_drive_cmd(drive, &rq, ide_wait); + } + + if (copy_from_user(args, (void *)arg, 4)) + return -EFAULT; + + memset(&tfargs, 0, sizeof(ide_task_t)); + tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2]; + tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3]; + tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1]; + tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00; + tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00; + tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00; + tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0]; + + if (args[3]) { + argsize = 4 + (SECTOR_WORDS * 4 * args[3]); + argbuf = kmalloc(argsize, GFP_KERNEL); + if (argbuf == NULL) + return -ENOMEM; + memcpy(argbuf, args, 4); + } + if (set_transfer(drive, &tfargs)) { + xfer_rate = args[1]; + if (ide_ata66_check(drive, &tfargs)) + goto abort; + } + + err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf); + + if (!err && xfer_rate) { + /* active-retuning-calls future */ + if ((HWIF(drive)->speedproc) != NULL) + HWIF(drive)->speedproc(drive, xfer_rate); + ide_driveid_update(drive); + } +abort: + if (copy_to_user((void *)arg, argbuf, argsize)) + err = -EFAULT; + if (argsize > 4) + kfree(argbuf); + return err; + +#else + + int err = 0; + byte args[4], *argbuf = args; + byte xfer_rate = 0; + int argsize = 0; + ide_task_t tfargs; + + if (NULL == (void *) arg) { + struct request rq; + ide_init_drive_cmd(&rq); + return ide_do_drive_cmd(drive, &rq, ide_wait); + } + + if (copy_from_user(args, (void *)arg, 4)) + return -EFAULT; + + memset(&tfargs, 0, sizeof(ide_task_t)); + tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2]; + tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3]; + tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1]; + tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00; + tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00; + tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00; + tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0]; + + if (args[3]) { + argsize = (SECTOR_WORDS * 4 * args[3]); + argbuf = kmalloc(argsize, GFP_KERNEL); + if (argbuf == NULL) + return -ENOMEM; + } + + if (set_transfer(drive, &tfargs)) { + xfer_rate = args[1]; + if (ide_ata66_check(drive, &tfargs)) + goto abort; + } + + tfargs.command_type = ide_cmd_type_parser(&tfargs); + err = ide_raw_taskfile(drive, &tfargs, argbuf); + + if (!err && xfer_rate) { + /* active-retuning-calls future */ + if ((HWIF(drive)->speedproc) != NULL) + HWIF(drive)->speedproc(drive, xfer_rate); + ide_driveid_update(drive); + } +abort: + + args[0] = tfargs.tfRegister[IDE_COMMAND_OFFSET]; + args[1] = tfargs.tfRegister[IDE_FEATURE_OFFSET]; + args[2] = tfargs.tfRegister[IDE_NSECTOR_OFFSET]; + args[3] = 0; + + if (copy_to_user((void *)arg, argbuf, 4)) + err = -EFAULT; + if (argbuf != NULL) { + if (copy_to_user((void *)arg, argbuf + 4, argsize)) + err = -EFAULT; + kfree(argbuf); + } + return err; + +#endif + +} + +/* + * FIXME : this needs to map into at taskfile. + */ +int ide_task_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int err = 0; + byte args[7], *argbuf = args; + int argsize = 7; + + if (copy_from_user(args, (void *)arg, 7)) + return -EFAULT; + err = ide_wait_cmd_task(drive, argbuf); + if (copy_to_user((void *)arg, argbuf, argsize)) + err = -EFAULT; + return err; +} + +EXPORT_SYMBOL(drive_is_ready); +EXPORT_SYMBOL(wait_for_ready); + EXPORT_SYMBOL(task_read_24); -EXPORT_SYMBOL(do_rw_taskfile); -EXPORT_SYMBOL(do_taskfile); -// EXPORT_SYMBOL(flagged_taskfile); +EXPORT_SYMBOL(ata_input_data); +EXPORT_SYMBOL(ata_output_data); +EXPORT_SYMBOL(atapi_input_bytes); +EXPORT_SYMBOL(atapi_output_bytes); +EXPORT_SYMBOL(taskfile_input_data); +EXPORT_SYMBOL(taskfile_output_data); -//EXPORT_SYMBOL(ide_end_taskfile); +EXPORT_SYMBOL(ide_wait_stat); +EXPORT_SYMBOL(do_rw_taskfile); +EXPORT_SYMBOL(flagged_taskfile); +EXPORT_SYMBOL(ide_end_taskfile); EXPORT_SYMBOL(set_multmode_intr); EXPORT_SYMBOL(set_geometry_intr); @@ -1574,15 +2324,344 @@ EXPORT_SYMBOL(task_mulin_intr); EXPORT_SYMBOL(pre_task_out_intr); EXPORT_SYMBOL(task_out_intr); +EXPORT_SYMBOL(pre_task_mulout_intr); EXPORT_SYMBOL(task_mulout_intr); EXPORT_SYMBOL(ide_init_drive_taskfile); -EXPORT_SYMBOL(ide_wait_taskfile); EXPORT_SYMBOL(ide_raw_taskfile); EXPORT_SYMBOL(ide_pre_handler_parser); EXPORT_SYMBOL(ide_handler_parser); +EXPORT_SYMBOL(ide_post_handler_parser); EXPORT_SYMBOL(ide_cmd_type_parser); EXPORT_SYMBOL(ide_taskfile_ioctl); +EXPORT_SYMBOL(ide_cmd_ioctl); +EXPORT_SYMBOL(ide_task_ioctl); + +/* + * Beginning of Taskfile OPCODE Library and feature sets. + */ + +/* + * All hosts that use the 80c ribbon must use! + * The name is derived from upper byte of word 93 and the 80c ribbon. + */ +byte eighty_ninty_three (ide_drive_t *drive) +{ +#if 0 + if (!HWIF(drive)->udma_four) + return 0; + + if (drive->id->major_rev_num) { + int hssbd = 0; + int i; + /* + * Determime highest Supported SPEC + */ + for (i=1; i<=15; i++) + if (drive->id->major_rev_num & (1<id->hw_config & 0x4000) && +#endif /* CONFIG_IDEDMA_IVB */ + (drive->id->hw_config & 0x6000)) ? 1 : 0); + +#else + + return ((byte) ((HWIF(drive)->udma_four) && +#ifndef CONFIG_IDEDMA_IVB + (drive->id->hw_config & 0x4000) && +#endif /* CONFIG_IDEDMA_IVB */ + (drive->id->hw_config & 0x6000)) ? 1 : 0); +#endif +} + +int ide_ata66_check (ide_drive_t *drive, ide_task_t *args) +{ + if (!HWIF(drive)->udma_four) { + printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", + HWIF(drive)->name); + return 1; + } + if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && + (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) && + (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) { +#ifndef CONFIG_IDEDMA_IVB + if ((drive->id->hw_config & 0x6000) == 0) { +#else /* !CONFIG_IDEDMA_IVB */ + if (((drive->id->hw_config & 0x2000) == 0) || + ((drive->id->hw_config & 0x4000) == 0)) { +#endif /* CONFIG_IDEDMA_IVB */ + printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->name); + return 1; + } + } + return 0; +} + +/* + * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. + * 1 : Safe to update drive->id DMA registers. + * 0 : OOPs not allowed. + */ +int set_transfer (ide_drive_t *drive, ide_task_t *args) +{ + if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) && + (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) && + (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) && + (drive->id->dma_ultra || + drive->id->dma_mword || + drive->id->dma_1word)) + return 1; + + return 0; +} + +byte ide_auto_reduce_xfer (ide_drive_t *drive) +{ + if (!drive->crc_count) + return drive->current_speed; + drive->crc_count = 0; + + switch(drive->current_speed) { + case XFER_UDMA_7: return XFER_UDMA_6; + case XFER_UDMA_6: return XFER_UDMA_5; + case XFER_UDMA_5: return XFER_UDMA_4; + case XFER_UDMA_4: return XFER_UDMA_3; + case XFER_UDMA_3: return XFER_UDMA_2; + case XFER_UDMA_2: return XFER_UDMA_1; + case XFER_UDMA_1: return XFER_UDMA_0; + /* + * OOPS we do not goto non Ultra DMA modes + * without iCRC's available we force + * the system to PIO and make the user + * invoke the ATA-1 ATA-2 DMA modes. + */ + case XFER_UDMA_0: + default: return XFER_PIO_4; + } +} + +int taskfile_lib_get_identify (ide_drive_t *drive, byte *buf) +{ + ide_task_t args; + memset(&args, 0, sizeof(ide_task_t)); + args.tfRegister[IDE_NSECTOR_OFFSET] = 0x01; + if (drive->media == ide_disk) + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_IDENTIFY; + else + args.tfRegister[IDE_COMMAND_OFFSET] = WIN_PIDENTIFY; + args.command_type = ide_cmd_type_parser(&args); + return ide_raw_taskfile(drive, &args, buf); +} + +/* + * Update the + */ +int ide_driveid_update (ide_drive_t *drive) +{ +#if 0 + struct hd_driveid *id; + + id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); + if (!id) + return 0; + + taskfile_lib_get_identify(drive, (char *)&id); + + ide_fix_driveid(id); + if (id) { + drive->id->dma_ultra = id->dma_ultra; + drive->id->dma_mword = id->dma_mword; + drive->id->dma_1word = id->dma_1word; + /* anything more ? */ + kfree(id); + } + return 1; +#else + /* + * Re-read drive->id for possible DMA mode + * change (copied from ide-probe.c) + */ + struct hd_driveid *id; + unsigned long timeout, flags; + + SELECT_MASK(HWIF(drive), drive, 1); + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl,IDE_CONTROL_REG); + ide_delay_50ms(); + OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG); + timeout = jiffies + WAIT_WORSTCASE; + do { + if (time_after(jiffies, timeout)) { + SELECT_MASK(HWIF(drive), drive, 0); + return 0; /* drive timed-out */ + } + ide_delay_50ms(); /* give drive a breather */ + } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT); + ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ + if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { + SELECT_MASK(HWIF(drive), drive, 0); + printk("%s: CHECK for good STATUS\n", drive->name); + return 0; + } + local_irq_save(flags); + SELECT_MASK(HWIF(drive), drive, 0); + id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); + if (!id) { + local_irq_restore(flags); + return 0; + } + ata_input_data(drive, id, SECTOR_WORDS); + (void) GET_STAT(); /* clear drive IRQ */ + local_irq_enable(); + local_irq_restore(flags); + ide_fix_driveid(id); + if (id) { + drive->id->dma_ultra = id->dma_ultra; + drive->id->dma_mword = id->dma_mword; + drive->id->dma_1word = id->dma_1word; + /* anything more ? */ + kfree(id); + } + + return 1; +#endif +} + + +/* + * Similar to ide_wait_stat(), except it never calls ide_error internally. + * This is a kludge to handle the new ide_config_drive_speed() function, + * and should not otherwise be used anywhere. Eventually, the tuneproc's + * should be updated to return ide_startstop_t, in which case we can get + * rid of this abomination again. :) -ml + * + * It is gone.......... + * + * const char *msg == consider adding for verbose errors. + */ +int ide_config_drive_speed (ide_drive_t *drive, byte speed) +{ + ide_hwif_t *hwif = HWIF(drive); + int i, error = 1; + byte stat; + +#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) + byte unit = (drive->select.b.unit & 0x01); + outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); +#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ + + /* + * Don't use ide_wait_cmd here - it will + * attempt to set_geometry and recalibrate, + * but for some reason these don't work at + * this point (lost interrupt). + */ + /* + * Select the drive, and issue the SETFEATURES command + */ + disable_irq(hwif->irq); /* disable_irq_nosync ?? */ + udelay(1); + SELECT_DRIVE(HWIF(drive), drive); + SELECT_MASK(HWIF(drive), drive, 0); + udelay(1); + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); + OUT_BYTE(speed, IDE_NSECTOR_REG); + OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); + OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); + if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); + udelay(1); + /* + * Wait for drive to become non-BUSY + */ + if ((stat = GET_STAT()) & BUSY_STAT) { + unsigned long flags, timeout; + local_irq_set(flags); + timeout = jiffies + WAIT_CMD; + while ((stat = GET_STAT()) & BUSY_STAT) { + if (time_after(jiffies, timeout)) + break; + } + local_irq_restore(flags); + } + + /* + * Allow status to settle, then read it again. + * A few rare drives vastly violate the 400ns spec here, + * so we'll wait up to 10usec for a "good" status + * rather than expensively fail things immediately. + * This fix courtesy of Matthew Faupel & Niccolo Rigacci. + */ + for (i = 0; i < 10; i++) { + udelay(1); + if (OK_STAT((stat = GET_STAT()), DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT)) { + error = 0; + break; + } + } + + SELECT_MASK(HWIF(drive), drive, 0); + + enable_irq(hwif->irq); + + if (error) { + (void) ide_dump_status(drive, "set_drive_speed_status", stat); + return error; + } + + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + +#if defined(CONFIG_BLK_DEV_IDEDMA) && !defined(CONFIG_DMA_NONPCI) + if (speed > XFER_PIO_4) { + outb(inb(hwif->dma_base+2)|(1<<(5+unit)), hwif->dma_base+2); + } else { + outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); + } +#endif /* (CONFIG_BLK_DEV_IDEDMA) && !(CONFIG_DMA_NONPCI) */ + + switch(speed) { + case XFER_UDMA_7: drive->id->dma_ultra |= 0x8080; break; + case XFER_UDMA_6: drive->id->dma_ultra |= 0x4040; break; + case XFER_UDMA_5: drive->id->dma_ultra |= 0x2020; break; + case XFER_UDMA_4: drive->id->dma_ultra |= 0x1010; break; + case XFER_UDMA_3: drive->id->dma_ultra |= 0x0808; break; + case XFER_UDMA_2: drive->id->dma_ultra |= 0x0404; break; + case XFER_UDMA_1: drive->id->dma_ultra |= 0x0202; break; + case XFER_UDMA_0: drive->id->dma_ultra |= 0x0101; break; + case XFER_MW_DMA_2: drive->id->dma_mword |= 0x0404; break; + case XFER_MW_DMA_1: drive->id->dma_mword |= 0x0202; break; + case XFER_MW_DMA_0: drive->id->dma_mword |= 0x0101; break; + case XFER_SW_DMA_2: drive->id->dma_1word |= 0x0404; break; + case XFER_SW_DMA_1: drive->id->dma_1word |= 0x0202; break; + case XFER_SW_DMA_0: drive->id->dma_1word |= 0x0101; break; + default: break; + } + return error; +} + +EXPORT_SYMBOL(eighty_ninty_three); +EXPORT_SYMBOL(ide_auto_reduce_xfer); +EXPORT_SYMBOL(set_transfer); +EXPORT_SYMBOL(taskfile_lib_get_identify); +EXPORT_SYMBOL(ide_driveid_update); +EXPORT_SYMBOL(ide_config_drive_speed); #ifdef CONFIG_PKT_TASK_IOCTL diff -urN linux-2.4.19-p7-pristine/drivers/ide/ide.c linux-2.4.19-p7/drivers/ide/ide.c --- linux-2.4.19-p7-pristine/drivers/ide/ide.c Tue Apr 16 03:15:16 2002 +++ linux-2.4.19-p7/drivers/ide/ide.c Sat Apr 27 21:56:09 2002 @@ -217,13 +217,12 @@ unsigned long t, flags; int i; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); t = jiffies * 11932; outb_p(0, 0x43); i = inb_p(0x40); i |= inb(0x40) << 8; - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); return (t - i); } #endif /* DISK_RECOVERY_TIME */ @@ -373,198 +372,17 @@ return system_bus_speed; } -#if SUPPORT_VLB_SYNC -/* - * Some localbus EIDE interfaces require a special access sequence - * when using 32-bit I/O instructions to transfer data. We call this - * the "vlb_sync" sequence, which consists of three successive reads - * of the sector count register location, with interrupts disabled - * to ensure that the reads all happen together. - */ -static inline void do_vlb_sync (ide_ioreg_t port) { - (void) inb (port); - (void) inb (port); - (void) inb (port); -} -#endif /* SUPPORT_VLB_SYNC */ - -/* - * This is used for most PIO data transfers *from* the IDE interface - */ -void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - byte io_32bit; - - /* first check if this controller has defined a special function - * for handling polled ide transfers - */ - - if(HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_ide_input_data, - drive, buffer, wcount); - return; - } - - io_32bit = drive->io_32bit; - - if (io_32bit) { -#if SUPPORT_VLB_SYNC - if (io_32bit & 2) { - unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - do_vlb_sync(IDE_NSECTOR_REG); - insl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ - } else -#endif /* SUPPORT_VLB_SYNC */ - insl(IDE_DATA_REG, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->slow) { - unsigned short *ptr = (unsigned short *) buffer; - while (wcount--) { - *ptr++ = inw_p(IDE_DATA_REG); - *ptr++ = inw_p(IDE_DATA_REG); - } - } else -#endif /* SUPPORT_SLOW_DATA_PORTS */ - insw(IDE_DATA_REG, buffer, wcount<<1); - } -} - -/* - * This is used for most PIO data transfers *to* the IDE interface - */ -void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount) -{ - byte io_32bit; - - if(HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_ide_output_data, - drive, buffer, wcount); - return; - } - - io_32bit = drive->io_32bit; - - if (io_32bit) { -#if SUPPORT_VLB_SYNC - if (io_32bit & 2) { - unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ - do_vlb_sync(IDE_NSECTOR_REG); - outsl(IDE_DATA_REG, buffer, wcount); - __restore_flags(flags); /* local CPU only */ - } else -#endif /* SUPPORT_VLB_SYNC */ - outsl(IDE_DATA_REG, buffer, wcount); - } else { -#if SUPPORT_SLOW_DATA_PORTS - if (drive->slow) { - unsigned short *ptr = (unsigned short *) buffer; - while (wcount--) { - outw_p(*ptr++, IDE_DATA_REG); - outw_p(*ptr++, IDE_DATA_REG); - } - } else -#endif /* SUPPORT_SLOW_DATA_PORTS */ - outsw(IDE_DATA_REG, buffer, wcount<<1); - } -} - -/* - * The following routines are mainly used by the ATAPI drivers. - * - * These routines will round up any request for an odd number of bytes, - * so if an odd bytecount is specified, be sure that there's at least one - * extra byte allocated for the buffer. - */ -void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) -{ - if(HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_atapi_input_bytes, - drive, buffer, bytecount); - return; - } - - ++bytecount; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - insw_swapw(IDE_DATA_REG, buffer, bytecount / 2); - return; - } -#endif /* CONFIG_ATARI */ - ide_input_data (drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - insw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); -} - -void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount) -{ - if(HWIF(drive)->ideproc) { - HWIF(drive)->ideproc(ideproc_atapi_output_bytes, - drive, buffer, bytecount); - return; - } - - ++bytecount; -#if defined(CONFIG_ATARI) || defined(CONFIG_Q40) - if (MACH_IS_ATARI || MACH_IS_Q40) { - /* Atari has a byte-swapped IDE interface */ - outsw_swapw(IDE_DATA_REG, buffer, bytecount / 2); - return; - } -#endif /* CONFIG_ATARI */ - ide_output_data (drive, buffer, bytecount / 4); - if ((bytecount & 0x03) >= 2) - outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1); -} - -/* - * Needed for PCI irq sharing - */ -//static inline -int drive_is_ready (ide_drive_t *drive) -{ - byte stat = 0; - if (drive->waiting_for_dma) - return HWIF(drive)->dmaproc(ide_dma_test_irq, drive); -#if 0 - udelay(1); /* need to guarantee 400ns since last command was issued */ -#endif - -#ifdef CONFIG_IDEPCI_SHARE_IRQ - /* - * We do a passive status test under shared PCI interrupts on - * cards that truly share the ATA side interrupt, but may also share - * an interrupt with another pci card/device. We make no assumptions - * about possible isa-pnp and pci-pnp issues yet. - */ - if (IDE_CONTROL_REG) - stat = GET_ALTSTAT(); - else -#endif /* CONFIG_IDEPCI_SHARE_IRQ */ - stat = GET_STAT(); /* Note: this may clear a pending IRQ!! */ - - if (stat & BUSY_STAT) - return 0; /* drive busy: definitely not interrupting */ - return 1; /* drive ready: *might* be interrupting */ -} - /* * This is our end_request replacement function. */ -void ide_end_request (byte uptodate, ide_hwgroup_t *hwgroup) +int ide_end_request (ide_drive_t *drive, int uptodate) { struct request *rq; unsigned long flags; - ide_drive_t *drive = hwgroup->drive; + int ret = 1; spin_lock_irqsave(&io_request_lock, flags); - rq = hwgroup->rq; + rq = HWGROUP(drive)->rq; /* * decide whether to reenable DMA -- 3 is a random magic for now, @@ -572,16 +390,18 @@ */ if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { drive->state = 0; - hwgroup->hwif->dmaproc(ide_dma_on, drive); + HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); } - if (!end_that_request_first(rq, uptodate, hwgroup->drive->name)) { + if (!end_that_request_first(rq, uptodate, drive->name)) { add_blkdev_randomness(MAJOR(rq->rq_dev)); blkdev_dequeue_request(rq); - hwgroup->rq = NULL; + HWGROUP(drive)->rq = NULL; end_that_request_last(rq); + ret = 0; } spin_unlock_irqrestore(&io_request_lock, flags); + return ret; } /* @@ -666,7 +486,9 @@ if (OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) { printk("%s: ATAPI reset complete\n", drive->name); } else { - if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { + if (time_before(jiffies, hwgroup->poll_timeout)) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); return ide_started; /* continue polling */ } @@ -691,7 +513,9 @@ byte tmp; if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) { - if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { + if (time_before(jiffies, hwgroup->poll_timeout)) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL); return ide_started; /* continue polling */ } @@ -784,8 +608,7 @@ ide_hwif_t *hwif = HWIF(drive); ide_hwgroup_t *hwgroup = HWGROUP(drive); - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); /* For an ATAPI device, first try an ATAPI SRST. */ if (drive->media != ide_disk && !do_not_try_atapi) { @@ -794,8 +617,10 @@ udelay (20); OUT_BYTE (WIN_SRST, IDE_COMMAND_REG); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20, NULL); - __restore_flags (flags); /* local CPU only */ + local_irq_restore(flags); return ide_started; } @@ -808,7 +633,7 @@ #if OK_TO_RESET_CONTROLLER if (!IDE_CONTROL_REG) { - __restore_flags(flags); + local_irq_restore(flags); return ide_stopped; } /* @@ -828,6 +653,8 @@ } udelay(10); /* more than enough time */ hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &reset_pollfunc, HZ/20, NULL); /* @@ -840,7 +667,7 @@ #endif /* OK_TO_RESET_CONTROLLER */ - __restore_flags (flags); /* local CPU only */ + local_irq_restore(flags); return ide_started; } @@ -875,7 +702,9 @@ case IDE_DRIVE_CMD: { byte *args = (byte *) rq->buffer; - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (args) { args[0] = stat; args[1] = err; @@ -886,7 +715,9 @@ case IDE_DRIVE_TASK: { byte *args = (byte *) rq->buffer; - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (args) { args[0] = stat; args[1] = err; @@ -901,7 +732,9 @@ case IDE_DRIVE_TASKFILE: { ide_task_t *args = (ide_task_t *) rq->special; - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (rq->errors == 0) + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (args) { if (args->tf_in_flags.b.data) { unsigned short data = IN_WORD(IDE_DATA_REG); @@ -947,8 +780,7 @@ unsigned long flags; byte err = 0; - __save_flags (flags); /* local CPU only */ - ide__sti(); /* local CPU only */ + local_irq_set(flags); printk("%s: %s: status=0x%02x", drive->name, msg, stat); #if FANCY_STATUS_DUMPS printk(" { "); @@ -1016,7 +848,7 @@ #endif /* FANCY_STATUS_DUMPS */ printk("\n"); } - __restore_flags (flags); /* local CPU only */ + local_irq_restore(flags); return err; } @@ -1037,11 +869,15 @@ u32 buffer[16]; unsigned int wcount = (i > 16) ? 16 : i; i -= wcount; - ide_input_data (drive, buffer, wcount); + ata_input_data (drive, buffer, wcount); } } /* + * FIXME Add an ATAPI error + */ + +/* * ide_error() takes action based on the error returned by the drive. */ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat) @@ -1068,6 +904,8 @@ if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) { /* other bits are useless when BUSY */ rq->errors |= ERROR_RESET; } else { + +/* ide_disk */ if (drive->media == ide_disk && (stat & ERR_STAT)) { /* err has different meaning on cdrom and tape */ if (err == ABRT_ERR) { @@ -1080,17 +918,19 @@ else if (err & TRK0_ERR) /* help it find track zero */ rq->errors |= ERROR_RECAL; } +/* !ide_disk */ if ((stat & DRQ_STAT) && rq->cmd != WRITE) try_to_flush_leftover_data(drive); +/* !ide_disk */ } if (GET_STAT() & (BUSY_STAT|DRQ_STAT)) OUT_BYTE(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); /* force an abort */ if (rq->errors >= ERROR_MAX) { if (drive->driver != NULL) - DRIVER(drive)->end_request(0, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 0); else - ide_end_request(0, HWGROUP(drive)); + ide_end_request(drive, 0); } else { if ((rq->errors & ERROR_RESET) == ERROR_RESET) { ++rq->errors; @@ -1109,6 +949,8 @@ */ void ide_cmd (ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, handler, WAIT_CMD, NULL); if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ @@ -1127,18 +969,18 @@ byte stat = GET_STAT(); int retries = 10; - ide__sti(); /* local CPU only */ + local_irq_enable(); if ((stat & DRQ_STAT) && args && args[3]) { byte io_32bit = drive->io_32bit; drive->io_32bit = 0; - ide_input_data(drive, &args[4], args[3] * SECTOR_WORDS); + ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS); drive->io_32bit = io_32bit; while (((stat = GET_STAT()) & BUSY_STAT) && retries--) udelay(100); } if (!OK_STAT(stat, READY_STAT, BAD_STAT)) - return ide_error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */ + return DRIVER(drive)->error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */ ide_end_drive_cmd (drive, stat, GET_ERR()); return ide_stopped; } @@ -1169,58 +1011,6 @@ } /* - * This routine busy-waits for the drive status to be not "busy". - * It then checks the status for all of the "good" bits and none - * of the "bad" bits, and if all is okay it returns 0. All other - * cases return 1 after invoking ide_error() -- caller should just return. - * - * This routine should get fixed to not hog the cpu during extra long waits.. - * That could be done by busy-waiting for the first jiffy or two, and then - * setting a timer to wake up at half second intervals thereafter, - * until timeout is achieved, before timing out. - */ -int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout) { - byte stat; - int i; - unsigned long flags; - - /* bail early if we've exceeded max_failures */ - if (drive->max_failures && (drive->failures > drive->max_failures)) { - *startstop = ide_stopped; - return 1; - } - - udelay(1); /* spec allows drive 400ns to assert "BUSY" */ - if ((stat = GET_STAT()) & BUSY_STAT) { - __save_flags(flags); /* local CPU only */ - ide__sti(); /* local CPU only */ - timeout += jiffies; - while ((stat = GET_STAT()) & BUSY_STAT) { - if (0 < (signed long)(jiffies - timeout)) { - __restore_flags(flags); /* local CPU only */ - *startstop = ide_error(drive, "status timeout", stat); - return 1; - } - } - __restore_flags(flags); /* local CPU only */ - } - /* - * Allow status to settle, then read it again. - * A few rare drives vastly violate the 400ns spec here, - * so we'll wait up to 10usec for a "good" status - * rather than expensively fail things immediately. - * This fix courtesy of Matthew Faupel & Niccolo Rigacci. - */ - for (i = 0; i < 10; i++) { - udelay(1); - if (OK_STAT((stat = GET_STAT()), good, bad)) - return 0; - } - *startstop = ide_error(drive, "status error", stat); - return 1; -} - -/* * execute_drive_cmd() issues a special drive command, * usually initiated by ioctl() from the external hdparm program. */ @@ -1233,43 +1023,9 @@ if (!(args)) break; -#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG - { - printk(KERN_INFO "%s: ", drive->name); -// printk("TF.0=x%02x ", args->tfRegister[IDE_DATA_OFFSET]); - printk("TF.1=x%02x ", args->tfRegister[IDE_FEATURE_OFFSET]); - printk("TF.2=x%02x ", args->tfRegister[IDE_NSECTOR_OFFSET]); - printk("TF.3=x%02x ", args->tfRegister[IDE_SECTOR_OFFSET]); - printk("TF.4=x%02x ", args->tfRegister[IDE_LCYL_OFFSET]); - printk("TF.5=x%02x ", args->tfRegister[IDE_HCYL_OFFSET]); - printk("TF.6=x%02x ", args->tfRegister[IDE_SELECT_OFFSET]); - printk("TF.7=x%02x\n", args->tfRegister[IDE_COMMAND_OFFSET]); - printk(KERN_INFO "%s: ", drive->name); -// printk("HTF.0=x%02x ", args->hobRegister[IDE_DATA_OFFSET_HOB]); - printk("HTF.1=x%02x ", args->hobRegister[IDE_FEATURE_OFFSET_HOB]); - printk("HTF.2=x%02x ", args->hobRegister[IDE_NSECTOR_OFFSET_HOB]); - printk("HTF.3=x%02x ", args->hobRegister[IDE_SECTOR_OFFSET_HOB]); - printk("HTF.4=x%02x ", args->hobRegister[IDE_LCYL_OFFSET_HOB]); - printk("HTF.5=x%02x ", args->hobRegister[IDE_HCYL_OFFSET_HOB]); - printk("HTF.6=x%02x ", args->hobRegister[IDE_SELECT_OFFSET_HOB]); - printk("HTF.7=x%02x\n", args->hobRegister[IDE_CONTROL_OFFSET_HOB]); - } -#endif /* CONFIG_IDE_TASK_IOCTL_DEBUG */ - -// if (args->tf_out_flags.all == 0) { - do_taskfile(drive, - (struct hd_drive_task_hdr *)&args->tfRegister, - (struct hd_drive_hob_hdr *)&args->hobRegister, - args->handler); -// } else { -// return flagged_taskfile(drive, args); -// } - - if (((args->command_type == IDE_DRIVE_TASK_RAW_WRITE) || - (args->command_type == IDE_DRIVE_TASK_OUT)) && - args->prehandler && args->handler) - return args->prehandler(drive, rq); - return ide_started; + if (args->tf_out_flags.all != 0) + return flagged_taskfile(drive, args); + return do_rw_taskfile(drive, args); } case IDE_DRIVE_TASK: { @@ -1349,15 +1105,26 @@ ide_hwif_t *hwif = HWIF(drive); #ifdef DEBUG - printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq); + printk("%s: start_request: current=0x%08lx\n", + hwif->name, (unsigned long) rq); #endif + /* bail early if we've exceeded max_failures */ if (drive->max_failures && (drive->failures > drive->max_failures)) { goto kill_rq; } + /* + * bail early if we've sent a device to sleep, however how to wake + * this needs to be a masked flag. FIXME for proper operations. + */ + if (drive->suspend_reset) { + goto kill_rq; + } + if (unit >= MAX_DRIVES) { - printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev)); + printk("%s: bad device number: %s\n", + hwif->name, kdevname(rq->rq_dev)); goto kill_rq; } #ifdef DEBUG @@ -1396,6 +1163,7 @@ switch(rq->cmd) { case IDE_DRIVE_CMD: case IDE_DRIVE_TASK: + return execute_drive_cmd(drive, rq); case IDE_DRIVE_TASKFILE: return execute_drive_cmd(drive, rq); default: @@ -1410,25 +1178,16 @@ return do_special(drive); kill_rq: if (drive->driver != NULL) - DRIVER(drive)->end_request(0, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 0); else - ide_end_request(0, HWGROUP(drive)); + ide_end_request(drive, 0); return ide_stopped; } -ide_startstop_t restart_request (ide_drive_t *drive) +int restart_request (ide_drive_t *drive, struct request *rq) { - ide_hwgroup_t *hwgroup = HWGROUP(drive); - unsigned long flags; - struct request *rq; - - spin_lock_irqsave(&io_request_lock, flags); - hwgroup->handler = NULL; - del_timer(&hwgroup->timer); - rq = hwgroup->rq; - spin_unlock_irqrestore(&io_request_lock, flags); - - return start_request(drive, rq); + (void) start_request(drive, rq); + return 0; } /* @@ -1455,7 +1214,7 @@ best = NULL; drive = hwgroup->drive; do { - if (!list_empty(&drive->queue.queue_head) && (!drive->sleep || 0 <= (signed long)(jiffies - drive->sleep))) { + if (!list_empty(&drive->queue.queue_head) && (!drive->sleep || time_after_eq(jiffies, drive->sleep))) { if (!best || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep))) || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive)))) @@ -1468,10 +1227,10 @@ if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) { long t = (signed long)(WAKEUP(best) - jiffies); if (t >= WAIT_MIN_SLEEP) { - /* - * We *may* have some time to spare, but first let's see if - * someone can potentially benefit from our nice mood today.. - */ + /* + * We *may* have some time to spare, but first let's see if + * someone can potentially benefit from our nice mood today.. + */ drive = best->next; do { if (!drive->sleep @@ -1534,7 +1293,8 @@ ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only: POSSIBLY BROKEN HERE(?) */ - __cli(); /* necessary paranoia: ensure IRQs are masked on local CPU */ + local_irq_disable(); + /* necessary paranoia: ensure IRQs are masked on local CPU */ while (!hwgroup->busy) { hwgroup->busy = 1; @@ -1548,13 +1308,13 @@ sleep = drive->sleep; } while ((drive = drive->next) != hwgroup->drive); if (sleep) { - /* - * Take a short snooze, and then wake up this hwgroup again. - * This gives other hwgroups on the same a chance to - * play fairly with us, just in case there are big differences - * in relative throughputs.. don't want to hog the cpu too much. - */ - if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep)) + /* + * Take a short snooze, and then wake up this hwgroup again. + * This gives other hwgroups on the same a chance to + * play fairly with us, just in case there are big differences + * in relative throughputs.. don't want to hog the cpu too much. + */ + if (time_before(sleep, jiffies + WAIT_MIN_SLEEP)) sleep = jiffies + WAIT_MIN_SLEEP; #if 1 if (timer_pending(&hwgroup->timer)) @@ -1595,7 +1355,8 @@ if (masked_irq && hwif->irq != masked_irq) disable_irq_nosync(hwif->irq); spin_unlock(&io_request_lock); - ide__sti(); /* allow other IRQs while we start this request */ + local_irq_enable(); + /* allow other IRQs while we start this request */ startstop = start_request(drive, rq); spin_lock_irq(&io_request_lock); if (masked_irq && hwif->irq != masked_irq) @@ -1623,6 +1384,7 @@ ide_do_request(q->queuedata, 0); } +#ifndef __IDEDMA_TIMEOUT /* * un-busy the hwgroup etc, and clear any pending DMA status. we want to * retry the current request in pio mode instead of risking tossing it @@ -1663,8 +1425,17 @@ rq->errors = 0; rq->sector = rq->bh->b_rsector; rq->current_nr_sectors = rq->bh->b_size >> 9; + rq->hard_cur_sectors = rq->current_nr_sectors; rq->buffer = rq->bh->b_data; + + /* + * FIXME or DELETE ME + * + * so what do we do if the device is left in an invalid state + * and will not accept commands. SOFT RESET is the only chance. + */ } +#endif /* * ide_timer_expiry() is our timeout function for all drive operations. @@ -1700,7 +1471,7 @@ hwgroup->handler = NULL; } else { ide_hwif_t *hwif; - ide_startstop_t startstop; + ide_startstop_t startstop = ide_stopped; if (!hwgroup->busy) { hwgroup->busy = 1; /* paranoia */ printk("%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name); @@ -1728,7 +1499,8 @@ #else disable_irq(hwif->irq); /* disable_irq_nosync ?? */ #endif /* DISABLE_IRQ_NOSYNC */ - __cli(); /* local CPU only, as if we were handling an interrupt */ + local_irq_disable(); + /* local CPU only, as if we were handling an interrupt */ if (hwgroup->poll_timeout != 0) { startstop = handler(drive); } else if (drive_is_ready(drive)) { @@ -1739,10 +1511,16 @@ startstop = handler(drive); } else { if (drive->waiting_for_dma) { +#ifndef __IDEDMA_TIMEOUT startstop = ide_stopped; ide_dma_timeout_retry(drive); +#else /* __IDEDMA_TIMEOUT */ + (void) hwgroup->hwif->dmaproc(ide_dma_end, drive); + printk("%s: timeout waiting for DMA\n", drive->name); + (void) hwgroup->hwif->dmaproc(ide_dma_timeout, drive); +#endif /* __IDEDMA_TIMEOUT */ } else - startstop = ide_error(drive, "irq timeout", GET_STAT()); + startstop = DRIVER(drive)->error(drive, "irq timeout", GET_STAT()); } set_recovery_timer(hwif); drive->service_time = jiffies - drive->service_start; @@ -1794,7 +1572,7 @@ /* Try to not flood the console with msgs */ static unsigned long last_msgtime, count; ++count; - if (0 < (signed long)(jiffies - (last_msgtime + HZ))) { + if (time_after(jiffies, last_msgtime + HZ)) { last_msgtime = jiffies; printk("%s%s: unexpected interrupt, status=0x%02x, count=%ld\n", hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat, count); @@ -1849,7 +1627,8 @@ #ifdef CONFIG_BLK_DEV_IDEPCI } else { /* - * Whack the status register, just in case we have a leftover pending IRQ. + * Whack the status register, just in case + * we have a leftover pending IRQ. */ (void) IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]); #endif /* CONFIG_BLK_DEV_IDEPCI */ @@ -1860,16 +1639,18 @@ drive = hwgroup->drive; if (!drive) { /* - * This should NEVER happen, and there isn't much we could do about it here. + * This should NEVER happen, and there isn't much + * we could do about it here. */ spin_unlock_irqrestore(&io_request_lock, flags); return; } if (!drive_is_ready(drive)) { /* - * This happens regularly when we share a PCI IRQ with another device. - * Unfortunately, it can also happen with some buggy drives that trigger - * the IRQ before their status register is up to date. Hopefully we have + * This happens regularly when we share a PCI IRQ with + * another device. Unfortunately, it can also happen + * with some buggy drives that trigger the IRQ before + * their status register is up to date. Hopefully we have * enough advance overhead that the latter isn't a problem. */ spin_unlock_irqrestore(&io_request_lock, flags); @@ -1884,7 +1665,7 @@ spin_unlock(&io_request_lock); if (drive->unmask) - ide__sti(); /* local CPU only */ + local_irq_enable(); startstop = handler(drive); /* service this interrupt, may set handler for next interrupt */ spin_lock_irq(&io_request_lock); @@ -2228,8 +2009,7 @@ if (index >= MAX_HWIFS) return; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); hwif = &ide_hwifs[index]; if (!hwif->present) goto abort; @@ -2247,7 +2027,7 @@ /* * All clear? Then blow away the buffer cache */ - sti(); + spin_unlock_irqrestore(&io_request_lock, flags); for (unit = 0; unit < MAX_DRIVES; ++unit) { drive = &hwif->drives[unit]; if (!drive->present) @@ -2263,7 +2043,7 @@ destroy_proc_ide_drives(hwif); #endif } - cli(); + spin_lock_irqsave(&io_request_lock, flags); hwgroup = hwif->hwgroup; /* @@ -2276,7 +2056,7 @@ g = g->next; } while (g != hwgroup->hwif); if (irq_count == 1) - free_irq(hwif->irq, hwgroup); + ide_free_irq(hwif->irq, hwgroup); /* * Note that we only release the standard ports, @@ -2383,7 +2163,7 @@ hwif->straight8 = old_hwif.straight8; hwif->hwif_data = old_hwif.hwif_data; abort: - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -2595,14 +2375,13 @@ while (hwgroup->busy) { unsigned long lflags; spin_unlock_irq(&io_request_lock); - __save_flags(lflags); /* local CPU only */ - __sti(); /* local CPU only; needed for jiffies */ - if (0 < (signed long)(jiffies - timeout)) { - __restore_flags(lflags); /* local CPU only */ + local_irq_set(lflags); + if (time_after(jiffies, timeout)) { + local_irq_restore(lflags); printk("%s: channel busy\n", drive->name); return -EBUSY; } - __restore_flags(lflags); /* local CPU only */ + local_irq_restore(lflags); spin_lock_irq(&io_request_lock); } return 0; @@ -2697,8 +2476,8 @@ ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL); ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma); ide_add_setting(drive, "ide_scsi", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->scsi, NULL); - ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 69, 1, 1, &drive->init_speed, NULL); - ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 69, 1, 1, &drive->current_speed, NULL); + ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL); + ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, NULL); ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL); } @@ -2918,68 +2697,15 @@ #endif /* CONFIG_IDE_TASK_IOCTL */ case HDIO_DRIVE_CMD: - { - byte args[4], *argbuf = args; - byte xfer_rate = 0; - int argsize = 4; - ide_task_t tfargs; - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; - if (NULL == (void *) arg) - return ide_do_drive_cmd(drive, &rq, ide_wait); - if (copy_from_user(args, (void *)arg, 4)) - return -EFAULT; + return ide_cmd_ioctl(drive, inode, file, cmd, arg); - tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2]; - tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3]; - tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1]; - tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00; - tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00; - tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00; - tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0]; - - if (args[3]) { - argsize = 4 + (SECTOR_WORDS * 4 * args[3]); - argbuf = kmalloc(argsize, GFP_KERNEL); - if (argbuf == NULL) - return -ENOMEM; - memcpy(argbuf, args, 4); - } - - if (set_transfer(drive, &tfargs)) { - xfer_rate = args[1]; - if (ide_ata66_check(drive, &tfargs)) - goto abort; - } - - err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf); - - if (!err && xfer_rate) { - /* active-retuning-calls future */ - if ((HWIF(drive)->speedproc) != NULL) - HWIF(drive)->speedproc(drive, xfer_rate); - ide_driveid_update(drive); - } - abort: - if (copy_to_user((void *)arg, argbuf, argsize)) - err = -EFAULT; - if (argsize > 4) - kfree(argbuf); - return err; - } case HDIO_DRIVE_TASK: - { - byte args[7], *argbuf = args; - int argsize = 7; - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; - if (copy_from_user(args, (void *)arg, 7)) - return -EFAULT; - err = ide_wait_cmd_task(drive, argbuf); - if (copy_to_user((void *)arg, argbuf, argsize)) - err = -EFAULT; - return err; - } + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + return -EACCES; + return ide_task_ioctl(drive, inode, file, cmd, arg); + case HDIO_SCAN_HWIF: { int args[3]; @@ -3011,18 +2737,15 @@ case HDIO_DRIVE_RESET: { unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - if (!capable(CAP_SYS_ADMIN)) return -EACCES; #if 1 spin_lock_irqsave(&io_request_lock, flags); - if (hwgroup->handler != NULL) { - printk("%s: ide_set_handler: handler not null; %p\n", drive->name, hwgroup->handler); - (void) hwgroup->handler(drive); -// hwgroup->handler = NULL; -// hwgroup->expiry = NULL; - hwgroup->timer.expires = jiffies + 0;; - del_timer(&hwgroup->timer); + if ( HWGROUP(drive)->handler != NULL) { + printk("%s: ide_set_handler: handler not null; %p\n", drive->name, HWGROUP(drive)->handler); + (void) HWGROUP(drive)->handler(drive); +// HWGROUP(drive)->handler = NULL; + HWGROUP(drive)->expiry = NULL; + del_timer(&HWGROUP(drive)->timer); } spin_unlock_irqrestore(&io_request_lock, flags); @@ -3736,22 +3459,42 @@ return 0; } +static int default_suspend (ide_drive_t *drive) +{ + return 0; +} + +static int default_resume (ide_drive_t *drive) +{ + return 0; +} + static int default_flushcache (ide_drive_t *drive) { return 0; } -static ide_startstop_t default_do_request(ide_drive_t *drive, struct request *rq, unsigned long block) +static ide_startstop_t default_do_request (ide_drive_t *drive, struct request *rq, unsigned long block) { - ide_end_request(0, HWGROUP(drive)); + ide_end_request(drive, 0); return ide_stopped; } - -static void default_end_request (byte uptodate, ide_hwgroup_t *hwgroup) + +static int default_end_request (ide_drive_t *drive, int uptodate) { - ide_end_request(uptodate, hwgroup); + return ide_end_request(drive, uptodate); } - + +static byte default_sense (ide_drive_t *drive, const char *msg, byte stat) +{ + return ide_dump_status(drive, msg, stat); +} + +static ide_startstop_t default_error (ide_drive_t *drive, const char *msg, byte stat) +{ + return ide_error(drive, msg, stat); +} + static int default_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -3791,6 +3534,11 @@ return ide_stopped; } +static int default_init (void) +{ + return 0; +} + static int default_reinit (ide_drive_t *drive) { printk(KERN_ERR "%s: does not support hotswap of device class !\n", drive->name); @@ -3804,9 +3552,13 @@ if (d->cleanup == NULL) d->cleanup = default_cleanup; if (d->standby == NULL) d->standby = default_standby; + if (d->suspend == NULL) d->suspend = default_suspend; + if (d->resume == NULL) d->resume = default_resume; if (d->flushcache == NULL) d->flushcache = default_flushcache; if (d->do_request == NULL) d->do_request = default_do_request; if (d->end_request == NULL) d->end_request = default_end_request; + if (d->sense == NULL) d->sense = default_sense; + if (d->error == NULL) d->error = default_error; if (d->ioctl == NULL) d->ioctl = default_ioctl; if (d->open == NULL) d->open = default_open; if (d->release == NULL) d->release = default_release; @@ -3814,6 +3566,7 @@ if (d->pre_reset == NULL) d->pre_reset = default_pre_reset; if (d->capacity == NULL) d->capacity = default_capacity; if (d->special == NULL) d->special = default_special; + if (d->init == NULL) d->init = default_init; if (d->reinit == NULL) d->reinit = default_reinit; } @@ -3841,15 +3594,15 @@ { unsigned long flags; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - if (version != IDE_SUBDRIVER_VERSION || !drive->present || drive->driver != NULL || drive->busy || drive->usage) { - restore_flags(flags); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); + if (version != IDE_SUBDRIVER_VERSION || !drive->present || + drive->driver != NULL || drive->busy || drive->usage) { + spin_unlock_irqrestore(&io_request_lock, flags); return 1; } drive->driver = driver; setup_driver_defaults(drive); - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); if (drive->autotune != 2) { if (driver->supports_dma && HWIF(drive)->dmaproc != NULL) { /* @@ -3877,10 +3630,10 @@ { unsigned long flags; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - if (drive->usage || drive->busy || drive->driver == NULL || DRIVER(drive)->busy) { - restore_flags(flags); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); + if (drive->usage || drive->busy || + drive->driver == NULL || DRIVER(drive)->busy) { + spin_unlock_irqrestore(&io_request_lock, flags); return 1; } #if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE) @@ -3892,7 +3645,7 @@ #endif auto_remove_settings(drive); drive->driver = NULL; - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); return 0; } @@ -3955,16 +3708,10 @@ EXPORT_SYMBOL(ide_register_subdriver); EXPORT_SYMBOL(ide_unregister_subdriver); EXPORT_SYMBOL(ide_replace_subdriver); -EXPORT_SYMBOL(ide_input_data); -EXPORT_SYMBOL(ide_output_data); -EXPORT_SYMBOL(atapi_input_bytes); -EXPORT_SYMBOL(atapi_output_bytes); -EXPORT_SYMBOL(drive_is_ready); EXPORT_SYMBOL(ide_set_handler); EXPORT_SYMBOL(ide_dump_status); EXPORT_SYMBOL(ide_error); EXPORT_SYMBOL(ide_fixstring); -EXPORT_SYMBOL(ide_wait_stat); EXPORT_SYMBOL(ide_do_reset); EXPORT_SYMBOL(restart_request); EXPORT_SYMBOL(ide_init_drive_cmd); diff -urN linux-2.4.19-p7-pristine/drivers/ide/it8172.c linux-2.4.19-p7/drivers/ide/it8172.c --- linux-2.4.19-p7-pristine/drivers/ide/it8172.c Tue Apr 16 03:15:16 2002 +++ linux-2.4.19-p7/drivers/ide/it8172.c Sat Apr 20 01:21:17 2002 @@ -95,10 +95,9 @@ drive_enables |= 0x0006; } - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); pci_write_config_word(HWIF(drive)->pci_dev, 0x40, drive_enables); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags) } #if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING) @@ -284,3 +283,17 @@ memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); hwif->noprobe = 0; } + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init it8172_device_fixup (struct pci_dev *dev, ide_pci_device_t *d) +{ + if ((!(PCI_FUNC(dev->devfn) & 1) || + (!((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))) + return; /* IT8172 is more than only a IDE controller */ + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} + diff -urN linux-2.4.19-p7-pristine/drivers/ide/ns87415.c linux-2.4.19-p7/drivers/ide/ns87415.c --- linux-2.4.19-p7-pristine/drivers/ide/ns87415.c Tue Jun 20 07:52:36 2000 +++ linux-2.4.19-p7/drivers/ide/ns87415.c Tue Apr 16 23:16:58 2002 @@ -38,8 +38,7 @@ struct pci_dev *dev = hwif->pci_dev; unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); new = *old; /* Adjust IRQ enable bit */ @@ -73,7 +72,7 @@ udelay(10); } - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); } static void ns87415_selectproc (ide_drive_t *drive) diff -urN linux-2.4.19-p7-pristine/drivers/ide/opti621.c linux-2.4.19-p7/drivers/ide/opti621.c --- linux-2.4.19-p7-pristine/drivers/ide/opti621.c Tue May 1 16:05:00 2001 +++ linux-2.4.19-p7/drivers/ide/opti621.c Sat Apr 20 01:21:18 2002 @@ -97,6 +97,7 @@ #include #include #include +#include #include #include @@ -276,8 +277,7 @@ hwif->name, ax, second.data_time, second.recovery_time, drdy); #endif - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); reg_base = hwif->io_ports[IDE_DATA_OFFSET]; outb(0xc0, reg_base+CNTRL_REG); /* allow Register-B */ @@ -302,7 +302,7 @@ write_reg(misc, MISC_REG); /* set address setup, DRDY timings, */ /* and read prefetch for both drives */ - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); } /* @@ -314,3 +314,16 @@ hwif->drives[1].drive_data = PIO_DONT_KNOW; hwif->tuneproc = &opti621_tune_drive; } + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init opti621_device_fixup (struct pci_dev *dev, ide_pci_device_t *d) +{ + if (!(PCI_FUNC(dev->devfn) & 1)) + return; /* OPTI621 is more than only a IDE controller */ + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} + diff -urN linux-2.4.19-p7-pristine/drivers/ide/pdc202xx.c linux-2.4.19-p7/drivers/ide/pdc202xx.c --- linux-2.4.19-p7-pristine/drivers/ide/pdc202xx.c Tue Apr 16 03:15:17 2002 +++ linux-2.4.19-p7/drivers/ide/pdc202xx.c Sat Apr 20 01:21:18 2002 @@ -1,8 +1,7 @@ /* - * linux/drivers/ide/pdc202xx.c Version 0.30 Mar. 18, 2000 + * linux/drivers/ide/pdc202xx.c Version 0.35 Mar. 30, 2002 * - * Copyright (C) 1998-2000 Andre Hedrick - * May be copied or modified under the terms of the GNU General Public License + * Copyright (C) 1998-2002 Andre Hedrick * * Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this * compiled into the kernel if you have more than one card installed. @@ -63,8 +62,23 @@ static int pdc202xx_get_info(char *, char **, off_t, int); extern int (*pdc202xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static struct pci_dev *bmide_dev; + +byte pdc202xx_proc = 0; + +#define PDC202_MAX_DEVS 5 + +static struct pci_dev *pdc202_devs[PDC202_MAX_DEVS]; +static int n_pdc202_devs; + +const char *pdc_quirk_drives[] = { + "QUANTUM FIREBALLlct08 08", + "QUANTUM FIREBALLP KA6.4", + "QUANTUM FIREBALLP LM20.4", + "QUANTUM FIREBALLP KX20.5", + "QUANTUM FIREBALLP KX27.3", + "QUANTUM FIREBALLP LM20.5", + NULL +}; char *pdc202xx_pio_verbose (u32 drive_pci) { @@ -221,14 +235,19 @@ case PCI_DEVICE_ID_PROMISE_20275: p += sprintf(p, "\n PDC20275 Chipset.\n"); break; + case PCI_DEVICE_ID_PROMISE_20271: + p += sprintf(p, "\n PDC20271 Chipset.\n"); + break; case PCI_DEVICE_ID_PROMISE_20269: p += sprintf(p, "\n PDC20269 TX2 Chipset.\n"); break; case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20268R: p += sprintf(p, "\n PDC20268 TX2 Chipset.\n"); break; -default: + case PCI_DEVICE_ID_PROMISE_20268R: + p += sprintf(p, "\n PDC20270 TX2/4 Chipset.\n"); + break; + default: p += sprintf(p, "\n PDC202XX Chipset.\n"); break; } @@ -238,36 +257,29 @@ static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - switch(bmide_dev->device) { - case PCI_DEVICE_ID_PROMISE_20276: - case PCI_DEVICE_ID_PROMISE_20275: - case PCI_DEVICE_ID_PROMISE_20269: - case PCI_DEVICE_ID_PROMISE_20268: - case PCI_DEVICE_ID_PROMISE_20268R: - p = pdc202xx_info_new(buffer, bmide_dev); - break; - default: - p = pdc202xx_info(buffer, bmide_dev); - break; + int i; + + for (i = 0; i < n_pdc202_devs; i++) { + struct pci_dev *dev = pdc202_devs[i]; + + switch(dev->device) { + case PCI_DEVICE_ID_PROMISE_20276: + case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: + case PCI_DEVICE_ID_PROMISE_20269: + case PCI_DEVICE_ID_PROMISE_20268: + case PCI_DEVICE_ID_PROMISE_20268R: + p = pdc202xx_info_new(buffer, dev); + break; + default: + p = pdc202xx_info(buffer, dev); + break; + } } return p-buffer; /* => must be less than 4k! */ } #endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */ -byte pdc202xx_proc = 0; - -const char *pdc_quirk_drives[] = { - "QUANTUM FIREBALLlct08 08", - "QUANTUM FIREBALLP KA6.4", - "QUANTUM FIREBALLP LM20.4", - "QUANTUM FIREBALLP KX20.5", - "QUANTUM FIREBALLP KX27.3", - "QUANTUM FIREBALLP LM20.5", - NULL -}; - -extern char *ide_xfer_verbose (byte xfer_rate); - /* A Register */ #define SYNC_ERRDY_EN 0xC0 @@ -718,7 +730,6 @@ unsigned short EP; byte CLKSPD = 0; byte udma_33 = ultra; -// byte udma_33 = ultra ? (IN_BYTE(high_16 + 0x001f) & 1) : 0; byte udma_66 = ((eighty_ninty_three(drive)) && udma_33) ? 1 : 0; byte udma_100 = 0; byte udma_133 = 0; @@ -727,14 +738,11 @@ byte ultra_66 = ((id->dma_ultra & 0x0010) || (id->dma_ultra & 0x0008)) ? 1 : 0; - byte ultra_100 = ((id->dma_ultra & 0x0020) || - (ultra_66)) ? 1 : 0; - byte ultra_133 = ((id->dma_ultra & 0x0040) || - (ultra_100)) ? 1 : 0; switch(dev->device) { case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: case PCI_DEVICE_ID_PROMISE_20269: udma_133 = (udma_66) ? 1 : 0; udma_100 = (udma_66) ? 1 : 0; @@ -787,9 +795,11 @@ * parameters. */ - if (((ultra_66) || (ultra_100) || (ultra_133)) && (cable)) { + if ((ultra_66) && (cable)) { #ifdef DEBUG - printk("ULTRA66: %s channel of Ultra 66 requires an 80-pin cable for Ultra66 operation.\n", hwif->channel ? "Secondary" : "Primary"); + printk("ULTRA 66/100/133: %s channel of Ultra 66/100/133 " + "requires an 80-pin cable for Ultra66 operation.\n", + hwif->channel ? "Secondary" : "Primary"); printk(" Switching to Ultra33 mode.\n"); #endif /* DEBUG */ /* Primary : zero out second bit */ @@ -798,19 +808,15 @@ OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11)); printk("Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); printk("%s reduced to Ultra33 mode.\n", drive->name); - udma_66 = 0; udma_100 = 0; udma_133 = 0; + udma_66 = 0; } else { - if ((ultra_66) || (ultra_100) || (ultra_133)) { + if (ultra_66) { /* * check to make sure drive on same channel * is u66 capable */ if (hwif->drives[!(drive->dn%2)].id) { - if ((hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0040) || - (hwif->drives[!(drive->dn%2)].id->dma_ultra -& 0x0020) || - (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0010) || - (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0008)) { + if (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0078) { if (!jumpbit) OUT_BYTE(CLKSPD | mask, (high_16 + 0x11)); } else { @@ -918,9 +924,12 @@ static int config_drive_xfer_rate (ide_drive_t *drive) { - struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); - ide_dma_action_t dma_func = ide_dma_off_quietly; + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + ide_dma_action_t dma_func = ide_dma_off_quietly; + + (void) config_chipset_for_pio(drive, 5); + drive->init_speed = 0; if (id && (id->capability & 1) && hwif->autodma) { /* Consult the list of known "bad" drives */ @@ -991,6 +1000,7 @@ switch (dev->device) { case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: case PCI_DEVICE_ID_PROMISE_20269: case PCI_DEVICE_ID_PROMISE_20268R: case PCI_DEVICE_ID_PROMISE_20268: @@ -1061,25 +1071,34 @@ void pdc202xx_new_reset (ide_drive_t *drive) { - OUT_BYTE(0x04,IDE_CONTROL_REG); - mdelay(1000); - OUT_BYTE(0x00,IDE_CONTROL_REG); - mdelay(1000); + /* + * Deleted this because it is redundant from the caller. + */ printk("PDC202XX: %s channel reset.\n", HWIF(drive)->channel ? "Secondary" : "Primary"); } -void pdc202xx_reset (ide_drive_t *drive) +void pdc202xx_reset_pci (struct pci_dev *dev) { - unsigned long high_16 = pci_resource_start(HWIF(drive)->pci_dev, 4); + unsigned long high_16 = pci_resource_start(dev, 4); byte udma_speed_flag = IN_BYTE(high_16 + 0x001f); OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f); mdelay(100); OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f); mdelay(2000); /* 2 seconds ?! */ +} + +void pdc202xx_reset_host (ide_hwif_t *hwif) +{ + pdc202xx_reset_pci(hwif->pci_dev); printk("PDC202XX: %s channel reset.\n", - HWIF(drive)->channel ? "Secondary" : "Primary"); + hwif->channel ? "Secondary" : "Primary"); +} + +void pdc202xx_reset (ide_drive_t *drive) +{ + pdc202xx_reset_host(HWIF(drive)); } /* @@ -1117,13 +1136,16 @@ byte newchip = 0; if (dev->resource[PCI_ROM_RESOURCE].start) { - pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); + pci_write_config_dword(dev, PCI_ROM_ADDRESS, + dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); + printk("%s: ROM enabled at 0x%08lx\n", + name, dev->resource[PCI_ROM_RESOURCE].start); } switch (dev->device) { case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: case PCI_DEVICE_ID_PROMISE_20269: case PCI_DEVICE_ID_PROMISE_20268R: case PCI_DEVICE_ID_PROMISE_20268: @@ -1131,10 +1153,7 @@ break; case PCI_DEVICE_ID_PROMISE_20267: case PCI_DEVICE_ID_PROMISE_20265: - OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f); - mdelay(100); - OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f); - mdelay(2000); /* 2 seconds ?! */ + pdc202xx_reset_pci(dev); break; case PCI_DEVICE_ID_PROMISE_20262: /* @@ -1147,10 +1166,7 @@ * reset leaves the timing registers intact, * but resets the drives. */ - OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f); - mdelay(100); - OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f); - mdelay(2000); /* 2 seconds ?! */ + pdc202xx_reset_pci(dev); default: if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) { byte irq = 0, irq2 = 0; @@ -1201,13 +1217,15 @@ fttk_tx_series: + pdc202_devs[n_pdc202_devs++] = dev; + #if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) if (!pdc202xx_proc) { pdc202xx_proc = 1; - bmide_dev = dev; pdc202xx_display_info = &pdc202xx_get_info; } #endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ + return dev->irq; } @@ -1219,6 +1237,7 @@ switch(hwif->pci_dev->device) { case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: case PCI_DEVICE_ID_PROMISE_20269: case PCI_DEVICE_ID_PROMISE_20268: case PCI_DEVICE_ID_PROMISE_20268R: @@ -1238,6 +1257,7 @@ switch(hwif->pci_dev->device) { case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20275: + case PCI_DEVICE_ID_PROMISE_20271: case PCI_DEVICE_ID_PROMISE_20269: case PCI_DEVICE_ID_PROMISE_20268: case PCI_DEVICE_ID_PROMISE_20268R: @@ -1278,4 +1298,60 @@ hwif->drives[1].autotune = 1; hwif->autodma = 0; #endif /* CONFIG_BLK_DEV_IDEDMA */ +} + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init pdc20265_device_fixup (struct pci_dev *dev, ide_pci_device_t *d) +{ + if ((dev->bus->self) && + (dev->bus->self->vendor == PCI_VENDOR_ID_INTEL) && + (dev->bus->self->device == PCI_DEVICE_ID_INTEL_I960)) { + printk(KERN_INFO "ide: Skipping Promise PDC20265 " + "attached to I2O RAID controller.\n"); + return; + } + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} + +void __init pdc20270_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) +{ + struct pci_dev *dev2 = NULL, *findev; + ide_pci_device_t *d2; + + if ((dev->bus->self && + dev->bus->self->vendor == PCI_VENDOR_ID_DEC) && + (dev->bus->self->device == PCI_DEVICE_ID_DEC_21150)) { + if (PCI_SLOT(dev->devfn) & 2) { + return; + } + d->extra = 0; + pci_for_each_dev(findev) { + if ((findev->vendor == dev->vendor) && + (findev->device == dev->device) && + (PCI_SLOT(findev->devfn) & 2)) { + byte irq = 0, irq2 = 0; + dev2 = findev; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); + if (irq != irq2) { + dev2->irq = dev->irq; + pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, irq); + } + } + } + } + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); + if (!dev2) + return; + d2 = d; + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d2->name, dev2->bus->number, dev2->devfn); + ide_setup_pci_device(dev2, d2); } diff -urN linux-2.4.19-p7-pristine/drivers/ide/pdc4030.c linux-2.4.19-p7/drivers/ide/pdc4030.c --- linux-2.4.19-p7-pristine/drivers/ide/pdc4030.c Tue Apr 16 03:15:18 2002 +++ linux-2.4.19-p7/drivers/ide/pdc4030.c Mon Apr 22 20:31:26 2002 @@ -89,12 +89,6 @@ #include "pdc4030.h" -#ifdef CONFIG_IDE_TASKFILE_IO -# define __TASKFILE__IO -#else /* CONFIG_IDE_TASKFILE_IO */ -# undef __TASKFILE__IO -#endif /* CONFIG_IDE_TASKFILE_IO */ - /* * promise_selectproc() is invoked by ide.c * in preparation for access to the specified drive. @@ -174,7 +168,8 @@ if (hwif->chipset == ide_pdc4030) /* we've already been found ! */ return 1; - if (IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF) { + if (IN_BYTE(IDE_NSECTOR_REG) == 0xFF || + IN_BYTE(IDE_SECTOR_REG) == 0xFF) { return 0; } if (IDE_CONTROL_REG) @@ -187,7 +182,7 @@ "%s: Failed Promise read config!\n",hwif->name); return 0; } - ide_input_data(drive,&ident,SECTOR_WORDS); + ata_input_data(drive, &ident, SECTOR_WORDS); if (ident.id[1] != 'P' || ident.id[0] != 'T') { return 0; } @@ -240,7 +235,7 @@ #ifdef DEBUG printk(KERN_DEBUG "Shifting i/f %d values to i/f %d\n",i-1,i); -#endif +#endif /* DEBUG */ ide_init_hwif_ports(&h->hw, (h-1)->io_ports[IDE_DATA_OFFSET], 0, NULL); memcpy(h->io_ports, h->hw.io_ports, sizeof(h->io_ports)); h->noprobe = (h-1)->noprobe; @@ -313,10 +308,13 @@ int total_remaining; unsigned int sectors_left, sectors_avail, nsect; struct request *rq; +#ifdef CONFIG_IDE_TASKFILE_IO + unsigned long flags; + char *to; +#endif /* CONFIG_IDE_TASKFILE_IO */ - if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { - return ide_error(drive, "promise_read_intr", stat); - } + if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) + return DRIVER(drive)->error(drive, "promise_read_intr", stat); read_again: do { @@ -334,20 +332,36 @@ if (nsect > sectors_avail) nsect = sectors_avail; sectors_avail -= nsect; - ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); +#ifdef CONFIG_IDE_TASKFILE_IO + to = ide_map_buffer(rq, &flags); + ata_input_data(drive, to, nsect * SECTOR_WORDS); +#else /* !CONFIG_IDE_TASKFILE_IO */ + ata_input_data(drive, rq->buffer, nsect * SECTOR_WORDS); +#endif /* CONFIG_IDE_TASKFILE_IO */ + #ifdef DEBUG_READ printk(KERN_DEBUG "%s: promise_read: sectors(%ld-%ld), " "buf=0x%08lx, rem=%ld\n", drive->name, rq->sector, - rq->sector+nsect-1, (unsigned long) rq->buffer, + rq->sector+nsect-1, +#ifdef CONFIG_IDE_TASKFILE_IO + (unsigned long) to, +#else /* !CONFIG_IDE_TASKFILE_IO */ + (unsigned long) rq->buffer, +#endif /* CONFIG_IDE_TASKFILE_IO */ rq->nr_sectors-nsect); -#endif - rq->sector += nsect; +#endif /* DEBUG_READ */ + +#ifdef CONFIG_IDE_TASKFILE_IO + ide_unmap_buffer(to, &flags); +#else /* !CONFIG_IDE_TASKFILE_IO */ rq->buffer += nsect<<9; +#endif /* CONFIG_IDE_TASKFILE_IO */ + rq->sector += nsect; rq->errors = 0; rq->nr_sectors -= nsect; total_remaining = rq->nr_sectors; if ((rq->current_nr_sectors -= nsect) <= 0) { - ide_end_request(1, HWGROUP(drive)); + DRIVER(drive)->end_request(drive, 1); } /* * Now the data has been read in, do the following: @@ -367,16 +381,18 @@ if (stat & DRQ_STAT) goto read_again; if (stat & BUSY_STAT) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &promise_read_intr, WAIT_CMD, NULL); #ifdef DEBUG_READ printk(KERN_DEBUG "%s: promise_read: waiting for" "interrupt\n", drive->name); -#endif +#endif /* DEBUG_READ */ return ide_started; } printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left " "!DRQ !BUSY\n", drive->name); - return ide_error(drive, "promise read intr", stat); + return DRIVER(drive)->error(drive, "promise read intr", stat); } return ide_stopped; } @@ -397,27 +413,95 @@ if (GET_STAT() & BUSY_STAT) { if (time_before(jiffies, hwgroup->poll_timeout)) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); return ide_started; /* continue polling... */ } hwgroup->poll_timeout = 0; printk(KERN_ERR "%s: completion timeout - still busy!\n", drive->name); - return ide_error(drive, "busy timeout", GET_STAT()); + return DRIVER(drive)->error(drive, "busy timeout", GET_STAT()); } hwgroup->poll_timeout = 0; #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name); -#endif +#endif /* DEBUG_WRITE */ for (i = rq->nr_sectors; i > 0; ) { i -= rq->current_nr_sectors; - ide_end_request(1, hwgroup); + DRIVER(drive)->end_request(drive, 1); } return ide_stopped; } /* + * promise_multwrite() transfers a block of up to mcount sectors of data + * to a drive as part of a disk multiple-sector write operation. + * + * Returns 0 on success. + * + * Note that we may be called from two contexts - the do_rw_disk context + * and IRQ context. The IRQ can happen any time after we've output the + * full "mcount" number of sectors, so we must make sure we update the + * state _before_ we output the final part of the data! + */ +int promise_multwrite (ide_drive_t *drive, unsigned int mcount) +{ + ide_hwgroup_t *hwgroup = HWGROUP(drive); + struct request *rq = &hwgroup->wrq; + + do { + char *buffer; + int nsect = rq->current_nr_sectors; +#ifdef CONFIG_IDE_TASKFILE_IO + unsigned long flags; +#endif /* CONFIG_IDE_TASKFILE_IO */ + + if (nsect > mcount) + nsect = mcount; + mcount -= nsect; +#ifdef CONFIG_IDE_TASKFILE_IO + buffer = ide_map_buffer(rq, &flags); + rq->sector += nsect; +#else /* !CONFIG_IDE_TASKFILE_IO */ + buffer = rq->buffer; + + rq->sector += nsect; + rq->buffer += nsect << 9; +#endif /* CONFIG_IDE_TASKFILE_IO */ + rq->nr_sectors -= nsect; + rq->current_nr_sectors -= nsect; + + /* Do we move to the next bh after this? */ + if (!rq->current_nr_sectors) { + struct buffer_head *bh = rq->bh->b_reqnext; + + /* end early early we ran out of requests */ + if (!bh) { + mcount = 0; + } else { + rq->bh = bh; + rq->current_nr_sectors = bh->b_size >> 9; + rq->hard_cur_sectors = rq->current_nr_sectors; + rq->buffer = bh->b_data; + } + } + + /* + * Ok, we're all setup for the interrupt + * re-entering us on the last transfer. + */ + taskfile_output_data(drive, buffer, nsect<<7); +#ifdef CONFIG_IDE_TASKFILE_IO + ide_unmap_buffer(buffer, &flags); +#endif /* CONFIG_IDE_TASKFILE_IO */ + } while (mcount); + + return 0; +} + +/* * promise_write_pollfunc() is the handler for disk write completion polling. */ static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive) @@ -426,24 +510,28 @@ if (IN_BYTE(IDE_NSECTOR_REG) != 0) { if (time_before(jiffies, hwgroup->poll_timeout)) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL); return ide_started; /* continue polling... */ } hwgroup->poll_timeout = 0; printk(KERN_ERR "%s: write timed-out!\n",drive->name); - return ide_error (drive, "write timeout", GET_STAT()); + return DRIVER(drive)->error(drive, "write timeout", GET_STAT()); } /* * Now write out last 4 sectors and poll for not BUSY */ - ide_multwrite(drive, 4); + promise_multwrite(drive, 4); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", drive->name, GET_STAT()); -#endif +#endif /* DEBUG_WRITE */ return ide_started; } @@ -463,16 +551,18 @@ printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), " "buffer=%p\n", drive->name, rq->sector, rq->sector + rq->nr_sectors - 1, rq->buffer); -#endif +#endif /* DEBUG_WRITE */ /* * If there are more than 4 sectors to transfer, do n-4 then go into * the polling strategy as defined above. */ if (rq->nr_sectors > 4) { - if (ide_multwrite(drive, rq->nr_sectors - 4)) + if (promise_multwrite(drive, rq->nr_sectors - 4)) return ide_stopped; hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL); return ide_started; } else { @@ -480,14 +570,16 @@ * There are 4 or fewer sectors to transfer, do them all in one go * and wait for NOT BUSY. */ - if (ide_multwrite(drive, rq->nr_sectors)) + if (promise_multwrite(drive, rq->nr_sectors)) return ide_stopped; hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " "status = %02x\n", drive->name, GET_STAT()); -#endif +#endif /* DEBUG_WRITE */ return ide_started; } } @@ -497,17 +589,40 @@ * already set up. It issues a READ or WRITE command to the Promise * controller, assuming LBA has been used to set up the block number. */ +#ifndef CONFIG_IDE_TASKFILE_IO ide_startstop_t do_pdc4030_io (ide_drive_t *drive, struct request *rq) { +#else /* CONFIG_IDE_TASKFILE_IO */ +ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task) +{ + struct request *rq = HWGROUP(drive)->rq; + task_struct_t *taskfile = (task_struct_t *) task->tfRegister; +#endif /* CONFIG_IDE_TASKFILE_IO */ ide_startstop_t startstop; unsigned long timeout; byte stat; +#ifdef CONFIG_IDE_TASKFILE_IO + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */ + SELECT_MASK(HWIF(drive), drive, 0); + + OUT_BYTE(taskfile->feature, IDE_FEATURE_REG); + OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG); + /* refers to number of sectors to transfer */ + OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG); + /* refers to sector offset or start sector */ + OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG); + OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG); + OUT_BYTE(taskfile->device_head, IDE_SELECT_REG); + OUT_BYTE(taskfile->command, IDE_COMMAND_REG); +#endif /* CONFIG_IDE_TASKFILE_IO */ + switch(rq->cmd) { - case READ: -#ifndef __TASKFILE__IO - OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG); -#endif + case READ: +#ifndef CONFIG_IDE_TASKFILE_IO + OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG); +#endif /* CONFIG_IDE_TASKFILE_IO */ /* * The card's behaviour is odd at this point. If the data is * available, DRQ will be true, and no interrupt will be @@ -518,49 +633,55 @@ * If neither of these is the case, we wait for up to 50ms (badly I'm * afraid!) until one of them is. */ - timeout = jiffies + HZ/20; /* 50ms wait */ - do { - stat=GET_STAT(); - if (stat & DRQ_STAT) { - udelay(1); - return promise_read_intr(drive); - } - if (IN_BYTE(IDE_SELECT_REG) & 0x01) { -#ifdef DEBUG_READ - printk(KERN_DEBUG "%s: read: waiting for interrupt\n", drive->name); -#endif - ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL); - return ide_started; - } + timeout = jiffies + HZ/20; /* 50ms wait */ + do { + stat=GET_STAT(); + if (stat & DRQ_STAT) { udelay(1); - } while (time_before(jiffies, timeout)); + return promise_read_intr(drive); + } + if (IN_BYTE(IDE_SELECT_REG) & 0x01) { +#ifdef DEBUG_READ + printk(KERN_DEBUG "%s: read: waiting for " + "interrupt\n", drive->name); +#endif /* DEBUG_READ */ + ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL); + return ide_started; + } + udelay(1); + } while (time_before(jiffies, timeout)); - printk(KERN_ERR "%s: reading: No DRQ and not waiting - Odd!\n", drive->name); - return ide_stopped; - case WRITE: -#ifndef __TASKFILE__IO - OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG); -#endif - if (ide_wait_stat(&startstop, drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { - printk(KERN_ERR "%s: no DRQ after issuing PROMISE_WRITE\n", drive->name); - return startstop; - } - if (!drive->unmask) - __cli(); /* local CPU only */ - HWGROUP(drive)->wrq = *rq; /* scratchpad */ - return promise_write(drive); - default: - printk("KERN_WARNING %s: bad command: %d\n", drive->name, rq->cmd); - ide_end_request(0, HWGROUP(drive)); - return ide_stopped; + printk(KERN_ERR "%s: reading: No DRQ and not " + "waiting - Odd!\n", drive->name); + return ide_stopped; + case WRITE: +#ifndef CONFIG_IDE_TASKFILE_IO + OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG); +#endif /* CONFIG_IDE_TASKFILE_IO */ + if (ide_wait_stat(&startstop, drive, DATA_READY, + drive->bad_wstat, WAIT_DRQ)) { + printk(KERN_ERR "%s: no DRQ after issuing " + "PROMISE_WRITE\n", drive->name); + return startstop; + } + if (!drive->unmask) + local_irq_disable(); + HWGROUP(drive)->wrq = *rq; /* scratchpad */ + return promise_write(drive); + default: + printk("KERN_WARNING %s: bad command: %d\n", + drive->name, rq->cmd); + DRIVER(drive)->end_request(drive, 0); + return ide_stopped; } } -#ifdef __TASKFILE__IO +#ifdef CONFIG_IDE_TASKFILE_IO ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block) { - struct hd_drive_task_hdr taskfile; + struct hd_drive_task_hdr taskfile; + ide_task_t args; memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr)); @@ -571,8 +692,17 @@ taskfile.device_head = ((block>>8)&0x0f)|drive->select.all; taskfile.command = (rq->cmd==READ)?PROMISE_READ:PROMISE_WRITE; - do_taskfile(drive, &taskfile, NULL, NULL); - return do_pdc4030_io(drive, rq); + memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr)); + memcpy(args.hobRegister, NULL, sizeof(struct hd_drive_hob_hdr)); + args.command_type = ide_cmd_type_parser(&args); + args.prehandler = NULL; + args.handler = NULL; + args.posthandler = NULL; + args.rq = (struct request *) rq; + rq->special = NULL; + rq->special = (ide_task_t *)&args; + + return do_pdc4030_io(drive, &args); } -#endif +#endif /* CONFIG_IDE_TASKFILE_IO */ diff -urN linux-2.4.19-p7-pristine/drivers/ide/pdcadma.c linux-2.4.19-p7/drivers/ide/pdcadma.c --- linux-2.4.19-p7-pristine/drivers/ide/pdcadma.c Wed Dec 31 16:00:00 1969 +++ linux-2.4.19-p7/drivers/ide/pdcadma.c Tue Apr 16 23:16:58 2002 @@ -0,0 +1,106 @@ +/* + * linux/drivers/ide/pdcadma.c Version 0.01 June 21, 2001 + * + * Copyright (C) 1999-2000 Andre Hedrick + * May be copied or modified under the terms of the GNU General Public License + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "ide_modes.h" + +#undef DISPLAY_PDCADMA_TIMINGS + +#if defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static int pdcadma_get_info(char *, char **, off_t, int); +extern int (*pdcadma_display_info)(char *, char **, off_t, int); /* ide-proc.c */ +static struct pci_dev *bmide_dev; + +static int pdcadma_get_info (char *buffer, char **addr, off_t offset, int count) +{ + char *p = buffer; + u32 bibma = pci_resource_start(bmide_dev, 4); + + p += sprintf(p, "\n PDC ADMA %04X Chipset.\n", bmide_dev->device); + p += sprintf(p, "UDMA\n"); + p += sprintf(p, "PIO\n"); + + return p-buffer; /* => must be less than 4k! */ +} +#endif /* defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) */ + +byte pdcadma_proc = 0; + +#ifdef CONFIG_BLK_DEV_IDEDMA +/* + * pdcadma_dmaproc() initiates/aborts (U)DMA read/write operations on a drive. + */ + +int pdcadma_dmaproc (ide_dma_action_t func, ide_drive_t *drive) +{ + switch (func) { + case ide_dma_check: + func = ide_dma_off_quietly; + default: + break; + } + return ide_dmaproc(func, drive); /* use standard DMA stuff */ +} +#endif /* CONFIG_BLK_DEV_IDEDMA */ + +unsigned int __init pci_init_pdcadma (struct pci_dev *dev, const char *name) +{ +#if defined(DISPLAY_PDCADMA_TIMINGS) && defined(CONFIG_PROC_FS) + if (!pdcadma_proc) { + pdcadma_proc = 1; + bmide_dev = dev; + pdcadma_display_info = &pdcadma_get_info; + } +#endif /* DISPLAY_PDCADMA_TIMINGS && CONFIG_PROC_FS */ + return 0; +} + +unsigned int __init ata66_pdcadma (ide_hwif_t *hwif) +{ + return 1; +} + +void __init ide_init_pdcadma (ide_hwif_t *hwif) +{ + hwif->autodma = 0; + hwif->dma_base = 0; + +// hwif->tuneproc = &pdcadma_tune_drive; +// hwif->speedproc = &pdcadma_tune_chipset; + +// if (hwif->dma_base) { +// hwif->dmaproc = &pdcadma_dmaproc; +// hwif->autodma = 1; +// } +} + +void __init ide_dmacapable_pdcadma (ide_hwif_t *hwif, unsigned long dmabase) +{ +// ide_setup_dma(hwif, dmabase, 8); +} + diff -urN linux-2.4.19-p7-pristine/drivers/ide/piix.c linux-2.4.19-p7/drivers/ide/piix.c --- linux-2.4.19-p7-pristine/drivers/ide/piix.c Tue Apr 16 03:15:18 2002 +++ linux-2.4.19-p7/drivers/ide/piix.c Tue Apr 16 23:16:58 2002 @@ -77,7 +77,6 @@ static int piix_get_info(char *, char **, off_t, int); extern int (*piix_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int piix_get_info (char *buffer, char **addr, off_t offset, int count) @@ -91,8 +90,8 @@ switch(bmide_dev->device) { case PCI_DEVICE_ID_INTEL_82801BA_8: case PCI_DEVICE_ID_INTEL_82801BA_9: - case PCI_DEVICE_ID_INTEL_82801CA_10: - case PCI_DEVICE_ID_INTEL_82801CA_11: + case PCI_DEVICE_ID_INTEL_82801CA_10: + case PCI_DEVICE_ID_INTEL_82801CA_11: p += sprintf(p, "\n Intel PIIX4 Ultra 100 Chipset.\n"); break; case PCI_DEVICE_ID_INTEL_82372FB_1: @@ -196,8 +195,6 @@ byte piix_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); - #if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING) /* * @@ -269,12 +266,11 @@ master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); } - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data); if (is_slave) pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } #if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING) @@ -357,6 +353,52 @@ return err; } +static int piix_ultra100 (struct pci_dev *dev) +{ + switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801BA_8: + case PCI_DEVICE_ID_INTEL_82801BA_9: + case PCI_DEVICE_ID_INTEL_82801CA_10: + case PCI_DEVICE_ID_INTEL_82801CA_11: + return 1; + default: + break; + } + return 0; +} + +static int piix_ultra66 (struct pci_dev *dev) +{ + if (piix_ultra100(dev)) + return 1; + + switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801AA_1: + case PCI_DEVICE_ID_INTEL_82372FB_1: + return 1; + default: + break; + } + return 0; +} + +static int piix_ultra (struct pci_dev *dev) +{ + if (piix_ultra66(dev)) + return 1; + + switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82371AB: + case PCI_DEVICE_ID_INTEL_82443MX_1: + case PCI_DEVICE_ID_INTEL_82451NX: + case PCI_DEVICE_ID_INTEL_82801AB_1: + return 1; + default: + break; + } + return 0; +} + static int piix_config_drive_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -365,18 +407,9 @@ byte speed; byte udma_66 = eighty_ninty_three(drive); - int ultra100 = ((dev->device == PCI_DEVICE_ID_INTEL_82801BA_8) || - (dev->device == PCI_DEVICE_ID_INTEL_82801BA_9) || - (dev->device == PCI_DEVICE_ID_INTEL_82801CA_10) || - (dev->device == PCI_DEVICE_ID_INTEL_82801CA_11)) ? 1 : 0; - int ultra66 = ((ultra100) || - (dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) || - (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0; - int ultra = ((ultra66) || - (dev->device == PCI_DEVICE_ID_INTEL_82371AB) || - (dev->device == PCI_DEVICE_ID_INTEL_82443MX_1) || - (dev->device == PCI_DEVICE_ID_INTEL_82451NX) || - (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0; + int ultra100 = piix_ultra100(dev); + int ultra66 = piix_ultra66(dev); + int ultra = piix_ultra(dev); if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) { speed = XFER_UDMA_5; @@ -419,6 +452,9 @@ struct hd_driveid *id = drive->id; ide_dma_action_t dma_func = ide_dma_on; + config_chipset_for_pio(drive); + drive->init_speed = 0; + if (id && (id->capability & 1) && HWIF(drive)->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { @@ -478,6 +514,22 @@ unsigned int __init pci_init_piix (struct pci_dev *dev, const char *name) { + switch(dev->device) { + case PCI_DEVICE_ID_INTEL_82801AA_1: + case PCI_DEVICE_ID_INTEL_82801AB_1: + case PCI_DEVICE_ID_INTEL_82801BA_8: + case PCI_DEVICE_ID_INTEL_82801BA_9: + case PCI_DEVICE_ID_INTEL_82801CA_10: + case PCI_DEVICE_ID_INTEL_82801CA_11: + { + unsigned int extra = 0; + pci_read_config_dword(dev, 0x54, &extra); + pci_write_config_dword(dev, 0x54, extra|0x400); + } + default: + break; + } + #if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) if (!piix_proc) { piix_proc = 1; diff -urN linux-2.4.19-p7-pristine/drivers/ide/qd65xx.c linux-2.4.19-p7/drivers/ide/qd65xx.c --- linux-2.4.19-p7-pristine/drivers/ide/qd65xx.c Tue Apr 16 03:15:18 2002 +++ linux-2.4.19-p7/drivers/ide/qd65xx.c Tue Apr 16 23:16:58 2002 @@ -94,10 +94,9 @@ { unsigned long flags; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); outb(content,reg); - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); } byte __init qd_read_reg (byte reg) @@ -105,10 +104,9 @@ unsigned long flags; byte read; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); read = inb(reg); - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); return read; } @@ -313,13 +311,12 @@ byte readreg; unsigned long flags; - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + spin_lock_irqsave(&io_request_lock, flags); savereg = inb_p(port); outb_p(QD_TESTVAL,port); /* safe value */ readreg = inb_p(port); outb(savereg,port); - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); if (savereg == QD_TESTVAL) { printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n"); diff -urN linux-2.4.19-p7-pristine/drivers/ide/serverworks.c linux-2.4.19-p7/drivers/ide/serverworks.c --- linux-2.4.19-p7-pristine/drivers/ide/serverworks.c Tue Apr 16 03:15:18 2002 +++ linux-2.4.19-p7/drivers/ide/serverworks.c Fri Apr 19 14:01:05 2002 @@ -1,7 +1,5 @@ /* - * linux/drivers/ide/serverworks.c Version 0.3 26 Oct 2001 - * - * May be copied or modified under the terms of the GNU General Public License + * linux/drivers/ide/serverworks.c Version 0.6 05 April 2002 * * Copyright (C) 1998-2000 Michel Aubry * Copyright (C) 1998-2000 Andrzej Krzysztofowicz @@ -21,61 +19,7 @@ * *** The CSB5 does not provide ANY register *** * *** to detect 80-conductor cable presence. *** * - * - * here's the default lspci: - * - * 00:0f.1 IDE interface: ServerWorks: Unknown device 0211 (prog-if 8a [Master SecP PriP]) - * Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- - * Status: Cap- 66Mhz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- SERR- TAbort- SERR- #include -static struct pci_dev *bmide_dev; +#define SVWKS_MAX_DEVS 2 +static struct pci_dev *svwks_devs[SVWKS_MAX_DEVS]; +static int n_svwks_devs; + static byte svwks_revision = 0; static int svwks_get_info(char *, char **, off_t, int); extern int (*svwks_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static int svwks_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - u32 bibma = pci_resource_start(bmide_dev, 4); - u32 reg40, reg44; - u16 reg48, reg56; - u8 reg54, c0=0, c1=0; - - pci_read_config_dword(bmide_dev, 0x40, ®40); - pci_read_config_dword(bmide_dev, 0x44, ®44); - pci_read_config_word(bmide_dev, 0x48, ®48); - pci_read_config_byte(bmide_dev, 0x54, ®54); - pci_read_config_word(bmide_dev, 0x56, ®56); - - /* - * at that point bibma+0x2 et bibma+0xa are byte registers - * to investigate: - */ - c0 = inb_p((unsigned short)bibma + 0x02); - c1 = inb_p((unsigned short)bibma + 0x0a); + int i; - switch(bmide_dev->device) { - case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: - p += sprintf(p, "\n " - "ServerWorks CSB5 Chipset (rev %02x)\n", - svwks_revision); - break; - case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: - p += sprintf(p, "\n " - "ServerWorks OSB4 Chipset (rev %02x)\n", - svwks_revision); - break; - default: - p += sprintf(p, "\n " - "ServerWorks %04x Chipset (rev %02x)\n", - bmide_dev->device, svwks_revision); - break; - } + p += sprintf(p, "\n " + "ServerWorks OSB4/CSB5/CSB6\n"); + + for (i = 0; i < n_svwks_devs; i++) { + struct pci_dev *dev = svwks_devs[i]; + u32 bibma = pci_resource_start(dev, 4); + u32 reg40, reg44; + u16 reg48, reg56; + u8 reg54, c0=0, c1=0; + + pci_read_config_dword(dev, 0x40, ®40); + pci_read_config_dword(dev, 0x44, ®44); + pci_read_config_word(dev, 0x48, ®48); + pci_read_config_byte(dev, 0x54, ®54); + pci_read_config_word(dev, 0x56, ®56); + + /* + * at that point bibma+0x2 et bibma+0xa are byte registers + * to investigate: + */ + c0 = inb_p((unsigned short)bibma + 0x02); + c1 = inb_p((unsigned short)bibma + 0x0a); - p += sprintf(p, "------------------------------- General Status ---------------------------------\n"); - p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); - p += sprintf(p, " %sabled %sabled\n", - (c0&0x80) ? "dis" : " en", - (c1&0x80) ? "dis" : " en"); - p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", + switch(dev->device) { + case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: + p += sprintf(p, "\n " + "ServerWorks CSB6 Chipset (rev %02x)\n", + svwks_revision); + break; + case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: + p += sprintf(p, "\n " + "ServerWorks CSB5 Chipset (rev %02x)\n", + svwks_revision); + break; + case PCI_DEVICE_ID_SERVERWORKS_OSB4IDE: + p += sprintf(p, "\n " + "ServerWorks OSB4 Chipset (rev %02x)\n", + svwks_revision); + break; + default: + p += sprintf(p, "\n " + "ServerWorks %04x Chipset (rev %02x)\n", + dev->device, svwks_revision); + break; + } + + p += sprintf(p, "------------------------------- " + "General Status " + "---------------------------------\n"); + p += sprintf(p, "--------------- Primary Channel " + "---------------- Secondary Channel " + "-------------\n"); + p += sprintf(p, " %sabled %sabled\n", + (c0&0x80) ? "dis" : " en", + (c1&0x80) ? "dis" : " en"); + p += sprintf(p, "--------------- drive0 --------- drive1 " + "-------- drive0 ---------- drive1 ------\n"); + p += sprintf(p, "DMA enabled: %s %s %s %s\n", (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ", (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", + p += sprintf(p, "UDMA enabled: %s %s" + " %s %s\n", (reg54 & 0x01) ? "yes" : "no ", (reg54 & 0x02) ? "yes" : "no ", (reg54 & 0x04) ? "yes" : "no ", (reg54 & 0x08) ? "yes" : "no " ); - p += sprintf(p, "UDMA enabled: %s %s %s %s\n", + p += sprintf(p, "UDMA enabled: %s %s" + " %s %s\n", ((reg56&0x0005)==0x0005)?"5": ((reg56&0x0004)==0x0004)?"4": ((reg56&0x0003)==0x0003)?"3": @@ -187,7 +152,8 @@ ((reg56&0x2000)==0x2000)?"2": ((reg56&0x1000)==0x1000)?"1": ((reg56&0xF000))?"?":"0"); - p += sprintf(p, "DMA enabled: %s %s %s %s\n", + p += sprintf(p, "DMA enabled: %s %s" + " %s %s\n", ((reg44&0x00002000)==0x00002000)?"2": ((reg44&0x00002100)==0x00002100)?"1": ((reg44&0x00007700)==0x00007700)?"0": @@ -205,7 +171,8 @@ ((reg44&0x00770000)==0x00770000)?"0": ((reg44&0x00FF0000)==0x00FF0000)?"X":"?"); - p += sprintf(p, "PIO enabled: %s %s %s %s\n", + p += sprintf(p, "PIO enabled: %s %s" + " %s %s\n", ((reg40&0x00002000)==0x00002000)?"4": ((reg40&0x00002200)==0x00002200)?"3": ((reg40&0x00003400)==0x00003400)?"2": @@ -226,19 +193,80 @@ ((reg40&0x00340000)==0x00340000)?"2": ((reg40&0x00470000)==0x00470000)?"1": ((reg40&0x005D0000)==0x005D0000)?"0":"?"); + + } + p += sprintf(p, "\n"); + return p-buffer; /* => must be less than 4k! */ } #endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ #define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ -byte svwks_proc = 0; +#define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ -extern char *ide_xfer_verbose (byte xfer_rate); +byte svwks_proc = 0; static struct pci_dev *isa_dev; -static int svwks_tune_chipset (ide_drive_t *drive, byte speed) +static byte svwks_ratemask (ide_drive_t *drive) +{ + struct pci_dev *dev = HWIF(drive)->pci_dev; + byte mode = 0; + + if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { + u32 reg = 0; + mode &= ~0x01; + if (isa_dev) + pci_read_config_dword(isa_dev, 0x64, ®); + if ((reg & 0x00004000) == 0x00004000) + mode |= 0x01; + } else if (svwks_revision < SVWKS_CSB5_REVISION_NEW) { + mode |= 0x01; + } else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) { + u8 btr =0; + pci_read_config_byte(dev, 0x5A, &btr); + mode |= btr; + if (!eighty_ninty_three(drive)) + mode &= ~0x02; + } + if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) && + (!(PCI_FUNC(dev->devfn) & 1))) + mode = 0x02; + mode &= ~0xFC; + return (mode); +} + +static byte svwks_ratefilter (ide_drive_t *drive, byte speed) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + byte mode = svwks_ratemask(drive); + + switch(mode) { + case 0x03: break; + case 0x02: while (speed > XFER_UDMA_4) speed--; break; + case 0x01: while (speed > XFER_UDMA_2) speed--; break; + case 0x00: + default: while (speed > XFER_MW_DMA_2) speed--; break; + break; + } +#endif /* CONFIG_BLK_DEV_IDEDMA */ +// printk("%s: mode == %02x speed == %02x\n", drive->name, mode, speed); + return speed; +} + +static byte svwks_csb_check (struct pci_dev *dev) +{ + switch (dev->device) { + case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: + case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: + return 1; + default: + break; + } + return 0; +} +static int svwks_tune_chipset (ide_drive_t *drive, byte xferspeed) { byte udma_modes[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; byte dma_modes[] = { 0x77, 0x21, 0x20 }; @@ -247,7 +275,7 @@ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; byte unit = (drive->select.b.unit & 0x01); - byte csb5 = (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0; + byte csb5 = svwks_csb_check(dev); #ifdef CONFIG_BLK_DEV_IDEDMA unsigned long dma_base = hwif->dma_base; @@ -265,6 +293,7 @@ unsigned short csb5_pio = 0x00; byte pio = ide_get_best_pio_mode(drive, 255, 5, NULL); + byte speed = svwks_ratefilter(drive, xferspeed); switch (drive->dn) { case 0: drive_pci = 0x41; drive_pci2 = 0x45; break; @@ -414,32 +443,50 @@ static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; - struct pci_dev *dev = HWIF(drive)->pci_dev; - byte udma_66 = eighty_ninty_three(drive); - int ultra66 = (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) ? 1 : 0; - int ultra100 = (ultra66 && svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 1 : 0; + byte mode = svwks_ratemask(drive); byte speed; - if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) { - speed = XFER_UDMA_5; - } else if (id->dma_ultra & 0x0010) { - speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2; - } else if (id->dma_ultra & 0x0008) { - speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1; - } else if (id->dma_ultra & 0x0004) { - speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0002) { - speed = XFER_UDMA_1; - } else if (id->dma_ultra & 0x0001) { - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else { - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); + if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) + mode = 0; + + switch(mode) { +#if 0 + case 0x04: + if (id->dma_ultra & 0x0040) + { speed = XFER_UDMA_6; break; } +#endif + case 0x03: + if (id->dma_ultra & 0x0020) + { speed = XFER_UDMA_5; break; } + case 0x02: + if (id->dma_ultra & 0x0010) + { speed = XFER_UDMA_4; break; } + if (id->dma_ultra & 0x0008) + { speed = XFER_UDMA_3; break; } + case 0x01: + if (id->dma_ultra & 0x0004) + { speed = XFER_UDMA_2; break; } + if (id->dma_ultra & 0x0002) + { speed = XFER_UDMA_1; break; } + if (id->dma_ultra & 0x0001) + { speed = XFER_UDMA_0; break; } + if (id->dma_mword & 0x0004) + { speed = XFER_MW_DMA_2; break; } + if (id->dma_mword & 0x0002) + { speed = XFER_MW_DMA_1; break; } + if (id->dma_mword & 0x0001) + { speed = XFER_MW_DMA_0; break; } +#if 0 + if (id->dma_1word & 0x0004) + { speed = XFER_SW_DMA_2; break; } + if (id->dma_1word & 0x0002) + { speed = XFER_SW_DMA_1; break; } + if (id->dma_1word & 0x0001) + { speed = XFER_SW_DMA_0; break; } +#endif + default: + speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); + break; } (void) svwks_tune_chipset(drive, speed); @@ -456,6 +503,9 @@ struct hd_driveid *id = drive->id; ide_dma_action_t dma_func = ide_dma_on; + config_chipset_for_pio(drive); + drive->init_speed = 0; + if (id && (id->capability & 1) && HWIF(drive)->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { @@ -570,31 +620,79 @@ } } - /* setup CSB5 : South Bridge and IDE */ - else if (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) { + /* setup CSB5/CSB6 : South Bridge and IDE option RAID */ + else if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) || + (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE)) { + /* Third Channel Test */ + if (!(PCI_FUNC(dev->devfn) & 1)) { +#if 1 + struct pci_dev * findev = NULL; + unsigned int reg4c = 0; + findev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL); + if (findev) { + pci_read_config_dword(findev, 0x4C, ®4c); + reg4c &= ~0x000007FF; + reg4c |= 0x00000040; + reg4c |= 0x00000020; + pci_write_config_dword(findev, 0x4C, reg4c); + } +#endif + outb_p(0x06, 0x0c00); + dev->irq = inb_p(0x0c01); +#if 1 + /* WE need to figure out how to get the correct one */ + printk("%s: interrupt %d\n", name, dev->irq); + if (dev->irq != 0x0B) + dev->irq = 0x0B; +#endif + } else { + /* + * This is a device pin issue on CSB6. + * Since there will be a future raid mode, + * early versions of the chipset require the + * interrupt pin to be set, and it is a compatablity + * mode issue. + */ + dev->irq = 0; + } + pci_write_config_dword(dev, 0x40, 0x99999999); + pci_write_config_dword(dev, 0x44, 0xFFFFFFFF); /* setup the UDMA Control register * * 1. clear bit 6 to enable DMA * 2. enable DMA modes with bits 0-1 - * 00 : legacy - * 01 : udma2 - * 10 : udma2/udma4 - * 11 : udma2/udma4/udma5 + * 00 : legacy + * 01 : udma2 + * 10 : udma2/udma4 + * 11 : udma2/udma4/udma5 */ pci_read_config_byte(dev, 0x5A, &btr); btr &= ~0x40; - btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; + if (!(PCI_FUNC(dev->devfn) & 1)) + btr |= 0x2; + else + btr |= (svwks_revision >= SVWKS_CSB5_REVISION_NEW) ? 0x3 : 0x2; pci_write_config_byte(dev, 0x5A, btr); } + svwks_devs[n_svwks_devs++] = dev; + #if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) if (!svwks_proc) { svwks_proc = 1; - bmide_dev = dev; svwks_display_info = &svwks_get_info; } #endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */ - return 0; + + return (dev->irq) ? dev->irq : 0; +} + +static unsigned int __init ata66_svwks_svwks (ide_hwif_t *hwif) +{ +// struct pci_dev *dev = hwif->pci_dev; +// return 0; + return 1; } /* On Dell PowerEdge servers with a CSB5, the top two bits of the subsystem @@ -636,6 +734,10 @@ { struct pci_dev *dev = hwif->pci_dev; + /* Server Works */ + if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS) + return ata66_svwks_svwks (hwif); + /* Dell PowerEdge */ if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL) return ata66_svwks_dell (hwif); @@ -661,10 +763,8 @@ hwif->autodma = 0; #else /* CONFIG_BLK_DEV_IDEDMA */ if (hwif->dma_base) { -#ifdef CONFIG_IDEDMA_AUTO if (!noautodma) hwif->autodma = 1; -#endif hwif->dmaproc = &svwks_dmaproc; } else { hwif->autodma = 0; @@ -673,3 +773,43 @@ } #endif /* !CONFIG_BLK_DEV_IDEDMA */ } + +/* + * We allow the BM-DMA driver to only work on enabled interfaces. + */ +void __init ide_dmacapable_svwks (ide_hwif_t *hwif, unsigned long dmabase) +{ + struct pci_dev *dev = hwif->pci_dev; + if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) && + (!(PCI_FUNC(dev->devfn) & 1)) && (hwif->channel)) + return; +#if 0 + if (svwks_revision == (SVWKS_CSB5_REVISION_NEW + 1)) { + if (hwif->mate && hwif->mate->dma_base) { + dmabase = hwif->mate->dma_base - (hwif->channel ? 0 : 8); + } else { + dmabase = pci_resource_start(dev, 4); + if (!dmabase) { + printk("%s: dma_base is invalid (0x%04lx)\n", + hwif->name, dmabase); + dmabase = 0; + } + } + } +#endif + ide_setup_dma(hwif, dmabase, 8); +} + +extern void ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *d); + +void __init serverworks_csb6_fixup (struct pci_dev *dev, ide_pci_device_t *d) +{ + if (!(PCI_FUNC(dev->devfn) & 1)) { + d->bootable = NEVER_BOARD; + } + + printk("%s: IDE controller on PCI bus %02x dev %02x\n", + d->name, dev->bus->number, dev->devfn); + ide_setup_pci_device(dev, d); +} + diff -urN linux-2.4.19-p7-pristine/drivers/ide/sis5513.c linux-2.4.19-p7/drivers/ide/sis5513.c --- linux-2.4.19-p7-pristine/drivers/ide/sis5513.c Tue Apr 16 03:15:19 2002 +++ linux-2.4.19-p7/drivers/ide/sis5513.c Tue Apr 16 23:16:58 2002 @@ -406,7 +406,6 @@ byte sis_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); /* @@ -680,6 +679,7 @@ ide_dma_action_t dma_func = ide_dma_off_quietly; (void) config_chipset_for_pio(drive, 5); + drive->init_speed = 0; if (id && (id->capability & 1) && HWIF(drive)->autodma) { /* Consult the list of known "bad" drives */ diff -urN linux-2.4.19-p7-pristine/drivers/ide/sl82c105.c linux-2.4.19-p7/drivers/ide/sl82c105.c --- linux-2.4.19-p7-pristine/drivers/ide/sl82c105.c Fri Sep 7 10:45:30 2001 +++ linux-2.4.19-p7/drivers/ide/sl82c105.c Tue Apr 16 23:16:58 2002 @@ -26,8 +26,6 @@ #include "ide_modes.h" -extern char *ide_xfer_verbose (byte xfer_rate); - /* * Convert a PIO mode and cycle time to the required on/off * times for the interface. This has protection against run-away diff -urN linux-2.4.19-p7-pristine/drivers/ide/slc90e66.c linux-2.4.19-p7/drivers/ide/slc90e66.c --- linux-2.4.19-p7-pristine/drivers/ide/slc90e66.c Tue Apr 16 03:15:19 2002 +++ linux-2.4.19-p7/drivers/ide/slc90e66.c Tue Apr 16 23:16:58 2002 @@ -60,7 +60,6 @@ static int slc90e66_get_info(char *, char **, off_t, int); extern int (*slc90e66_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); static struct pci_dev *bmide_dev; static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count) @@ -150,8 +149,6 @@ byte slc90e66_proc = 0; -extern char *ide_xfer_verbose (byte xfer_rate); - #ifdef CONFIG_BLK_DEV_IDEDMA /* * @@ -212,8 +209,8 @@ master_data = master_data | 0x0070; pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data); slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0); - slave_data = slave_data | ((timings[pio][0] << 2) | (timings[pio][1] - << (HWIF(drive)->index ? 4 : 0))); + slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) + << (HWIF(drive)->index ? 4 : 0)); } else { master_data = master_data & 0xccf8; if (pio > 1) @@ -222,12 +219,11 @@ master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); } - save_flags(flags); - cli(); + spin_lock_irqsave(&io_request_lock, flags); pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data); if (is_slave) pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data); - restore_flags(flags); + spin_unlock_irqrestore(&io_request_lock, flags); } #ifdef CONFIG_BLK_DEV_IDEDMA @@ -298,13 +294,13 @@ byte speed = 0; byte udma_66 = eighty_ninty_three(drive); -#if 1 /* allow PIO modes */ if (!HWIF(drive)->autodma) { speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); (void) slc90e66_tune_chipset(drive, speed); return ((int) ide_dma_off_quietly); } -#endif + drive->init_speed = 0; + if ((id->dma_ultra & 0x0010) && (ultra)) { speed = (udma_66) ? XFER_UDMA_4 : XFER_UDMA_2; } else if ((id->dma_ultra & 0x0008) && (ultra)) { diff -urN linux-2.4.19-p7-pristine/drivers/ide/trm290.c linux-2.4.19-p7/drivers/ide/trm290.c --- linux-2.4.19-p7-pristine/drivers/ide/trm290.c Tue Jun 20 07:52:36 2000 +++ linux-2.4.19-p7/drivers/ide/trm290.c Tue Apr 16 23:16:58 2002 @@ -148,8 +148,7 @@ /* select PIO or DMA */ reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82); - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); if (reg != hwif->select_data) { hwif->select_data = reg; @@ -164,7 +163,7 @@ outw(reg, hwif->config_data+3); } - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); } static void trm290_selectproc (ide_drive_t *drive) @@ -194,9 +193,29 @@ outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */ if (drive->media != ide_disk) return 0; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); - OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - return 0; +/* + * FIX ME to use only ACB ide_task_t args Struct + */ +#if 0 + { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } +#else + if ((HWGROUP(drive)->rq->cmd == IDE_DRIVE_TASKFILE) && + (drive->addressing)) { + ide_task_t *args = HWGROUP(drive)->rq->special; + OUT_BYTE(args->tfRegister[IDE_COMMAND_OFFSET], IDE_COMMAND_REG); + } else if (drive->addressing == 1) { + OUT_BYTE(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); + } else { + OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); + } +#endif + return HWIF(drive)->dmaproc(ide_dma_begin, drive); case ide_dma_begin: return 0; case ide_dma_end: @@ -234,8 +253,7 @@ printk("TRM290: using default config base at 0x%04lx\n", hwif->config_data); } - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); /* put config reg into first byte of hwif->select_data */ outb(0x51|(hwif->channel<<3), hwif->config_data+1); hwif->select_data = 0x21; /* select PIO as default */ @@ -243,7 +261,7 @@ reg = inb(hwif->config_data+3); /* get IRQ info */ reg = (reg & 0x10) | 0x03; /* mask IRQs for both ports */ outb(reg, hwif->config_data+3); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); if ((reg & 0x10)) hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */ diff -urN linux-2.4.19-p7-pristine/drivers/ide/umc8672.c linux-2.4.19-p7/drivers/ide/umc8672.c --- linux-2.4.19-p7-pristine/drivers/ide/umc8672.c Thu Apr 13 22:54:26 2000 +++ linux-2.4.19-p7/drivers/ide/umc8672.c Tue Apr 16 23:16:58 2002 @@ -92,13 +92,11 @@ out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); tmp = 0; - for (i = 3; i >= 0; i--) - { + for (i = 3; i >= 0; i--) { tmp = (tmp << 2) | speedtab[1][speeds[i]]; } out_umc (0xdc,tmp); - for (i = 0;i < 4; i++) - { + for (i = 0;i < 4; i++) { out_umc (0xd0+i,speedtab[2][speeds[i]]); out_umc (0xd8+i,speedtab[2][speeds[i]]); } @@ -114,40 +112,38 @@ ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup; pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]); - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ + printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", + drive->name, pio, pio_to_umc[pio]); + spin_lock_irqsave(&io_request_lock, flags); if (hwgroup && hwgroup->handler != NULL) { printk("umc8672: other interface is busy: exiting tune_umc()\n"); } else { current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; umc_set_speeds (current_speeds); } - restore_flags(flags); /* all CPUs */ + spin_unlock_irqrestore(&io_request_lock, flags); } void __init init_umc8672 (void) /* called from ide.c */ { unsigned long flags; - __save_flags(flags); /* local CPU only */ - __cli(); /* local CPU only */ + local_irq_save(flags); if (check_region(0x108, 2)) { - __restore_flags(flags); + local_irq_restore(flags); printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n"); return; } outb_p (0x5A,0x108); /* enable umc */ - if (in_umc (0xd5) != 0xa0) - { - __restore_flags(flags); /* local CPU only */ + if (in_umc (0xd5) != 0xa0) { + local_irq_restore(flags); printk ("umc8672: not found\n"); return; } outb_p (0xa5,0x108); /* disable umc */ umc_set_speeds (current_speeds); - __restore_flags(flags); /* local CPU only */ + local_irq_restore(flags); request_region(0x108, 2, "umc8672"); ide_hwifs[0].chipset = ide_umc8672; diff -urN linux-2.4.19-p7-pristine/drivers/pci/pci.ids linux-2.4.19-p7/drivers/pci/pci.ids --- linux-2.4.19-p7-pristine/drivers/pci/pci.ids Tue Apr 16 03:15:41 2002 +++ linux-2.4.19-p7/drivers/pci/pci.ids Tue Apr 16 02:30:46 2002 @@ -2945,11 +2945,17 @@ 0009 CNB20LE Host Bridge 0010 CIOB30 0011 CMIC-HE + 0017 GCNB-LE Host Bridge 0200 OSB4 South Bridge 0201 CSB5 South Bridge + 0203 CSB6 South Bridge 0211 OSB4 IDE Controller 0212 CSB5 IDE Controller - 0220 OSB4/CSB5 USB Controller + 0213 CSB6 RAID/IDE Controller + 0220 OSB4/CSB5 OHCI USB Controller + 0221 CSB6 OHCI USB Controller + 0225 GCLE Host Bridge + 0227 GCLE-2 Host Bridge 1167 Mutoh Industries Inc 1168 Thine Electronics Inc 1169 Centre for Development of Advanced Computing diff -urN linux-2.4.19-p7-pristine/drivers/scsi/ide-scsi.c linux-2.4.19-p7/drivers/scsi/ide-scsi.c --- linux-2.4.19-p7-pristine/drivers/scsi/ide-scsi.c Tue Apr 16 03:15:50 2002 +++ linux-2.4.19-p7/drivers/scsi/ide-scsi.c Mon Apr 22 20:28:34 2002 @@ -53,65 +53,66 @@ #include "ide-scsi.h" #include -#define IDESCSI_DEBUG_LOG 0 +#define IDESCSI_DEBUG_LOG 0 typedef struct idescsi_pc_s { - u8 c[12]; /* Actual packet bytes */ - int request_transfer; /* Bytes to transfer */ - int actually_transferred; /* Bytes actually transferred */ - int buffer_size; /* Size of our data buffer */ - struct request *rq; /* The corresponding request */ - byte *buffer; /* Data buffer */ - byte *current_position; /* Pointer into the above buffer */ - struct scatterlist *sg; /* Scatter gather table */ - int b_count; /* Bytes transferred from current entry */ - Scsi_Cmnd *scsi_cmd; /* SCSI command */ - void (*done)(Scsi_Cmnd *); /* Scsi completion routine */ - unsigned long flags; /* Status/Action flags */ - unsigned long timeout; /* Command timeout */ + u8 c[12]; /* Actual packet bytes */ + int request_transfer; /* Bytes to transfer */ + int actually_transferred; /* Bytes actually transferred */ + int buffer_size; /* Size of our data buffer */ + struct request *rq; /* The corresponding request */ + byte *buffer; /* Data buffer */ + byte *current_position; /* Pointer into the above buffer */ + struct scatterlist *sg; /* Scatter gather table */ + int b_count; /* Bytes transferred from current entry */ + Scsi_Cmnd *scsi_cmd; /* SCSI command */ + void (*done)(Scsi_Cmnd *); /* Scsi completion routine */ + unsigned long flags; /* Status/Action flags */ + unsigned long timeout; /* Command timeout */ } idescsi_pc_t; /* * Packet command status bits. */ -#define PC_DMA_IN_PROGRESS 0 /* 1 while DMA in progress */ -#define PC_WRITING 1 /* Data direction */ -#define PC_TRANSFORM 2 /* transform SCSI commands */ +#define PC_DMA_IN_PROGRESS 0 /* 1 while DMA in progress */ +#define PC_WRITING 1 /* Data direction */ +#define PC_TRANSFORM 2 /* transform SCSI commands */ /* * SCSI command transformation layer */ -#define IDESCSI_TRANSFORM 0 /* Enable/Disable transformation */ -#define IDESCSI_SG_TRANSFORM 1 /* /dev/sg transformation */ +#define IDESCSI_TRANSFORM 0 /* Enable/Disable transformation */ +#define IDESCSI_SG_TRANSFORM 1 /* /dev/sg transformation */ /* * Log flags */ -#define IDESCSI_LOG_CMD 0 /* Log SCSI commands */ +#define IDESCSI_LOG_CMD 0 /* Log SCSI commands */ typedef struct { ide_drive_t *drive; - idescsi_pc_t *pc; /* Current packet command */ - unsigned long flags; /* Status/Action flags */ - unsigned long transform; /* SCSI cmd translation layer */ - unsigned long log; /* log flags */ + idescsi_pc_t *pc; /* Current packet command */ + unsigned long flags; /* Status/Action flags */ + unsigned long transform; /* SCSI cmd translation layer */ + unsigned long log; /* log flags */ + devfs_handle_t de; /* pointer to IDE device */ } idescsi_scsi_t; /* * Per ATAPI device status bits. */ -#define IDESCSI_DRQ_INTERRUPT 0 /* DRQ interrupt device */ +#define IDESCSI_DRQ_INTERRUPT 0 /* DRQ interrupt device */ /* * ide-scsi requests. */ -#define IDESCSI_PC_RQ 90 +#define IDESCSI_PC_RQ 90 /* * Bits of the interrupt reason register. */ -#define IDESCSI_IREASON_COD 0x1 /* Information transferred is command */ -#define IDESCSI_IREASON_IO 0x2 /* The device requests us to read */ +#define IDESCSI_IREASON_COD 0x1 /* Information transferred is command */ +#define IDESCSI_IREASON_IO 0x2 /* The device requests us to read */ static void idescsi_discard_data (ide_drive_t *drive, unsigned int bcount) { @@ -181,8 +182,12 @@ return; if (drive->media == ide_cdrom || drive->media == ide_optical) { if (c[0] == READ_6 || c[0] == WRITE_6) { - c[8] = c[4]; c[5] = c[3]; c[4] = c[2]; - c[3] = c[1] & 0x1f; c[2] = 0; c[1] &= 0xe0; + c[8] = c[4]; + c[5] = c[3]; + c[4] = c[2]; + c[3] = c[1] & 0x1f; + c[2] = 0; + c[1] &= 0xe0; c[0] += (READ_10 - READ_6); } if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) { @@ -192,15 +197,22 @@ return; memset(atapi_buf, 0, pc->buffer_size + 4); memset (c, 0, 12); - c[0] = sc[0] | 0x40; c[1] = sc[1]; c[2] = sc[2]; - c[8] = sc[4] + 4; c[9] = sc[5]; + c[0] = sc[0] | 0x40; + c[1] = sc[1]; + c[2] = sc[2]; + c[8] = sc[4] + 4; + c[9] = sc[5]; if (sc[4] + 4 > 255) c[7] = sc[4] + 4 - 255; if (c[0] == MODE_SELECT_10) { - atapi_buf[1] = scsi_buf[0]; /* Mode data length */ - atapi_buf[2] = scsi_buf[1]; /* Medium type */ - atapi_buf[3] = scsi_buf[2]; /* Device specific parameter */ - atapi_buf[7] = scsi_buf[3]; /* Block descriptor length */ + /* Mode data length */ + atapi_buf[1] = scsi_buf[0]; + /* Medium type */ + atapi_buf[2] = scsi_buf[1]; + /* Device specific parameter */ + atapi_buf[3] = scsi_buf[2]; + /* Block descriptor length */ + atapi_buf[7] = scsi_buf[3]; memcpy(atapi_buf + 8, scsi_buf + 4, pc->buffer_size - 4); } pc->buffer = atapi_buf; @@ -220,15 +232,21 @@ return; if (drive->media == ide_cdrom || drive->media == ide_optical) { if (pc->c[0] == MODE_SENSE_10 && sc[0] == MODE_SENSE) { - scsi_buf[0] = atapi_buf[1]; /* Mode data length */ - scsi_buf[1] = atapi_buf[2]; /* Medium type */ - scsi_buf[2] = atapi_buf[3]; /* Device specific parameter */ - scsi_buf[3] = atapi_buf[7]; /* Block descriptor length */ + /* Mode data length */ + scsi_buf[0] = atapi_buf[1]; + /* Medium type */ + scsi_buf[1] = atapi_buf[2]; + /* Device specific parameter */ + scsi_buf[2] = atapi_buf[3]; + /* Block descriptor length */ + scsi_buf[3] = atapi_buf[7]; memcpy(scsi_buf + 4, atapi_buf + 8, pc->request_transfer - 8); } if (pc->c[0] == INQUIRY) { - scsi_buf[2] |= 2; /* ansi_revision */ - scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2; /* response data format */ + /* ansi_revision */ + scsi_buf[2] |= 2; + /* response data format */ + scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2; } } if (atapi_buf && atapi_buf != scsi_buf) @@ -256,34 +274,65 @@ printk("]\n"); } -static void idescsi_end_request (byte uptodate, ide_hwgroup_t *hwgroup) +static int idescsi_do_end_request (ide_drive_t *drive, int uptodate) +{ + struct request *rq; + unsigned long flags; + int ret = 1; + + spin_lock_irqsave(&io_request_lock, flags); + rq = HWGROUP(drive)->rq; + + /* + * decide whether to reenable DMA -- 3 is a random magic for now, + * if we DMA timeout more than 3 times, just stay in PIO + */ + if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { + drive->state = 0; + HWGROUP(drive)->hwif->dmaproc(ide_dma_on, drive); + } + + if (!end_that_request_first(rq, uptodate, drive->name)) { + add_blkdev_randomness(MAJOR(rq->rq_dev)); + blkdev_dequeue_request(rq); + HWGROUP(drive)->rq = NULL; + end_that_request_last(rq); + ret = 0; + } + spin_unlock_irqrestore(&io_request_lock, flags); + return ret; +} + +static int idescsi_end_request (ide_drive_t *drive, int uptodate) { - ide_drive_t *drive = hwgroup->drive; idescsi_scsi_t *scsi = drive->driver_data; - struct request *rq = hwgroup->rq; + struct request *rq = HWGROUP(drive)->rq; idescsi_pc_t *pc = (idescsi_pc_t *) rq->buffer; int log = test_bit(IDESCSI_LOG_CMD, &scsi->log); u8 *scsi_buf; unsigned long flags; if (rq->cmd != IDESCSI_PC_RQ) { - ide_end_request (uptodate, hwgroup); - return; + idescsi_do_end_request(drive, uptodate); + return 0; } ide_end_drive_cmd (drive, 0, 0); if (rq->errors >= ERROR_MAX) { pc->scsi_cmd->result = DID_ERROR << 16; if (log) - printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number); + printk ("ide-scsi: %s: I/O error for %lu\n", + drive->name, pc->scsi_cmd->serial_number); } else if (rq->errors) { pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16); if (log) - printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number); + printk ("ide-scsi: %s: check condition for %lu\n", + drive->name, pc->scsi_cmd->serial_number); } else { pc->scsi_cmd->result = DID_OK << 16; idescsi_transform_pc2 (drive, pc); if (log) { - printk ("ide-scsi: %s: suc %lu", drive->name, pc->scsi_cmd->serial_number); + printk ("ide-scsi: %s: suc %lu", drive->name, + pc->scsi_cmd->serial_number); if (!test_bit(PC_WRITING, &pc->flags) && pc->actually_transferred && pc->actually_transferred <= 1024 && pc->buffer) { printk(", rst = "); scsi_buf = pc->scsi_cmd->request_buffer; @@ -297,6 +346,7 @@ idescsi_free_bh (rq->bh); kfree(pc); kfree(rq); scsi->pc = NULL; + return 0; } static inline unsigned long get_timeout(idescsi_pc_t *pc) @@ -328,15 +378,15 @@ (void) (HWIF(drive)->dmaproc(ide_dma_end, drive)); } - status = GET_STAT(); /* Clear the interrupt */ + status = GET_STAT(); /* Clear the interrupt */ if ((status & DRQ_STAT) == 0) { /* No more interrupts */ if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred); - ide__sti(); + local_irq_enable(); if (status & ERR_STAT) rq->errors++; - idescsi_end_request (1, HWGROUP(drive)); + idescsi_end_request(drive, 1); return ide_stopped; } bcount = IN_BYTE (IDE_BCOUNTH_REG) << 8 | IN_BYTE (IDE_BCOUNTL_REG); @@ -344,7 +394,7 @@ if (ireason & IDESCSI_IREASON_COD) { printk (KERN_ERR "ide-scsi: CoD != 0 in idescsi_pc_intr\n"); - return ide_do_reset (drive); + return ide_do_reset(drive); } if (ireason & IDESCSI_IREASON_IO) { temp = pc->actually_transferred + bcount; @@ -362,7 +412,9 @@ } pc->actually_transferred += temp; pc->current_position += temp; - idescsi_discard_data (drive,bcount - temp); + idescsi_discard_data(drive,bcount - temp); + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); return ide_started; } @@ -374,24 +426,26 @@ if (ireason & IDESCSI_IREASON_IO) { clear_bit(PC_WRITING, &pc->flags); if (pc->sg) - idescsi_input_buffers (drive, pc, bcount); + idescsi_input_buffers(drive, pc, bcount); else - atapi_input_bytes (drive,pc->current_position,bcount); + atapi_input_bytes(drive,pc->current_position,bcount); } else { set_bit(PC_WRITING, &pc->flags); if (pc->sg) - idescsi_output_buffers (drive, pc, bcount); + idescsi_output_buffers(drive, pc, bcount); else - atapi_output_bytes (drive,pc->current_position,bcount); + atapi_output_bytes(drive,pc->current_position,bcount); } - pc->actually_transferred+=bcount; /* Update the current position */ + pc->actually_transferred+=bcount; /* Update the current position */ pc->current_position+=bcount; + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); /* And set the interrupt handler again */ return ide_started; } -static ide_startstop_t idescsi_transfer_pc (ide_drive_t *drive) +static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) { idescsi_scsi_t *scsi = drive->driver_data; idescsi_pc_t *pc = scsi->pc; @@ -399,16 +453,19 @@ ide_startstop_t startstop; if (ide_wait_stat (&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) { - printk (KERN_ERR "ide-scsi: Strange, packet command initiated yet DRQ isn't asserted\n"); + printk (KERN_ERR "ide-scsi: Strange, packet command " \ + "initiated yet DRQ isn't asserted\n"); return startstop; } ireason = IN_BYTE (IDE_IREASON_REG); if ((ireason & (IDESCSI_IREASON_IO | IDESCSI_IREASON_COD)) != IDESCSI_IREASON_COD) { printk (KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while issuing a packet command\n"); - return ide_do_reset (drive); + return ide_do_reset(drive); } + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); /* Set the interrupt routine */ - atapi_output_bytes (drive, scsi->pc->c, 12); /* Send the actual packet */ + atapi_output_bytes(drive, scsi->pc->c, 12); /* Send the actual packet */ return ide_started; } @@ -422,10 +479,13 @@ struct request *rq = pc->rq; int dma_ok = 0; - scsi->pc=pc; /* Set the current packet command */ - pc->actually_transferred=0; /* We haven't transferred any data yet */ + /* Set the current packet command */ + scsi->pc=pc; + /* We haven't transferred any data yet */ + pc->actually_transferred=0; pc->current_position=pc->buffer; - bcount = IDE_MIN (pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */ + /* Request to transfer the entire buffer at once */ + bcount = IDE_MIN (pc->request_transfer, 63 * 1024); if (drive->using_dma && rq->bh) dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive); @@ -442,6 +502,8 @@ (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); } if (test_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { + if (HWGROUP(drive)->handler != NULL) /* paranoia check */ + BUG(); ide_set_handler (drive, &idescsi_transfer_pc, get_timeout(pc), NULL); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ return ide_started; @@ -465,7 +527,7 @@ return idescsi_issue_pc (drive, (idescsi_pc_t *) rq->buffer); } printk (KERN_ERR "ide-scsi: %s: unsupported command in request queue (%x)\n", drive->name, rq->cmd); - idescsi_end_request (0,HWGROUP (drive)); + idescsi_end_request(drive, 0); return ide_stopped; } @@ -502,6 +564,8 @@ */ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi, int id) { + int minor = (drive->select.b.unit) << PARTN_BITS; + DRIVER(drive)->busy++; idescsi_drives[id] = drive; drive->driver_data = scsi; @@ -516,6 +580,10 @@ set_bit(IDESCSI_LOG_CMD, &scsi->log); #endif /* IDESCSI_DEBUG_LOG */ idescsi_add_settings(drive); + scsi->de = devfs_register(drive->de, "generic", DEVFS_FL_DEFAULT, + HWIF(drive)->major, minor, + S_IFBLK | S_IRUSR | S_IWUSR, + ide_fops, NULL); } static int idescsi_cleanup (ide_drive_t *drive) @@ -524,11 +592,14 @@ if (ide_unregister_subdriver (drive)) return 1; + if (scsi->de) + devfs_unregister(scsi->de); drive->driver_data = NULL; kfree (scsi); return 0; } +int idescsi_init (void); int idescsi_reinit(ide_drive_t *drive); /* @@ -539,13 +610,21 @@ version: IDESCSI_VERSION, media: ide_scsi, busy: 0, +#ifdef CONFIG_IDEDMA_ONLYDISK + supports_dma: 0, +#else supports_dma: 1, +#endif supports_dsc_overlap: 0, cleanup: idescsi_cleanup, standby: NULL, + suspend: NULL, + resume: NULL, flushcache: NULL, do_request: idescsi_do_request, end_request: idescsi_end_request, + sense: NULL, + error: NULL, ioctl: NULL, open: idescsi_open, release: idescsi_ide_release, @@ -555,12 +634,12 @@ capacity: NULL, special: NULL, proc: NULL, + init: idescsi_init, reinit: idescsi_reinit, ata_prebuilder: NULL, atapi_prebuilder: NULL, }; -int idescsi_init (void); static ide_module_t idescsi_module = { IDE_DRIVER_MODULE, idescsi_init, diff -urN linux-2.4.19-p7-pristine/include/asm-alpha/ide.h linux-2.4.19-p7/include/asm-alpha/ide.h --- linux-2.4.19-p7-pristine/include/asm-alpha/ide.h Tue Apr 16 03:16:22 2002 +++ linux-2.4.19-p7/include/asm-alpha/ide.h Tue Apr 16 23:16:58 2002 @@ -19,8 +19,6 @@ #define MAX_HWIFS 4 #endif -#define ide__sti() __sti() - static __inline__ int ide_default_irq(ide_ioreg_t base) { switch (base) { diff -urN linux-2.4.19-p7-pristine/include/asm-alpha/system.h linux-2.4.19-p7/include/asm-alpha/system.h --- linux-2.4.19-p7-pristine/include/asm-alpha/system.h Thu Oct 4 18:47:08 2001 +++ linux-2.4.19-p7/include/asm-alpha/system.h Tue Apr 16 23:16:59 2002 @@ -309,9 +309,11 @@ #define __sti() do { barrier(); setipl(IPL_MIN); } while(0) #define __save_flags(flags) ((flags) = rdps()) #define __save_and_cli(flags) do { (flags) = swpipl(IPL_MAX); barrier(); } while(0) +#define __save_and_sti(flags) do { (flags) = setipl(IPL_MIN); barrier(); } while(0) #define __restore_flags(flags) do { barrier(); setipl(flags); barrier(); } while(0) #define local_irq_save(flags) __save_and_cli(flags) +#define local_irq_set(flags) __save_and_sti(flags) #define local_irq_restore(flags) __restore_flags(flags) #define local_irq_disable() __cli() #define local_irq_enable() __sti() @@ -320,8 +322,6 @@ extern int global_irq_holder; -#define save_and_cli(flags) (save_flags(flags), cli()) - extern void __global_cli(void); extern void __global_sti(void); extern unsigned long __global_save_flags(void); @@ -331,6 +331,8 @@ #define sti() __global_sti() #define save_flags(flags) ((flags) = __global_save_flags()) #define restore_flags(flags) __global_restore_flags(flags) +#define save_and_cli(flags) (save_flags(flags), cli()) +#define save_and_sti(flags) (save_flags(flags), sti()) #else /* CONFIG_SMP */ @@ -338,6 +340,7 @@ #define sti() __sti() #define save_flags(flags) __save_flags(flags) #define save_and_cli(flags) __save_and_cli(flags) +#define save_and_sti(flags) __save_and_sti(flags) #define restore_flags(flags) __restore_flags(flags) #endif /* CONFIG_SMP */ diff -urN linux-2.4.19-p7-pristine/include/asm-arm/ide.h linux-2.4.19-p7/include/asm-arm/ide.h --- linux-2.4.19-p7-pristine/include/asm-arm/ide.h Tue Apr 16 03:16:26 2002 +++ linux-2.4.19-p7/include/asm-arm/ide.h Tue Apr 16 23:16:59 2002 @@ -17,8 +17,6 @@ #define MAX_HWIFS 4 #endif -#define ide__sti() __sti() - #include typedef union { diff -urN linux-2.4.19-p7-pristine/include/asm-arm/proc-armo/system.h linux-2.4.19-p7/include/asm-arm/proc-armo/system.h --- linux-2.4.19-p7-pristine/include/asm-arm/proc-armo/system.h Sun Aug 12 11:14:00 2001 +++ linux-2.4.19-p7/include/asm-arm/proc-armo/system.h Tue Apr 16 23:16:59 2002 @@ -127,4 +127,6 @@ : "memory"); \ } while (0) +#define __save_and_sti(x) ({__save_flags(x);__sti();}) + #endif diff -urN linux-2.4.19-p7-pristine/include/asm-arm/proc-armv/system.h linux-2.4.19-p7/include/asm-arm/proc-armv/system.h --- linux-2.4.19-p7-pristine/include/asm-arm/proc-armv/system.h Sun Aug 12 11:14:00 2001 +++ linux-2.4.19-p7/include/asm-arm/proc-armv/system.h Tue Apr 16 23:16:59 2002 @@ -141,6 +141,8 @@ : "r" (x) \ : "memory") +#define __save_and_sti(x) ({__save_flags(x);__sti();}) + #if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110) /* * On the StrongARM, "swp" is terminally broken since it bypasses the diff -urN linux-2.4.19-p7-pristine/include/asm-arm/system.h linux-2.4.19-p7/include/asm-arm/system.h --- linux-2.4.19-p7-pristine/include/asm-arm/system.h Mon Nov 27 17:07:59 2000 +++ linux-2.4.19-p7/include/asm-arm/system.h Tue Apr 16 23:16:59 2002 @@ -58,6 +58,7 @@ /* For spinlocks etc */ #define local_irq_save(x) __save_flags_cli(x) +#define local_irq_set(x) __save_and_sti(x) #define local_irq_restore(x) __restore_flags(x) #define local_irq_disable() __cli() #define local_irq_enable() __sti() @@ -82,6 +83,8 @@ #define save_flags(x) __save_flags(x) #define restore_flags(x) __restore_flags(x) #define save_flags_cli(x) __save_flags_cli(x) +#define save_and_cli(x) __save_flags_cli(x) +#define save_and_sti(x) __save_flags_sti(x) #endif /* CONFIG_SMP */ diff -urN linux-2.4.19-p7-pristine/include/asm-cris/ide.h linux-2.4.19-p7/include/asm-cris/ide.h --- linux-2.4.19-p7-pristine/include/asm-cris/ide.h Tue Apr 16 03:16:27 2002 +++ linux-2.4.19-p7/include/asm-cris/ide.h Tue Apr 16 23:16:59 2002 @@ -22,8 +22,6 @@ #define MAX_HWIFS 4 -#define ide__sti() __sti() - static __inline__ int ide_default_irq(ide_ioreg_t base) { /* all IDE busses share the same IRQ, number 4. diff -urN linux-2.4.19-p7-pristine/include/asm-cris/system.h linux-2.4.19-p7/include/asm-cris/system.h --- linux-2.4.19-p7-pristine/include/asm-cris/system.h Fri Nov 9 14:11:15 2001 +++ linux-2.4.19-p7/include/asm-cris/system.h Tue Apr 16 23:16:59 2002 @@ -69,6 +69,7 @@ /* For spinlocks etc */ #define local_irq_save(x) __asm__ __volatile__ ("move $ccr,%0\n\tdi" : "=rm" (x) : : "memory"); +#define local_irq_set(x) __asm__ __volatile__ ("move $ccr,%0\n\tei" : "=rm" (x) : : "memory"); #define local_irq_restore(x) restore_flags(x) #define local_irq_disable() cli() @@ -80,7 +81,8 @@ #define sti() __sti() #define save_flags(x) __save_flags(x) #define restore_flags(x) __restore_flags(x) -#define save_and_cli(x) do { __save_flags(x); cli(); } while(0) +#define save_and_cli(x) do { save_flags(x); cli(); } while(0) +#define save_and_sti(x) do { save_flags(x); sti(); } while(0) static inline unsigned long __xchg(unsigned long x, void * ptr, int size) { diff -urN linux-2.4.19-p7-pristine/include/asm-i386/ide.h linux-2.4.19-p7/include/asm-i386/ide.h --- linux-2.4.19-p7-pristine/include/asm-i386/ide.h Tue Apr 16 03:16:27 2002 +++ linux-2.4.19-p7/include/asm-i386/ide.h Tue Apr 16 23:16:59 2002 @@ -23,8 +23,6 @@ # endif #endif -#define ide__sti() __sti() - static __inline__ int ide_default_irq(ide_ioreg_t base) { switch (base) { diff -urN linux-2.4.19-p7-pristine/include/asm-i386/system.h linux-2.4.19-p7/include/asm-i386/system.h --- linux-2.4.19-p7-pristine/include/asm-i386/system.h Thu Nov 22 11:46:18 2001 +++ linux-2.4.19-p7/include/asm-i386/system.h Tue Apr 16 23:16:59 2002 @@ -317,8 +317,18 @@ /* used in the idle loop; sti takes one instruction cycle to complete */ #define safe_halt() __asm__ __volatile__("sti; hlt": : :"memory") +#define __save_and_cli(x) do { __save_flags(x); __cli(); } while(0); +#define __save_and_sti(x) do { __save_flags(x); __sti(); } while(0); + /* For spinlocks etc */ +#if 0 #define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory") +#define local_irq_set(x) __asm__ __volatile__("pushfl ; popl %0 ; sti":"=g" (x): /* no input */ :"memory") +#else +#define local_irq_save(x) __save_and_cli(x) +#define local_irq_set(x) __save_and_sti(x) +#endif + #define local_irq_restore(x) __restore_flags(x) #define local_irq_disable() __cli() #define local_irq_enable() __sti() @@ -333,6 +343,8 @@ #define sti() __global_sti() #define save_flags(x) ((x)=__global_save_flags()) #define restore_flags(x) __global_restore_flags(x) +#define save_and_cli(x) do { save_flags(x); cli(); } while(0); +#define save_and_sti(x) do { save_flags(x); sti(); } while(0); #else @@ -340,6 +352,8 @@ #define sti() __sti() #define save_flags(x) __save_flags(x) #define restore_flags(x) __restore_flags(x) +#define save_and_cli(x) __save_and_cli(x) +#define save_and_sti(x) __save_and_sti(x) #endif diff -urN linux-2.4.19-p7-pristine/include/asm-ia64/ide.h linux-2.4.19-p7/include/asm-ia64/ide.h --- linux-2.4.19-p7-pristine/include/asm-ia64/ide.h Tue Apr 16 03:16:28 2002 +++ linux-2.4.19-p7/include/asm-ia64/ide.h Tue Apr 16 23:16:59 2002 @@ -25,8 +25,6 @@ # endif #endif -#define ide__sti() __sti() - static __inline__ int ide_default_irq (ide_ioreg_t base) { diff -urN linux-2.4.19-p7-pristine/include/asm-ia64/system.h linux-2.4.19-p7/include/asm-ia64/system.h --- linux-2.4.19-p7-pristine/include/asm-ia64/system.h Tue Apr 16 03:16:40 2002 +++ linux-2.4.19-p7/include/asm-ia64/system.h Tue Apr 16 23:16:59 2002 @@ -165,6 +165,15 @@ :: "r" (x) : "memory") #endif /* !CONFIG_IA64_DEBUG_IRQ */ +#error andre hedrick screwed this up please help unscrew in order to clean up +/* + * __save_and_sti(x) == __save_flags(x); ide__sti(); + * __save_flags(x); __sti(); + * + * local_irq_set(x) == __save_and_sti(x) + */ + + #define local_irq_enable() __asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory") #define __cli() local_irq_disable () diff -urN linux-2.4.19-p7-pristine/include/asm-m68k/ide.h linux-2.4.19-p7/include/asm-m68k/ide.h --- linux-2.4.19-p7-pristine/include/asm-m68k/ide.h Tue Apr 16 03:16:40 2002 +++ linux-2.4.19-p7/include/asm-m68k/ide.h Tue Apr 16 23:16:59 2002 @@ -352,34 +352,6 @@ #define ide_ack_intr(hwif) ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1) -/* - * On the Atari, we sometimes can't enable interrupts: - */ - -/* MSch: changed sti() to STI() wherever possible in ide.c; moved STI() def. - * to asm/ide.h - */ -/* The Atari interrupt structure strictly requires that the IPL isn't lowered - * uncontrolled in an interrupt handler. In the concrete case, the IDE - * interrupt is already a slow int, so the irq is already disabled at the time - * the handler is called, and the IPL has been lowered to the minimum value - * possible. To avoid going below that, STI() checks for being called inside - * an interrupt, and in that case it does nothing. Hope that is reasonable and - * works. (Roman) - */ -#ifdef MACH_ATARI_ONLY -#define ide__sti() \ - do { \ - if (!in_interrupt()) __sti(); \ - } while(0) -#elif defined(CONFIG_ATARI) -#define ide__sti() \ - do { \ - if (!MACH_IS_ATARI || !in_interrupt()) sti(); \ - } while(0) -#else /* !defined(CONFIG_ATARI) */ -#define ide__sti() __sti() -#endif #endif /* __KERNEL__ */ diff -urN linux-2.4.19-p7-pristine/include/asm-m68k/system.h linux-2.4.19-p7/include/asm-m68k/system.h --- linux-2.4.19-p7-pristine/include/asm-m68k/system.h Thu Oct 25 13:53:55 2001 +++ linux-2.4.19-p7/include/asm-m68k/system.h Tue Apr 16 23:16:59 2002 @@ -46,7 +46,6 @@ (last) = _last; \ } - /* interrupt control.. */ #if 0 #define __sti() asm volatile ("andiw %0,%%sr": : "i" (ALLOWINT) : "memory") @@ -63,6 +62,7 @@ /* For spinlocks etc */ #define local_irq_save(x) ({ __save_flags(x); __cli(); }) +#define local_irq_set(x) ({ __save_flags(x); __sti(); }) #define local_irq_restore(x) __restore_flags(x) #define local_irq_disable() __cli() #define local_irq_enable() __sti() @@ -71,7 +71,8 @@ #define sti() __sti() #define save_flags(x) __save_flags(x) #define restore_flags(x) __restore_flags(x) -#define save_and_cli(flags) do { save_flags(flags); cli(); } while(0) +#define save_and_cli(x) do { save_flags(x); cli(); } while(0) +#define save_and_set(x) do { save_flags(x); sti(); } while(0) /* * Force strict CPU ordering. diff -urN linux-2.4.19-p7-pristine/include/asm-mips/ide.h linux-2.4.19-p7/include/asm-mips/ide.h --- linux-2.4.19-p7-pristine/include/asm-mips/ide.h Tue Apr 16 03:16:43 2002 +++ linux-2.4.19-p7/include/asm-mips/ide.h Tue Apr 16 23:16:59 2002 @@ -24,8 +24,6 @@ # endif #endif -#define ide__sti() __sti() - struct ide_ops { int (*ide_default_irq)(ide_ioreg_t base); ide_ioreg_t (*ide_default_io_base)(int index); diff -urN linux-2.4.19-p7-pristine/include/asm-mips/system.h linux-2.4.19-p7/include/asm-mips/system.h --- linux-2.4.19-p7-pristine/include/asm-mips/system.h Tue Apr 16 03:16:46 2002 +++ linux-2.4.19-p7/include/asm-mips/system.h Tue Apr 16 23:16:59 2002 @@ -111,6 +111,8 @@ : /* no inputs */ \ : "memory") +#define __save_and_sti(x) do { __save_flags(x); __sti(); } while(0); + __asm__(".macro\t__restore_flags flags\n\t" ".set\tnoreorder\n\t" ".set\tnoat\n\t" @@ -149,6 +151,7 @@ # define save_flags(x) do { x = __global_save_flags(); } while (0) # define restore_flags(x) __global_restore_flags(x) # define save_and_cli(x) do { save_flags(x); cli(); } while(0) +# define save_and_sti(x) do { save_flags(x); sti(); } while(0) #else /* Single processor */ @@ -157,11 +160,13 @@ # define save_flags(x) __save_flags(x) # define save_and_cli(x) __save_and_cli(x) # define restore_flags(x) __restore_flags(x) +# define save_and_sti(x) __save_and_sti(x) #endif /* SMP */ /* For spinlocks etc */ #define local_irq_save(x) __save_and_cli(x) +#define local_irq_set(x) __save_and_sti(x) #define local_irq_restore(x) __restore_flags(x) #define local_irq_disable() __cli() #define local_irq_enable() __sti() diff -urN linux-2.4.19-p7-pristine/include/asm-mips64/ide.h linux-2.4.19-p7/include/asm-mips64/ide.h --- linux-2.4.19-p7-pristine/include/asm-mips64/ide.h Tue Apr 16 03:16:48 2002 +++ linux-2.4.19-p7/include/asm-mips64/ide.h Tue Apr 16 23:16:59 2002 @@ -27,8 +27,6 @@ # endif #endif -#define ide__sti() __sti() - struct ide_ops { int (*ide_default_irq)(ide_ioreg_t base); ide_ioreg_t (*ide_default_io_base)(int index); diff -urN linux-2.4.19-p7-pristine/include/asm-mips64/system.h linux-2.4.19-p7/include/asm-mips64/system.h --- linux-2.4.19-p7-pristine/include/asm-mips64/system.h Tue Apr 16 03:16:50 2002 +++ linux-2.4.19-p7/include/asm-mips64/system.h Tue Apr 16 23:16:59 2002 @@ -108,6 +108,8 @@ : /* no inputs */ \ : "memory") +#define __save_and_sti(x) do { __save_flags(x); __sti(); } while(0); + __asm__(".macro\t__restore_flags flags\n\t" ".set\tnoreorder\n\t" ".set\tnoat\n\t" @@ -146,6 +148,7 @@ #define save_flags(x) ((x)=__global_save_flags()) #define restore_flags(x) __global_restore_flags(x) #define save_and_cli(x) do { save_flags(x); cli(); } while(0) +#define save_and_sti(x) do { save_flags(x); sti(); } while(0) #else @@ -154,11 +157,13 @@ #define save_flags(x) __save_flags(x) #define restore_flags(x) __restore_flags(x) #define save_and_cli(x) __save_and_cli(x) +#define save_and_sti(x) __save_and_sti(x) #endif /* CONFIG_SMP */ /* For spinlocks etc */ #define local_irq_save(x) __save_and_cli(x) +#define local_irq_set(x) __save_and_sti(x) #define local_irq_restore(x) __restore_flags(x) #define local_irq_disable() __cli() #define local_irq_enable() __sti() diff -urN linux-2.4.19-p7-pristine/include/asm-parisc/ide.h linux-2.4.19-p7/include/asm-parisc/ide.h --- linux-2.4.19-p7-pristine/include/asm-parisc/ide.h Tue Apr 16 03:16:50 2002 +++ linux-2.4.19-p7/include/asm-parisc/ide.h Tue Apr 16 23:16:59 2002 @@ -19,8 +19,6 @@ #define MAX_HWIFS 10 #endif -#define ide__sti() __sti() - static __inline__ int ide_default_irq(ide_ioreg_t base) { switch (base) { diff -urN linux-2.4.19-p7-pristine/include/asm-parisc/system.h linux-2.4.19-p7/include/asm-parisc/system.h --- linux-2.4.19-p7-pristine/include/asm-parisc/system.h Wed Dec 6 11:46:39 2000 +++ linux-2.4.19-p7/include/asm-parisc/system.h Tue Apr 16 23:16:59 2002 @@ -61,6 +61,13 @@ #define smp_wmb() __asm__ __volatile__("":::"memory"); #endif +#error andre hedrick screwed this up please help unscrew in order to clean up +/* + * __save_and_sti(x) == __save_flags(x); ide__sti(); + * __save_flags(x); __sti(); + * + */ + /* interrupt control */ #define __save_flags(x) __asm__ __volatile__("ssm 0, %0" : "=r" (x) : : "memory") #define __restore_flags(x) __asm__ __volatile__("mtsm %0" : : "r" (x) : "memory") @@ -69,6 +76,8 @@ #define local_irq_save(x) \ __asm__ __volatile__("rsm %1,%0" : "=r" (x) :"i" (PSW_I) : "memory" ) +#define local_irq_set(x) \ + __asm__ __volatile__("ssm %1,%0" : "=r" (x) :"i" (PSW_I) : "memory" ) #define local_irq_restore(x) \ __asm__ __volatile__("mtsm %0" : : "r" (x) : "memory" ) #define local_irq_disable() __cli() @@ -80,6 +89,8 @@ #define sti() __sti() #define save_flags(x) __save_flags(x) #define restore_flags(x) __restore_flags(x) +#define save_and_cli(x) do { __save_flags(x); __cli(); } while(0) +#define save_and_sti(x) do { __save_flags(x); __sti(); } while(0) #endif diff -urN linux-2.4.19-p7-pristine/include/asm-ppc/hw_irq.h linux-2.4.19-p7/include/asm-ppc/hw_irq.h --- linux-2.4.19-p7-pristine/include/asm-ppc/hw_irq.h Mon May 21 15:02:06 2001 +++ linux-2.4.19-p7/include/asm-ppc/hw_irq.h Tue Apr 16 23:16:59 2002 @@ -20,6 +20,7 @@ #define __save_flags(flags) __save_flags_ptr((unsigned long *)&flags) #define __save_and_cli(flags) ({__save_flags(flags);__cli();}) +#define __save_and_sti(flags) ({__save_flags(flags);__sti();}) extern void do_lost_interrupts(unsigned long); diff -urN linux-2.4.19-p7-pristine/include/asm-ppc/ide.h linux-2.4.19-p7/include/asm-ppc/ide.h --- linux-2.4.19-p7-pristine/include/asm-ppc/ide.h Tue Apr 16 03:16:51 2002 +++ linux-2.4.19-p7/include/asm-ppc/ide.h Tue Apr 16 23:16:59 2002 @@ -57,8 +57,6 @@ #undef SUPPORT_VLB_SYNC #define SUPPORT_VLB_SYNC 0 -#define ide__sti() __sti() - static __inline__ int ide_default_irq(ide_ioreg_t base) { if (ppc_ide_md.default_irq) diff -urN linux-2.4.19-p7-pristine/include/asm-ppc/system.h linux-2.4.19-p7/include/asm-ppc/system.h --- linux-2.4.19-p7-pristine/include/asm-ppc/system.h Tue Apr 16 03:16:51 2002 +++ linux-2.4.19-p7/include/asm-ppc/system.h Tue Apr 16 23:16:59 2002 @@ -105,6 +105,7 @@ #define save_flags(flags) __save_flags(flags) #define restore_flags(flags) __restore_flags(flags) #define save_and_cli(flags) __save_and_cli(flags) +#define save_and_sti(flags) __save_and_sti(flags) #else /* CONFIG_SMP */ @@ -117,11 +118,15 @@ #define save_flags(x) ((x)=__global_save_flags()) #define restore_flags(x) __global_restore_flags(x) +#define save_and_cli(x) do { save_flags(x); cli(); } while(0); +#define save_and_sti(x) do { save_flags(x); sti(); } while(0); + #endif /* !CONFIG_SMP */ #define local_irq_disable() __cli() #define local_irq_enable() __sti() #define local_irq_save(flags) __save_and_cli(flags) +#define local_irq_set(flags) __save_and_sti(flags) #define local_irq_restore(flags) __restore_flags(flags) static __inline__ unsigned long diff -urN linux-2.4.19-p7-pristine/include/asm-ppc64/hw_irq.h linux-2.4.19-p7/include/asm-ppc64/hw_irq.h --- linux-2.4.19-p7-pristine/include/asm-ppc64/hw_irq.h Tue Apr 16 03:16:51 2002 +++ linux-2.4.19-p7/include/asm-ppc64/hw_irq.h Tue Apr 16 23:16:59 2002 @@ -31,6 +31,7 @@ #define __save_flags(flags) ((flags) = __no_use_save_flags()) #define __restore_flags(flags) __no_use_restore_flags((unsigned long)flags) #define __save_and_cli(flags) ({__save_flags(flags);__cli();}) +#define __save_and_sti(flags) ({__save_flags(flags);__sti();}) #else @@ -63,6 +64,7 @@ } #define __save_and_cli(flags) __do_save_and_cli(&flags) +#define __save_and_sti(flags) ({__save_flags(flags);__sti();}) #endif /* CONFIG_PPC_ISERIES */ diff -urN linux-2.4.19-p7-pristine/include/asm-ppc64/ide.h linux-2.4.19-p7/include/asm-ppc64/ide.h --- linux-2.4.19-p7-pristine/include/asm-ppc64/ide.h Tue Apr 16 03:16:52 2002 +++ linux-2.4.19-p7/include/asm-ppc64/ide.h Tue Apr 16 23:16:59 2002 @@ -22,8 +22,6 @@ #define MAX_HWIFS 4 #endif -#define ide__sti() __sti() - void ppc64_ide_fix_driveid(struct hd_driveid *id); #define ide_fix_driveid(id) ppc64_ide_fix_driveid((id)) diff -urN linux-2.4.19-p7-pristine/include/asm-ppc64/system.h linux-2.4.19-p7/include/asm-ppc64/system.h --- linux-2.4.19-p7-pristine/include/asm-ppc64/system.h Tue Apr 16 03:16:54 2002 +++ linux-2.4.19-p7/include/asm-ppc64/system.h Tue Apr 16 23:16:59 2002 @@ -102,6 +102,7 @@ #define save_flags(flags) __save_flags(flags) #define restore_flags(flags) __restore_flags(flags) #define save_and_cli(flags) __save_and_cli(flags) +#define save_and_sti(flags) __save_and_sti(flags) #else /* CONFIG_SMP */ @@ -114,11 +115,15 @@ #define save_flags(x) ((x)=__global_save_flags()) #define restore_flags(x) __global_restore_flags(x) +#define save_and_cli(x) do { save_flags(x); cli(); } while(0); +#define save_and_sti(x) do { save_flags(x); sti(); } while(0); + #endif /* !CONFIG_SMP */ #define local_irq_disable() __cli() #define local_irq_enable() __sti() #define local_irq_save(flags) __save_and_cli(flags) +#define local_irq_set(flags) __save_and_sti(flags) #define local_irq_restore(flags) __restore_flags(flags) static __inline__ int __is_processor(unsigned long pv) diff -urN linux-2.4.19-p7-pristine/include/asm-s390/ide.h linux-2.4.19-p7/include/asm-s390/ide.h --- linux-2.4.19-p7-pristine/include/asm-s390/ide.h Tue Apr 16 03:16:55 2002 +++ linux-2.4.19-p7/include/asm-s390/ide.h Tue Apr 16 23:16:59 2002 @@ -15,8 +15,6 @@ #define MAX_HWIFS 0 #endif -#define ide__sti() do {} while (0) - typedef union { unsigned all : 8; /* all of the bits together */ struct { diff -urN linux-2.4.19-p7-pristine/include/asm-s390/system.h linux-2.4.19-p7/include/asm-s390/system.h --- linux-2.4.19-p7-pristine/include/asm-s390/system.h Tue Apr 16 03:16:55 2002 +++ linux-2.4.19-p7/include/asm-s390/system.h Tue Apr 16 23:16:59 2002 @@ -206,8 +206,12 @@ : "cc", "0", "1", "2"); \ }) +#define __save_and_cli(x) do { __save_flags(x); __cli(); } while(0); +#define __save_and_sti(x) do { __save_flags(x); __sti(); } while(0); + /* For spinlocks etc */ #define local_irq_save(x) ((x) = __cli()) +#define local_irq_set(x) __save_and_sti(x) #define local_irq_restore(x) __restore_flags(x) #define local_irq_disable() __cli() #define local_irq_enable() __sti() @@ -223,6 +227,8 @@ #define sti() __global_sti() #define save_flags(x) ((x)=__global_save_flags()) #define restore_flags(x) __global_restore_flags(x) +#define save_and_cli(x) do { save_flags(x); cli(); } while(0); +#define save_and_sti(x) do { save_flags(x); sti(); } while(0); extern void smp_ctl_set_bit(int cr, int bit); extern void smp_ctl_clear_bit(int cr, int bit); @@ -235,6 +241,8 @@ #define sti() __sti() #define save_flags(x) __save_flags(x) #define restore_flags(x) __restore_flags(x) +#define save_and_cli(x) __save_and_cli(x) +#define save_and_sti(x) __save_and_sti(x) #define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit) #define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit) diff -urN linux-2.4.19-p7-pristine/include/asm-s390x/ide.h linux-2.4.19-p7/include/asm-s390x/ide.h --- linux-2.4.19-p7-pristine/include/asm-s390x/ide.h Tue Apr 16 03:16:55 2002 +++ linux-2.4.19-p7/include/asm-s390x/ide.h Tue Apr 16 23:16:59 2002 @@ -15,8 +15,6 @@ #define MAX_HWIFS 0 #endif -#define ide__sti() do {} while (0) - typedef union { unsigned all : 8; /* all of the bits together */ struct { diff -urN linux-2.4.19-p7-pristine/include/asm-s390x/system.h linux-2.4.19-p7/include/asm-s390x/system.h --- linux-2.4.19-p7-pristine/include/asm-s390x/system.h Tue Apr 16 03:16:56 2002 +++ linux-2.4.19-p7/include/asm-s390x/system.h Tue Apr 16 23:16:59 2002 @@ -216,8 +216,13 @@ : "cc", "0", "1", "2"); \ }) + +#define __save_and_cli(x) do { __save_flags(x); __cli(); } while(0); +#define __save_and_sti(x) do { __save_flags(x); __sti(); } while(0); + /* For spinlocks etc */ #define local_irq_save(x) ((x) = __cli()) +#define local_irq_set(x) __save_and_sti(x) #define local_irq_restore(x) __restore_flags(x) #define local_irq_disable() __cli() #define local_irq_enable() __sti() @@ -233,6 +238,8 @@ #define sti() __global_sti() #define save_flags(x) ((x)=__global_save_flags()) #define restore_flags(x) __global_restore_flags(x) +#define save_and_cli(x) do { save_flags(x); cli(); } while(0); +#define save_and_sti(x) do { save_flags(x); sti(); } while(0); extern void smp_ctl_set_bit(int cr, int bit); extern void smp_ctl_clear_bit(int cr, int bit); @@ -245,6 +252,8 @@ #define sti() __sti() #define save_flags(x) __save_flags(x) #define restore_flags(x) __restore_flags(x) +#define save_and_cli(x) __save_and_cli(x) +#define save_and_sti(x) __save_and_sti(x) #define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit) #define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit) diff -urN linux-2.4.19-p7-pristine/include/asm-sh/ide.h linux-2.4.19-p7/include/asm-sh/ide.h --- linux-2.4.19-p7-pristine/include/asm-sh/ide.h Tue Apr 16 03:16:56 2002 +++ linux-2.4.19-p7/include/asm-sh/ide.h Tue Apr 16 23:16:59 2002 @@ -22,8 +22,6 @@ #define MAX_HWIFS 2 #endif -#define ide__sti() __sti() - static __inline__ int ide_default_irq_hp600(ide_ioreg_t base) { switch (base) { diff -urN linux-2.4.19-p7-pristine/include/asm-sh/system.h linux-2.4.19-p7/include/asm-sh/system.h --- linux-2.4.19-p7-pristine/include/asm-sh/system.h Sat Sep 8 12:29:09 2001 +++ linux-2.4.19-p7/include/asm-sh/system.h Tue Apr 16 23:16:59 2002 @@ -215,8 +215,11 @@ : "=&r" (__dummy)); \ } while (0) +#define __save_and_sti(x) do { __save_flags(x); __sti(); } while(0); + /* For spinlocks etc */ #define local_irq_save(x) x = __save_and_cli() +#define local_irq_set(x) __save_and_sti(x) #define local_irq_restore(x) __restore_flags(x) #define local_irq_disable() __cli() #define local_irq_enable() __sti() @@ -231,13 +234,14 @@ #define sti() __global_sti() #define save_flags(x) ((x)=__global_save_flags()) #define restore_flags(x) __global_restore_flags(x) - +#define save_and_sti(x) do { save_flags(x); sti(); } while(0); #else #define cli() __cli() #define sti() __sti() #define save_flags(x) __save_flags(x) #define save_and_cli(x) x = __save_and_cli() +#define save_and_sti(x) __save_and_sti(x) #define restore_flags(x) __restore_flags(x) #endif diff -urN linux-2.4.19-p7-pristine/include/asm-sparc/ide.h linux-2.4.19-p7/include/asm-sparc/ide.h --- linux-2.4.19-p7-pristine/include/asm-sparc/ide.h Tue Apr 16 03:16:56 2002 +++ linux-2.4.19-p7/include/asm-sparc/ide.h Tue Apr 16 23:16:59 2002 @@ -20,8 +20,6 @@ #undef MAX_HWIFS #define MAX_HWIFS 2 -#define ide__sti() __sti() - static __inline__ int ide_default_irq(ide_ioreg_t base) { return 0; diff -urN linux-2.4.19-p7-pristine/include/asm-sparc/system.h linux-2.4.19-p7/include/asm-sparc/system.h --- linux-2.4.19-p7-pristine/include/asm-sparc/system.h Tue Oct 30 15:08:11 2001 +++ linux-2.4.19-p7/include/asm-sparc/system.h Tue Apr 16 23:16:59 2002 @@ -241,20 +241,21 @@ return retval; } +#define __save_and_sti(flags) do { __save_flags(flags); __sti(); } while(0); + #define __save_flags(flags) ((flags) = getipl()) #define __save_and_cli(flags) ((flags) = read_psr_and_cli()) #define __restore_flags(flags) setipl((flags)) #define local_irq_disable() __cli() #define local_irq_enable() __sti() #define local_irq_save(flags) __save_and_cli(flags) +#define local_irq_set(flags) __save_and_sti(flags) #define local_irq_restore(flags) __restore_flags(flags) #ifdef CONFIG_SMP extern unsigned char global_irq_holder; -#define save_and_cli(flags) do { save_flags(flags); cli(); } while(0) - extern void __global_cli(void); extern void __global_sti(void); extern unsigned long __global_save_flags(void); @@ -263,6 +264,7 @@ #define sti() __global_sti() #define save_flags(flags) ((flags)=__global_save_flags()) #define restore_flags(flags) __global_restore_flags(flags) +#define save_and_sti(flags) do { save_flags(flags); sti(); } while(0); #else @@ -271,6 +273,7 @@ #define save_flags(x) __save_flags(x) #define restore_flags(x) __restore_flags(x) #define save_and_cli(x) __save_and_cli(x) +#define save_and_sti(x) __save_and_sti(x) #endif diff -urN linux-2.4.19-p7-pristine/include/asm-sparc64/ide.h linux-2.4.19-p7/include/asm-sparc64/ide.h --- linux-2.4.19-p7-pristine/include/asm-sparc64/ide.h Tue Apr 16 03:16:57 2002 +++ linux-2.4.19-p7/include/asm-sparc64/ide.h Tue Apr 16 23:16:59 2002 @@ -20,8 +20,6 @@ #undef MAX_HWIFS #define MAX_HWIFS 2 -#define ide__sti() __sti() - static __inline__ int ide_default_irq(ide_ioreg_t base) { return 0; diff -urN linux-2.4.19-p7-pristine/include/asm-sparc64/system.h linux-2.4.19-p7/include/asm-sparc64/system.h --- linux-2.4.19-p7-pristine/include/asm-sparc64/system.h Fri Dec 21 09:42:03 2001 +++ linux-2.4.19-p7/include/asm-sparc64/system.h Tue Apr 16 23:16:59 2002 @@ -65,9 +65,13 @@ #define __save_flags(flags) ((flags) = getipl()) #define __save_and_cli(flags) ((flags) = read_pil_and_cli()) #define __restore_flags(flags) setipl((flags)) + +#define __save_and_sti(flags) ({ __save_flags(flags); __sti(); }) + #define local_irq_disable() __cli() #define local_irq_enable() __sti() #define local_irq_save(flags) __save_and_cli(flags) +#define local_irq_set(flags) __save_and_sti(flags) #define local_irq_restore(flags) __restore_flags(flags) #ifndef CONFIG_SMP @@ -76,6 +80,7 @@ #define save_flags(x) __save_flags(x) #define restore_flags(x) __restore_flags(x) #define save_and_cli(x) __save_and_cli(x) +#define save_and_sti(x) __save_and_sti(x) #else #ifndef __ASSEMBLY__ @@ -90,6 +95,7 @@ #define save_flags(x) ((x) = __global_save_flags()) #define restore_flags(flags) __global_restore_flags(flags) #define save_and_cli(flags) do { save_flags(flags); cli(); } while(0) +#define save_and_sti(flags) do { save_flags(flags); sti(); } while(0) #endif diff -urN linux-2.4.19-p7-pristine/include/linux/blkdev.h linux-2.4.19-p7/include/linux/blkdev.h --- linux-2.4.19-p7-pristine/include/linux/blkdev.h Tue Apr 16 03:16:58 2002 +++ linux-2.4.19-p7/include/linux/blkdev.h Tue Apr 16 02:30:46 2002 @@ -37,6 +37,7 @@ unsigned int nr_segments; unsigned int nr_hw_segments; unsigned long current_nr_sectors; + unsigned long hard_cur_sectors; void * special; char * buffer; struct completion * waiting; diff -urN linux-2.4.19-p7-pristine/include/linux/hdreg.h linux-2.4.19-p7/include/linux/hdreg.h --- linux-2.4.19-p7-pristine/include/linux/hdreg.h Tue Apr 16 03:16:59 2002 +++ linux-2.4.19-p7/include/linux/hdreg.h Fri Apr 19 15:39:04 2002 @@ -131,8 +131,8 @@ */ #define IDE_TASKFILE_STD_OUT_FLAGS 0xFE #define IDE_TASKFILE_STD_IN_FLAGS 0xFE -#define IDE_HOB_STD_OUT_FLAGS 0xC0 -#define IDE_HOB_STD_IN_FLAGS 0xC0 +#define IDE_HOB_STD_OUT_FLAGS 0x3C /* sector, nsector lcyl and hcyl */ +#define IDE_HOB_STD_IN_FLAGS 0x3C typedef struct ide_task_request_s { task_ioreg_t io_ports[8]; @@ -177,29 +177,67 @@ /* ATA/ATAPI Commands pre T13 Spec */ #define WIN_NOP 0x00 +/* + * 0x01->0x02 Reserved + */ #define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ +/* + * 0x04->0x07 Reserved + */ #define WIN_SRST 0x08 /* ATAPI soft reset command */ #define WIN_DEVICE_RESET 0x08 -#define WIN_RESTORE 0x10 +/* + * 0x09->0x0F Reserved + */ +#define WIN_RECAL 0x10 +/* + * 0x10->0x1F Reserved + */ +#define WIN_RESTORE WIN_RECAL #define WIN_READ 0x20 /* 28-Bit */ +#define WIN_READ_ONCE 0x21 /* 28-Bit without retries */ +#define WIN_READ_LONG 0x22 /* 28-Bit */ +#define WIN_READ_LONG_ONCE 0x23 /* 28-Bit without retries */ #define WIN_READ_EXT 0x24 /* 48-Bit */ #define WIN_READDMA_EXT 0x25 /* 48-Bit */ #define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */ #define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ #define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ +/* + * 0x2A->0x2F Reserved + */ #define WIN_WRITE 0x30 /* 28-Bit */ +#define WIN_WRITE_ONCE 0x31 /* 28-Bit without retries */ +#define WIN_WRITE_LONG 0x32 /* 28-Bit */ +#define WIN_WRITE_LONG_ONCE 0x33 /* 28-Bit without retries */ #define WIN_WRITE_EXT 0x34 /* 48-Bit */ #define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ #define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ #define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ #define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ #define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ +/* + * 0x3A->0x3B Reserved + */ #define WIN_WRITE_VERIFY 0x3C /* 28-Bit */ +/* + * 0x3D->0x3F Reserved + */ #define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ +#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - without retries */ #define WIN_VERIFY_EXT 0x42 /* 48-Bit */ +/* + * 0x43->0x4F Reserved + */ #define WIN_FORMAT 0x50 +/* + * 0x51->0x5F Reserved + */ #define WIN_INIT 0x60 -#define WIN_SEEK 0x70 +/* + * 0x61->0x5F Reserved + */ +#define WIN_SEEK 0x70 /* 0x70-0x7F Reserved */ #define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ #define WIN_DIAGNOSE 0x90 #define WIN_SPECIFY 0x91 /* set drive geometry translation */ @@ -208,6 +246,9 @@ #define WIN_SETIDLE2 0x97 #define WIN_CHECKPOWERMODE2 0x98 #define WIN_SLEEPNOW2 0x99 +/* + * 0x9A VENDOR + */ #define WIN_PACKETCMD 0xA0 /* Send a packet command. */ #define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ #define WIN_QUEUED_SERVICE 0xA2 @@ -218,7 +259,9 @@ #define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ #define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */ #define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ +#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - without retries */ #define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ +#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */ #define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */ #define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ #define WIN_GETMEDIASTATUS 0xDA @@ -233,6 +276,7 @@ #define WIN_SLEEPNOW1 0xE6 #define WIN_FLUSH_CACHE 0xE7 #define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ +#define WIN_WRITE_SAME 0xE9 /* read ata-2 to use */ #define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ #define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ #define WIN_MEDIAEJECT 0xED @@ -270,7 +314,7 @@ #define SMART_HCYL_PASS 0xC2 /* WIN_SETFEATURES sub-commands */ - +#define SETFEATURES_EN_8BIT 0x01 /* Enable 8-Bit Transfers */ #define SETFEATURES_EN_WCACHE 0x02 /* Enable write cache */ #define SETFEATURES_XFER 0x03 /* Set transfer mode */ # define XFER_UDMA_7 0x47 /* 0100|0111 */ @@ -296,17 +340,25 @@ #define SETFEATURES_DIS_DEFECT 0x04 /* Disable Defect Management */ #define SETFEATURES_EN_APM 0x05 /* Enable advanced power management */ #define SETFEATURES_DIS_MSN 0x31 /* Disable Media Status Notification */ +#define SETFEATURES_DIS_RETRY 0x33 /* Disable Retry */ #define SETFEATURES_EN_AAM 0x42 /* Enable Automatic Acoustic Management */ +#define SETFEATURES_RW_LONG 0x44 /* Set Lenght of VS bytes */ +#define SETFEATURES_SET_CACHE 0x54 /* Set Cache segments to SC Reg. Val */ #define SETFEATURES_DIS_RLA 0x55 /* Disable read look-ahead feature */ #define SETFEATURES_EN_RI 0x5D /* Enable release interrupt */ #define SETFEATURES_EN_SI 0x5E /* Enable SERVICE interrupt */ #define SETFEATURES_DIS_RPOD 0x66 /* Disable reverting to power on defaults */ +#define SETFEATURES_DIS_ECC 0x77 /* Disable ECC byte count */ +#define SETFEATURES_DIS_8BIT 0x81 /* Disable 8-Bit Transfers */ #define SETFEATURES_DIS_WCACHE 0x82 /* Disable write cache */ #define SETFEATURES_EN_DEFECT 0x84 /* Enable Defect Management */ #define SETFEATURES_DIS_APM 0x85 /* Disable advanced power management */ +#define SETFEATURES_EN_ECC 0x88 /* Enable ECC byte count */ #define SETFEATURES_EN_MSN 0x95 /* Enable Media Status Notification */ +#define SETFEATURES_EN_RETRY 0x99 /* Enable Retry */ #define SETFEATURES_EN_RLA 0xAA /* Enable read look-ahead feature */ #define SETFEATURES_PREFETCH 0xAB /* Sets drive prefetch value */ +#define SETFEATURES_4B_RW_LONG 0xBB /* Set Lenght of 4 bytes */ #define SETFEATURES_DIS_AAM 0xC2 /* Disable Automatic Acoustic Management */ #define SETFEATURES_EN_RPOD 0xCC /* Enable reverting to power on defaults */ #define SETFEATURES_DIS_RI 0xDD /* Disable release interrupt */ @@ -501,7 +553,10 @@ * cmd set-feature supported extensions * 15: Shall be ZERO * 14: Shall be ONE - * 13:3 reserved + * 13:6 reserved + * 5: General Purpose Logging + * 4: Streaming Feature Set + * 3: Media Card Pass Through * 2: Media Serial Number Valid * 1: SMART selt-test supported * 0: SMART error logging @@ -548,19 +603,22 @@ * command set-feature default * 15: Shall be ZERO * 14: Shall be ONE - * 13:3 reserved + * 13:6 reserved + * 5: General Purpose Logging enabled + * 4: Valid CONFIGURE STREAM executed + * 3: Media Card Pass Through enabled * 2: Media Serial Number Valid * 1: SMART selt-test supported * 0: SMART error logging */ unsigned short dma_ultra; /* (word 88) */ - unsigned short word89; /* reserved (word 89) */ - unsigned short word90; /* reserved (word 90) */ + unsigned short trseuc; /* time required for security erase */ + unsigned short trsEuc; /* time required for enhanced erase */ unsigned short CurAPMvalues; /* current APM values */ - unsigned short word92; /* reserved (word 92) */ + unsigned short mprc; /* master password revision code */ unsigned short hw_config; /* hardware config (word 93) - * 15: - * 14: + * 15: Shall be ZERO + * 14: Shall be ONE * 13: * 12: * 11: @@ -574,18 +632,17 @@ * 3: * 2: * 1: - * 0: + * 0: Shall be ONE */ unsigned short acoustic; /* (word 94) * 15:8 Vendor's recommended value * 7:0 current value */ - unsigned short words95_99[5]; /* reserved words 95-99 */ -#if 0 - unsigned short words100_103[4] ;/* reserved words 100-103 */ -#else + unsigned short msrqs; /* min stream request size */ + unsigned short sxfert; /* stream transfer time */ + unsigned short sal; /* stream access latency */ + unsigned int spg; /* stream performance granularity */ unsigned long long lba_capacity_2;/* 48-bit total number of sectors */ -#endif unsigned short words104_125[22];/* reserved words 104-125 */ unsigned short last_lun; /* (word 126) */ unsigned short word127; /* (word 127) Feature Set diff -urN linux-2.4.19-p7-pristine/include/linux/ide.h linux-2.4.19-p7/include/linux/ide.h --- linux-2.4.19-p7-pristine/include/linux/ide.h Tue Apr 16 03:17:00 2002 +++ linux-2.4.19-p7/include/linux/ide.h Sat Apr 27 21:56:09 2002 @@ -16,6 +16,13 @@ #include #include + +#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT +# define __IDEDMA_TIMEOUT +#else /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ +# undef __IDEDMA_TIMEOUT +#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ + /* * This is the multiple IDE interface driver, as evolved from hd.c. * It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15). @@ -347,6 +354,9 @@ } b; } special_t; +struct ide_driver_s; +struct ide_settings_s; + typedef struct ide_drive_s { request_queue_t queue; /* request queue */ struct ide_drive_s *next; /* circular list of hwgroup drives */ @@ -381,7 +391,12 @@ unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */ unsigned remap_0_to_1 : 2; /* 0=remap if ezdrive, 1=remap, 2=noremap */ unsigned ata_flash : 1; /* 1=present, 0=default */ - unsigned addressing; /* : 2; 0=28-bit, 1=48-bit, 2=64-bit */ + unsigned addressing; /* : 3; + * 0=28-bit + * 1=48-bit + * 2=48-bit doing 28-bit + * 3=64-bit + */ byte scsi; /* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */ byte media; /* disk, cdrom, tape, floppy, ... */ select_t select; /* basic drive/head select reg value */ @@ -404,16 +419,16 @@ unsigned long capacity; /* total number of sectors */ unsigned long long capacity48; /* total number of sectors */ unsigned int drive_data; /* for use by tuneproc/selectproc as needed */ - void *hwif; /* actually (ide_hwif_t *) */ + struct hwif_s *hwif; /* actually (ide_hwif_t *) */ wait_queue_head_t wqueue; /* used to wait for drive in open() */ struct hd_driveid *id; /* drive model identification info */ struct hd_struct *part; /* drive partition table */ char name[4]; /* drive name, such as "hda" */ - void *driver; /* (ide_driver_t *) */ + struct ide_driver_s *driver; /* (ide_driver_t *) */ void *driver_data; /* extra driver data */ devfs_handle_t de; /* directory for device */ struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ - void *settings; /* /proc/ide/ drive settings */ + struct ide_settings_s *settings; /* /proc/ide/ drive settings */ char driver_req[10]; /* requests specific driver */ int last_lun; /* last logical unit */ int forced_lun; /* if hdxlun was given at boot */ @@ -469,6 +484,82 @@ typedef void (ide_ideproc_t)(ide_ide_action_t, ide_drive_t *, void *, unsigned int); /* + * mapping stuff, prepare for highmem... + * + * temporarily mapping a (possible) highmem bio for PIO transfer + */ +#define ide_rq_offset(rq) \ + (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9) + +extern inline void *ide_map_buffer(struct request *rq, unsigned long *flags) +{ + return rq->buffer + ide_rq_offset(rq); +} + +extern inline void ide_unmap_buffer(char *buffer, unsigned long *flags) +{ + do { } while (0); +} + +#if 1 +/* + * A Verbose noise maker for debugging on the attempted transfer rates. + */ +extern inline char *ide_xfer_verbose (byte xfer_rate) +{ + switch(xfer_rate) { + case XFER_UDMA_7: return("UDMA 7"); + case XFER_UDMA_6: return("UDMA 6"); + case XFER_UDMA_5: return("UDMA 5"); + case XFER_UDMA_4: return("UDMA 4"); + case XFER_UDMA_3: return("UDMA 3"); + case XFER_UDMA_2: return("UDMA 2"); + case XFER_UDMA_1: return("UDMA 1"); + case XFER_UDMA_0: return("UDMA 0"); + case XFER_MW_DMA_2: return("MW DMA 2"); + case XFER_MW_DMA_1: return("MW DMA 1"); + case XFER_MW_DMA_0: return("MW DMA 0"); + case XFER_SW_DMA_2: return("SW DMA 2"); + case XFER_SW_DMA_1: return("SW DMA 1"); + case XFER_SW_DMA_0: return("SW DMA 0"); + case XFER_PIO_4: return("PIO 4"); + case XFER_PIO_3: return("PIO 3"); + case XFER_PIO_2: return("PIO 2"); + case XFER_PIO_1: return("PIO 1"); + case XFER_PIO_0: return("PIO 0"); + case XFER_PIO_SLOW: return("PIO SLOW"); + default: return("XFER ERROR"); + } +} + +/* + * A Verbose noise maker for debugging on the attempted dmaing calls. + */ +extern inline char *ide_dmafunc_verbose (ide_dma_action_t dmafunc) +{ + switch (dmafunc) { + case ide_dma_read: return("ide_dma_read"); + case ide_dma_write: return("ide_dma_write"); + case ide_dma_begin: return("ide_dma_begin"); + case ide_dma_end: return("ide_dma_end:"); + case ide_dma_check: return("ide_dma_check"); + case ide_dma_on: return("ide_dma_on"); + case ide_dma_off: return("ide_dma_off"); + case ide_dma_off_quietly: return("ide_dma_off_quietly"); + case ide_dma_test_irq: return("ide_dma_test_irq"); + case ide_dma_bad_drive: return("ide_dma_bad_drive"); + case ide_dma_good_drive: return("ide_dma_good_drive"); + case ide_dma_verbose: return("ide_dma_verbose"); + case ide_dma_retune: return("ide_dma_retune"); + case ide_dma_lostirq: return("ide_dma_lostirq"); + case ide_dma_timeout: return("ide_dma_timeout"); + default: return("unknown"); + } +} + +#endif + +/* * An ide_tuneproc_t() is used to set the speed of an IDE interface * to a particular PIO mode. The "byte" parameter is used * to select the PIO mode by number (0,1,2,3,4,5), and a value of 255 @@ -513,8 +604,14 @@ typedef struct hwif_s { struct hwif_s *next; /* for linked-list in ide_hwgroup_t */ - void *hwgroup; /* actually (ide_hwgroup_t *) */ + struct hwgroup_s *hwgroup; /* actually (ide_hwgroup_t *) */ ide_ioreg_t io_ports[IDE_NR_PORTS]; /* task file registers */ +/* + * FIXME!! need a generic register set :-/ PPC guys ideas?? + * + * ide_mmioreg_t mm_ports[IDE_NR_PORTS]; "task file registers" + * + */ hw_regs_t hw; /* Hardware info */ ide_drive_t drives[MAX_DRIVES]; /* drive info */ struct gendisk *gd; /* gendisk structure */ @@ -552,6 +649,7 @@ unsigned reset : 1; /* reset after probe */ unsigned autodma : 1; /* automatically try to enable DMA at boot */ unsigned udma_four : 1; /* 1=ATA-66 capable, 0=default */ + unsigned highmem : 1; /* can do full 32-bit dma */ byte channel; /* for dual-port chips: 0=primary, 1=secondary */ #ifdef CONFIG_BLK_DEV_IDEPCI struct pci_dev *pci_dev; /* for pci chipsets */ @@ -598,6 +696,8 @@ struct request wrq; /* local copy of current write rq */ unsigned long poll_timeout; /* timeout value during long polls */ ide_expiry_t *expiry; /* queried upon timeouts */ + int pio_clock; /* ide_system_bus_speed */ + int addressing; /* hosts addressing */ } ide_hwgroup_t; /* structure attached to the request for IDE_TASK_CMDS */ @@ -685,24 +785,6 @@ */ #define IDE_SUBDRIVER_VERSION 1 -typedef int (ide_cleanup_proc)(ide_drive_t *); -typedef int (ide_standby_proc)(ide_drive_t *); -typedef int (ide_flushcache_proc)(ide_drive_t *); -typedef ide_startstop_t (ide_do_request_proc)(ide_drive_t *, struct request *, unsigned long); -typedef void (ide_end_request_proc)(byte, ide_hwgroup_t *); -typedef int (ide_ioctl_proc)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long); -typedef int (ide_open_proc)(struct inode *, struct file *, ide_drive_t *); -typedef void (ide_release_proc)(struct inode *, struct file *, ide_drive_t *); -typedef int (ide_check_media_change_proc)(ide_drive_t *); -typedef void (ide_revalidate_proc)(ide_drive_t *); -typedef void (ide_pre_reset_proc)(ide_drive_t *); -typedef unsigned long (ide_capacity_proc)(ide_drive_t *); -typedef ide_startstop_t (ide_special_proc)(ide_drive_t *); -typedef void (ide_setting_proc)(ide_drive_t *); -typedef int (ide_reinit_proc)(ide_drive_t *); -typedef void (ata_prebuilder_proc)(ide_drive_t *); -typedef void (atapi_prebuilder_proc)(ide_drive_t *); - typedef struct ide_driver_s { const char *name; const char *version; @@ -710,26 +792,31 @@ unsigned busy : 1; unsigned supports_dma : 1; unsigned supports_dsc_overlap : 1; - ide_cleanup_proc *cleanup; - ide_standby_proc *standby; - ide_flushcache_proc *flushcache; - ide_do_request_proc *do_request; - ide_end_request_proc *end_request; - ide_ioctl_proc *ioctl; - ide_open_proc *open; - ide_release_proc *release; - ide_check_media_change_proc *media_change; - ide_revalidate_proc *revalidate; - ide_pre_reset_proc *pre_reset; - ide_capacity_proc *capacity; - ide_special_proc *special; - ide_proc_entry_t *proc; - ide_reinit_proc *reinit; - ata_prebuilder_proc *ata_prebuilder; - atapi_prebuilder_proc *atapi_prebuilder; + int (*cleanup)(ide_drive_t *); + int (*standby)(ide_drive_t *); + int (*suspend)(ide_drive_t *); + int (*resume)(ide_drive_t *); + int (*flushcache)(ide_drive_t *); + ide_startstop_t (*do_request)(ide_drive_t *, struct request *, unsigned long); + int (*end_request)(ide_drive_t *, int); + byte (*sense)(ide_drive_t *, const char *, byte); + ide_startstop_t (*error)(ide_drive_t *, const char *, byte); + int (*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long); + int (*open)(struct inode *, struct file *, ide_drive_t *); + void (*release)(struct inode *, struct file *, ide_drive_t *); + int (*media_change)(ide_drive_t *); + void (*revalidate)(ide_drive_t *); + void (*pre_reset)(ide_drive_t *); + unsigned long (*capacity)(ide_drive_t *); + ide_startstop_t (*special)(ide_drive_t *); + ide_proc_entry_t *proc; + int (*init)(void); + int (*reinit)(ide_drive_t *); + void (*ata_prebuilder)(ide_drive_t *); + void (*atapi_prebuilder)(ide_drive_t *); } ide_driver_t; -#define DRIVER(drive) ((ide_driver_t *)((drive)->driver)) +#define DRIVER(drive) ((drive)->driver) /* * IDE modules. @@ -769,23 +856,7 @@ #define LOCAL_END_REQUEST /* Don't generate end_request in blk.h */ #include -void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup); - -/* - * This is used for (nearly) all data transfers from/to the IDE interface - * FIXME for 2.5, to a pointer pass verses memcpy........ - */ -void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount); -void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount); - -/* - * This is used for (nearly) all ATAPI data transfers from/to the IDE interface - * FIXME for 2.5, to a pointer pass verses memcpy........ - */ -void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount); -void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount); - -int drive_is_ready (ide_drive_t *drive); +int ide_end_request (ide_drive_t *drive, int uptodate); /* * This is used on exit from the driver, to designate the next irq handler @@ -828,8 +899,6 @@ */ int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, byte bad, unsigned long timeout); -int ide_wait_noerr (ide_drive_t *drive, byte good, byte bad, unsigned long timeout); - /* * This routine is called from the partition-table code in genhd.c * to "convert" a drive to a logical geometry with fewer than 1024 cyls. @@ -856,7 +925,7 @@ * Re-Start an operation for an IDE interface. * The caller should return immediately after invoking this. */ -ide_startstop_t restart_request (ide_drive_t *); +int restart_request (ide_drive_t *, struct request *); /* * This function is intended to be used prior to invoking ide_do_drive_cmd(). @@ -924,9 +993,8 @@ ide_pre_handler_t *prehandler; ide_handler_t *handler; ide_post_handler_t *posthandler; - void *special; /* valid_t generally */ struct request *rq; /* copy of request */ - unsigned long block; /* copy of block */ + void *special; /* valid_t generally */ } ide_task_t; typedef struct pkt_task_s { @@ -934,25 +1002,31 @@ int data_phase; int command_type; ide_handler_t *handler; - void *special; struct request *rq; /* copy of request */ - unsigned long block; /* copy of block */ + void *special; } pkt_task_t; +void ata_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount); +void ata_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount); +void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount); +void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount); +void taskfile_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount); +void taskfile_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount); + +int drive_is_ready (ide_drive_t *drive); +int wait_for_ready (ide_drive_t *drive, int timeout); + /* - * taskfile io for disks for now... + * taskfile io for disks for now...and builds request from ide_ioctl */ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task); -/* - * Builds request from ide_ioctl - */ -void do_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, ide_handler_t *handler); +void ide_end_taskfile (ide_drive_t *drive, byte stat, byte err); /* * Special Flagged Register Validation Caller */ -// ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task); +ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task); ide_startstop_t set_multmode_intr (ide_drive_t *drive); ide_startstop_t set_geometry_intr (ide_drive_t *drive); @@ -962,19 +1036,21 @@ ide_startstop_t task_mulin_intr (ide_drive_t *drive); ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq); ide_startstop_t task_out_intr (ide_drive_t *drive); +ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq); ide_startstop_t task_mulout_intr (ide_drive_t *drive); void ide_init_drive_taskfile (struct request *rq); -int ide_wait_taskfile (ide_drive_t *drive, struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile, byte *buf); - int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *cmd, byte *buf); ide_pre_handler_t * ide_pre_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile); ide_handler_t * ide_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile); +ide_post_handler_t * ide_post_handler_parser (struct hd_drive_task_hdr *taskfile, struct hd_drive_hob_hdr *hobfile); /* Expects args is a full set of TF registers and parses the command type */ int ide_cmd_type_parser (ide_task_t *args); int ide_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +int ide_cmd_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +int ide_task_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); #ifdef CONFIG_PKT_TASK_IOCTL int pkt_taskfile_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); @@ -989,6 +1065,7 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed); byte eighty_ninty_three (ide_drive_t *drive); int set_transfer (ide_drive_t *drive, ide_task_t *args); +int taskfile_lib_get_identify (ide_drive_t *drive, byte *buf); /* * ide_system_bus_speed() returns what we think is the system VESA/PCI @@ -999,12 +1076,6 @@ int ide_system_bus_speed (void); /* - * ide_multwrite() transfers a block of up to mcount sectors of data - * to a drive as part of a disk multwrite operation. - */ -int ide_multwrite (ide_drive_t *drive, unsigned int mcount); - -/* * ide_stall_queue() can be used by a drive to give excess bandwidth back * to the hwgroup by sleeping for timeout jiffies. */ @@ -1076,6 +1147,28 @@ #else /* CONFIG_BLK_DEV_OFFBOARD */ # define OFF_BOARD NEVER_BOARD #endif /* CONFIG_BLK_DEV_OFFBOARD */ + + +typedef struct ide_pci_enablebit_s { + byte reg; /* byte pci reg holding the enable-bit */ + byte mask; /* mask to isolate the enable-bit */ + byte val; /* value of masked reg when "enabled" */ +} ide_pci_enablebit_t; + +typedef struct ide_pci_device_s { + ide_pci_devid_t devid; + char *name; + void (*order_fix)(struct pci_dev *, struct ide_pci_device_s *); + unsigned int (*init_chipset)(struct pci_dev *, const char *); + unsigned int (*ata66_check)(ide_hwif_t *); + void (*init_hwif)(ide_hwif_t *); + void (*dma_init)(ide_hwif_t *, unsigned long); + ide_pci_enablebit_t enablebits[2]; + byte bootable; + unsigned int extra; +} ide_pci_device_t; + +void ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t *d) __init; unsigned long ide_find_free_region (unsigned short size) __init; void ide_scan_pcibus (int scan_direction) __init; diff -urN linux-2.4.19-p7-pristine/include/linux/pci_ids.h linux-2.4.19-p7/include/linux/pci_ids.h --- linux-2.4.19-p7-pristine/include/linux/pci_ids.h Tue Apr 16 03:17:01 2002 +++ linux-2.4.19-p7/include/linux/pci_ids.h Tue Apr 16 02:30:48 2002 @@ -606,6 +606,7 @@ #define PCI_DEVICE_ID_PROMISE_20268 0x4d68 #define PCI_DEVICE_ID_PROMISE_20268R 0x6268 #define PCI_DEVICE_ID_PROMISE_20269 0x4d69 +#define PCI_DEVICE_ID_PROMISE_20271 0x6269 #define PCI_DEVICE_ID_PROMISE_20275 0x1275 #define PCI_DEVICE_ID_PROMISE_20276 0x5275 #define PCI_DEVICE_ID_PROMISE_5300 0x5300 @@ -926,6 +927,8 @@ #define PCI_VENDOR_ID_TTI 0x1103 #define PCI_DEVICE_ID_TTI_HPT343 0x0003 #define PCI_DEVICE_ID_TTI_HPT366 0x0004 +#define PCI_DEVICE_ID_TTI_HPT372 0x0005 +#define PCI_DEVICE_ID_TTI_HPT374 0x0008 #define PCI_VENDOR_ID_VIA 0x1106 #define PCI_DEVICE_ID_VIA_8363_0 0x0305 @@ -1098,12 +1101,18 @@ #define PCI_DEVICE_ID_SERVERWORKS_LE 0x0009 #define PCI_DEVICE_ID_SERVERWORKS_CIOB30 0x0010 #define PCI_DEVICE_ID_SERVERWORKS_CMIC_HE 0x0011 +#define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017 #define PCI_DEVICE_ID_SERVERWORKS_OSB4 0x0200 #define PCI_DEVICE_ID_SERVERWORKS_CSB5 0x0201 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6 0x0203 #define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211 #define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212 +#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213 #define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220 #define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB +#define PCI_DEVICE_ID_SERVERWORKS_CSB6USB 0x0221 +#define PCI_DEVICE_ID_SERVERWORKS_GCLE 0x0225 +#define PCI_DEVICE_ID_SERVERWORKS_GCLE2 0x0227 #define PCI_DEVICE_ID_SERVERWORKS_CSB5ISA 0x0230 #define PCI_VENDOR_ID_SBE 0x1176