diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-01-27 01:05:20 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-01-27 01:05:20 +0000 |
commit | 546db14ee74118296f425f3b91634fb767d67290 (patch) | |
tree | 22b613a3da8d4bf663eec5e155af01b87fdf9094 /drivers/block | |
parent | 1e25e41c4f5474e14452094492dbc169b800e4c8 (diff) |
Merge with Linux 2.3.23. The new bootmem stuff has broken various
platforms. At this time I've only verified that IP22 support compiles
and IP27 actually works.
Diffstat (limited to 'drivers/block')
31 files changed, 2033 insertions, 1405 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in index c23b8d094..7f70e32ee 100644 --- a/drivers/block/Config.in +++ b/drivers/block/Config.in @@ -62,17 +62,15 @@ else fi if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" ]; then bool ' HPT34X chipset support' CONFIG_BLK_DEV_HPT34X - if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a \ - "$CONFIG_BLK_DEV_HPT34X" = "y" ]; then - bool ' HPT34X DMA support (DANGEROUS)' CONFIG_BLK_DEV_HPT34X_DMA + if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_HPT34X" = "y" ]; then + bool ' HPT34X DMA support (EXPERIMENTAL)' CONFIG_BLK_DEV_HPT34X_DMA fi bool ' HPT366 chipset support' CONFIG_BLK_DEV_HPT366 fi if [ "$CONFIG_X86" = "y" ]; then bool ' Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX - if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a \ - "$CONFIG_BLK_DEV_PIIX" = "y" ]; then - bool ' PIIXn Tuning support (EXPERIMENTAL)' CONFIG_BLK_DEV_PIIX_TUNING + if [ "$CONFIG_BLK_DEV_PIIX" = "y" ]; then + bool ' PIIXn Tuning support' CONFIG_BLK_DEV_PIIX_TUNING fi fi if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then @@ -83,19 +81,20 @@ else fi if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" ]; then bool ' PROMISE PDC20246/PDC20262 support' CONFIG_BLK_DEV_PDC202XX - if [ "$CONFIG_EXPERIMENTAL" = "y" -a \ - "$CONFIG_BLK_DEV_PDC202XX" = "y" ]; then - bool ' Special UDMA Feature (EXPERIMENTAL)' CONFIG_PDC202XX_FORCE_BURST_BIT - bool ' Special Mode Feature (DANGEROUS)' CONFIG_PDC202XX_FORCE_MASTER_MODE + if [ "$CONFIG_BLK_DEV_PDC202XX" = "y" ]; then + bool ' Special UDMA Feature' CONFIG_PDC202XX_FORCE_BURST_BIT + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool ' Special Mode Feature (EXPERIMENTAL)' CONFIG_PDC202XX_FORCE_MASTER_MODE + fi + fi + if [ "$CONFIG_X86" = "y" ]; then + bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 fi - fi - if [ "$CONFIG_X86" = "y" ]; then - bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 fi if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 if [ "$CONFIG_X86" = "y" ]; then - bool ' VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586 + bool ' VIA82CXXX chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82CXXX fi fi fi @@ -139,8 +138,7 @@ else bool ' ALI M14xx support' CONFIG_BLK_DEV_ALI14XX bool ' DTC-2278 support' CONFIG_BLK_DEV_DTC2278 bool ' Holtek HT6560B support' CONFIG_BLK_DEV_HT6560B - if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" -a \ - "$CONFIG_EXPERIMENTAL" = "y" ]; then + if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030 fi bool ' QDI QD6580 support' CONFIG_BLK_DEV_QD6580 @@ -225,6 +223,7 @@ if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \ "$CONFIG_BLK_DEV_HPT366" = "y" -o \ "$CONFIG_BLK_DEV_IDE_PMAC" = "y" -o \ "$CONFIG_BLK_DEV_OPTI621" = "y" -o \ + "$CONFIG_BLK_DEV_PDC202XX" = "y" -o \ "$CONFIG_BLK_DEV_PIIX" = "y" -o \ "$CONFIG_BLK_DEV_SIS5513" = "y" -o \ "$CONFIG_BLK_DEV_SL82C105" = "y" ]; then diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 8519318d9..1de4fa581 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -230,8 +230,8 @@ ifeq ($(CONFIG_BLK_DEV_UMC8672),y) IDE_OBJS += umc8672.o endif -ifeq ($(CONFIG_BLK_DEV_VIA82C586),y) -IDE_OBJS += via82c586.o +ifeq ($(CONFIG_BLK_DEV_VIA82CXXX),y) +IDE_OBJS += via82cxxx.o endif ### if CONFIG_BLK_DEV_IDE is n, IDE_OBJS will be ignored @@ -379,4 +379,3 @@ ide-mod.o: ide.o $(IDE_OBJS) ide-probe-mod.o: ide-probe.o ide-geometry.o $(LD) $(LD_RFLAG) -r -o $@ ide-probe.o ide-geometry.o - diff --git a/drivers/block/aec6210.c b/drivers/block/aec6210.c index c52d8450d..75bb8657f 100644 --- a/drivers/block/aec6210.c +++ b/drivers/block/aec6210.c @@ -1,7 +1,8 @@ /* - * linux/drivers/block/aec6210.c Version 0.01 Nov 17, 1998 + * linux/drivers/block/aec6210.c Version 0.02 Sept. 3, 1999 * - * Copyright (C) 1998-99 Andre Hedrick + * Copyright (C) 1998-99 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * * pio 0 :: 40: 00 07 00 00 00 00 00 00 02 07 a6 04 00 02 00 02 * pio 1 :: 40: 0a 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02 @@ -50,6 +51,10 @@ #include <asm/io.h> #include <asm/irq.h> +/* + * TO DO: active tuning and correction of cards without a bios. + */ + unsigned int __init pci_init_aec6210 (struct pci_dev *dev, const char *name) { if (dev->resource[PCI_ROM_RESOURCE].start) { diff --git a/drivers/block/alim15x3.c b/drivers/block/alim15x3.c index b7a0a5c4f..545361052 100644 --- a/drivers/block/alim15x3.c +++ b/drivers/block/alim15x3.c @@ -1,21 +1,28 @@ /* - * linux/drivers/block/alim15x3.c Version 0.05 Jun. 29, 1999 + * linux/drivers/block/alim15x3.c Version 0.06 Sept. 3, 1999 * * Copyright (C) 1998-99 Michel Aubry, Maintainer * Copyright (C) 1998-99 Andrzej Krzysztofowicz, Maintainer - * Copyright (C) 1998-99 Andre Hedrick, Integrater and Maintainer * - * (U)DMA capable version of ali 1533/1543(C) + * Copyright (C) 1998-99 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * - * Default disable (U)DMA on all devices execpt hard disks. - * This measure of overkill is needed to stablize the chipset code. + * (U)DMA capable version of ali 1533/1543(C), 1535(D) * + * version: 1.0 beta2 (Sep. 2, 1999) + * e-mail your problems to cjtsai@ali.com.tw + * + ********************************************************************** + * 9/7/99 --Parts from the above author are included and need to be + * converted into standard interface, once I finish the thought. */ #include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/pci.h> +#include <linux/delay.h> +#include <linux/hdreg.h> #include <linux/ide.h> #include <asm/io.h> @@ -59,188 +66,7 @@ char *channel_status[8] = { "error DRQ ", "error DRQ busy" }; -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ - -static void ali15x3_tune_drive (ide_drive_t *drive, byte pio) -{ - ide_pio_data_t d; - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - int s_time, a_time, c_time; - byte s_clc, a_clc, r_clc; - unsigned long flags; - int bus_speed = ide_system_bus_speed(); - int port = hwif->index ? 0x5c : 0x58; - - pio = ide_get_best_pio_mode(drive, pio, 5, &d); - s_time = ide_pio_timings[pio].setup_time; - a_time = ide_pio_timings[pio].active_time; - if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8) - s_clc = 0; - if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8) - a_clc = 0; - c_time = ide_pio_timings[pio].cycle_time; - -#if 0 - if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16) - r_clc = 0; -#endif - if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { - r_clc = 1; - } else { - if (r_clc >= 16) - r_clc = 0; - } - save_flags(flags); - cli(); - 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); - - /* - * setup active rec - * { 70, 165, 365 }, PIO Mode 0 - * { 50, 125, 208 }, PIO Mode 1 - * { 30, 100, 110 }, PIO Mode 2 - * { 30, 80, 70 }, PIO Mode 3 with IORDY - * { 25, 70, 25 }, PIO Mode 4 with IORDY ns - * { 20, 50, 30 } PIO Mode 5 with IORDY (nonstandard) - */ - -} - -unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name) -{ - byte confreg0 = 0, confreg1 =0, progif = 0; - int errors = 0; - - if (pci_read_config_byte(dev, 0x50, &confreg1)) - goto veryspecialsettingserror; - if (!(confreg1 & 0x02)) - if (pci_write_config_byte(dev, 0x50, confreg1 | 0x02)) - goto veryspecialsettingserror; - - if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif)) - goto veryspecialsettingserror; - if (!(progif & 0x40)) { - /* - * The way to enable them is to set progif - * writable at 0x4Dh register, and set bit 6 - * of progif to 1: - */ - if (pci_read_config_byte(dev, 0x4d, &confreg0)) - goto veryspecialsettingserror; - if (confreg0 & 0x80) - if (pci_write_config_byte(dev, 0x4d, confreg0 & ~0x80)) - goto veryspecialsettingserror; - if (pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x40)) - goto veryspecialsettingserror; - if (confreg0 & 0x80) - if (pci_write_config_byte(dev, 0x4d, confreg0)) - errors++; - } - - if ((pci_read_config_byte(dev, PCI_CLASS_PROG, &progif)) || (!(progif & 0x40))) - goto veryspecialsettingserror; - - printk("%s: enabled read of IDE channels state (en/dis-abled) %s.\n", - name, errors ? "with Error(s)" : "Succeeded" ); - return 0; - -veryspecialsettingserror: - printk("%s: impossible to enable read of IDE channels state (en/dis-abled)!\n", name); - return 0; -} - -int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive) -{ - switch (func) { - case ide_dma_check: - if (drive->media == ide_cdrom) { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - struct hd_driveid *id = drive->id; - byte cd_dma_fifo = 0; - - pci_read_config_byte(dev, 0x53, &cd_dma_fifo); - - if (((id->field_valid & 4) || (id->field_valid & 2)) && - (id->capability & 1) && hwif->autodma) { - unsigned long dma_set_bit = hwif->dma_base + 2; -#if 0 - if (cd_dma_fifo & 0x02) - pci_write_config_byte(dev, 0x53, cd_dma_fifo & ~0x02); - pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x01); -#else - pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x01|0x02); -#endif - if (drive->select.b.unit & 0x01) { - outb(inb(dma_set_bit)|0x40, dma_set_bit); - } else { - outb(inb(dma_set_bit)|0x20, dma_set_bit); - } - } else { - if (cd_dma_fifo & 0x01) - pci_write_config_byte(dev, 0x53, cd_dma_fifo & ~0x01); - pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x02); - } - } else if (drive->media != ide_disk) { - return ide_dmaproc(ide_dma_off_quietly, drive); - } - default: - break; - } - return ide_dmaproc(func, drive); /* use standard DMA stuff */ -} - -void __init ide_init_ali15x3 (ide_hwif_t *hwif) -{ - struct pci_dev *dev; - byte ideic, inmir, iderev; - byte irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, - 1, 11, 0, 12, 0, 14, 0, 15 }; - - pci_read_config_byte(hwif->pci_dev, PCI_REVISION_ID, &iderev); - - hwif->irq = hwif->channel ? 15 : 14; - for (dev = pci_devices; dev; dev=dev->next) /* look for ISA bridge */ - if (dev->vendor==PCI_VENDOR_ID_AL && - dev->device==PCI_DEVICE_ID_AL_M1533) - break; - if (dev) { - pci_read_config_byte(dev, 0x58, &ideic); - ideic = ideic & 0x03; - if ((hwif->channel && ideic == 0x03) || - (!hwif->channel && !ideic)) { - pci_read_config_byte(dev, 0x44, &inmir); - inmir = inmir & 0x0f; - hwif->irq = irq_routing_table[inmir]; - } else - if (hwif->channel && !(ideic & 0x01)) { - pci_read_config_byte(dev, 0x75, &inmir); - inmir = inmir & 0x0f; - hwif->irq = irq_routing_table[inmir]; - } - } -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) - bmide_dev = hwif->pci_dev; - ali_display_info = &ali_get_info; -#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ - - hwif->tuneproc = &ali15x3_tune_drive; - if ((hwif->dma_base) && (iderev >= 0xC1)) { - /* M1543C or newer for DMAing */ - hwif->dmaproc = &ali15x3_dmaproc; - } else { - hwif->autodma = 0; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - } - return; -} - -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int dummy) { byte reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1; @@ -407,3 +233,540 @@ static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int return p-buffer; /* => must be less than 4k! */ } #endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ + +static byte m5229_revision = 0; +static byte chip_is_1543c_e = 0; +static byte cable_80_pin[2] = { 0, 0 }; + +byte ali_proc = 0; +static struct pci_dev *isa_dev; + +static void ali15x3_tune_drive (ide_drive_t *drive, byte pio) +{ + ide_pio_data_t d; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + int s_time, a_time, c_time; + byte s_clc, a_clc, r_clc; + unsigned long flags; + int bus_speed = ide_system_bus_speed(); + int port = hwif->index ? 0x5c : 0x58; + + pio = ide_get_best_pio_mode(drive, pio, 5, &d); + s_time = ide_pio_timings[pio].setup_time; + a_time = ide_pio_timings[pio].active_time; + if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8) + s_clc = 0; + if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8) + a_clc = 0; + c_time = ide_pio_timings[pio].cycle_time; + +#if 0 + if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16) + r_clc = 0; +#endif + + if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { + r_clc = 1; + } else { + if (r_clc >= 16) + r_clc = 0; + } + save_flags(flags); + cli(); + 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); + + /* + * setup active rec + * { 70, 165, 365 }, PIO Mode 0 + * { 50, 125, 208 }, PIO Mode 1 + * { 30, 100, 110 }, PIO Mode 2 + * { 30, 80, 70 }, PIO Mode 3 with IORDY + * { 25, 70, 25 }, PIO Mode 4 with IORDY ns + * { 20, 50, 30 } PIO Mode 5 with IORDY (nonstandard) + */ + +} + +static __inline__ unsigned char dma2_bits_to_command(unsigned char bits) +{ + if (bits & 0x04) + return XFER_MW_DMA_2; + if (bits & 0x02) + return XFER_MW_DMA_1; + return XFER_MW_DMA_0; +} + +static __inline__ unsigned char udma2_bits_to_command(unsigned char bits) +{ + if (bits & 0x10) + return XFER_UDMA_4; + if (bits & 0x08) + return XFER_UDMA_3; + if (bits & 0x04) + return XFER_UDMA_2; + if (bits & 0x02) + return XFER_UDMA_1; + return XFER_UDMA_0; +} + +static __inline__ int wait_for_ready(ide_drive_t *drive) +{ + int timeout = 20000; /* (old value: 100) */ + byte stat; + + while (--timeout) { + stat = GET_STAT(); + /* + * printk("STAT(%2x) ", stat); + */ + if (!(stat & BUSY_STAT)) { + if ((stat & READY_STAT) || (stat & ERR_STAT)) { + break; + } + } + /* + * (old value: 100) + */ + udelay(150); + } + if ((stat & ERR_STAT) || timeout <= 0) + return 1; + return 0; +} + +static void ali15x3_do_setfeature(ide_drive_t *drive, byte command) +{ + unsigned long flags; + byte old_select; + + save_flags(flags); + cli(); + + /* save old selected device */ + old_select = IN_BYTE(IDE_SELECT_REG); + /* "SELECT " */ + OUT_BYTE(drive->select.all, IDE_SELECT_REG); + /* "SETXFER " */ + OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); + /* "CMND " */ + OUT_BYTE(command, IDE_NSECTOR_REG); + + if(wait_for_ready(drive)) /* "wait " */ + goto out; + + /* "SETFEATURE " */ + OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); + /* "wait " */ + (void) wait_for_ready(drive); + +out: + /* + * restore to old "selected device" + */ + OUT_BYTE(old_select, IDE_SELECT_REG); + restore_flags(flags); +} + +static void ali15x3_dma2_enable(ide_drive_t *drive, unsigned long dma_base) +{ + byte unit = (drive->select.b.unit & 0x01); + byte bits = (drive->id->dma_mword | drive->id->dma_1word) & 0x07; + byte tmpbyte; + ide_hwif_t *hwif = HWIF(drive); + unsigned long flags; + int m5229_udma_setting_index = hwif->channel? 0x57 : 0x56; + + ali15x3_do_setfeature(drive, dma2_bits_to_command(bits)); + + /* + * clear "ultra enable" bit + */ + pci_read_config_byte(hwif->pci_dev, m5229_udma_setting_index, &tmpbyte); + if (unit) { + tmpbyte &= 0x7f; + } else { + tmpbyte &= 0xf7; + } + save_flags(flags); + cli(); + pci_write_config_byte(hwif->pci_dev, m5229_udma_setting_index, tmpbyte); + restore_flags(flags); + drive->id->dma_ultra = 0x00; + + /* + * Enable DMA + */ + outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); + printk("ALI15X3: MultiWord DMA enabled\n"); +} + +static void ali15x3_udma_enable(ide_drive_t *drive, unsigned long dma_base) +{ + byte unit = (drive->select.b.unit & 0x01); + byte bits = drive->id->dma_ultra & 0x1f; + byte tmpbyte; + ide_hwif_t *hwif = HWIF(drive); + unsigned long flags; + unsigned char udma_mode = 0; + int m5229_udma_setting_index = hwif->channel? 0x57 : 0x56; + + if (bits & 0x18) { + /* + * 00011000, disk: ultra66 + */ + if (m5229_revision < 0xc2) { + /* + * controller: ultra33 + */ + bits = 0x04; + /* + * 00000100, use ultra33, mode 2 + */ + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0004; + } else { + /* + * controller: ultra66 + * + * Try to detect word93 bit13 and + * 80-pin cable (from host view) + */ + if (!((drive->id->word93 & 0x2000) && + cable_80_pin[hwif->channel])) { + bits = 0x04; + /* + * 00000100, use ultra33, mode 2 + */ + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0004; + } + } + } + + /* + * set feature regardless + */ + ali15x3_do_setfeature(drive, udma_mode = udma2_bits_to_command(bits)); + udma_mode &= 0x0f; /* get UDMA mode */ + + /* + * Enable DMA and UltraDMA + */ + outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); + /* + * m5229 ultra + */ + pci_read_config_byte(hwif->pci_dev, m5229_udma_setting_index, &tmpbyte); + /* + * clear bit0~3 or bit 4~7 + */ + tmpbyte &= (0x0f << ((1-unit) << 2)); + /* + * enable ultra dma and set timing + */ + tmpbyte |= ((0x08 | (4-udma_mode)) << (unit << 2)); + /* + * set to m5229 + */ + save_flags(flags); + cli(); + pci_write_config_byte(hwif->pci_dev, m5229_udma_setting_index, tmpbyte); + restore_flags(flags); + + if (udma_mode >= 3) { + /* + * ultra 66 + */ + pci_read_config_byte(hwif->pci_dev, 0x4b, &tmpbyte); + tmpbyte |= 1; + save_flags(flags); + cli(); + pci_write_config_byte(hwif->pci_dev, 0x4b, tmpbyte); + restore_flags(flags); + } + + printk("ALI15X3: Ultra DMA enabled\n"); +} + +static int ali15x3_dma_onoff(ide_drive_t *drive, int enable) +{ + if (enable) { + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + struct hd_driveid *id = drive->id; + + if ((id->field_valid & 0x0004) && + (id->dma_ultra & 0x001f)) { + /* + * 1543C_E, in ultra mode, WDC "harddisk" + * will cause "CRC" errors (even if no CRC problem), + * so we try to use "DMA" here + */ + if (m5229_revision <= 0x20) { + /* + * Normal MultiWord DMA modes. + */ + ali15x3_dma2_enable(drive, dma_base); + } else if ((m5229_revision < 0xC2) && + ((drive->media!=ide_disk) || + (chip_is_1543c_e && + strstr(id->model, "WDC ")))) { + /* + * Normal MultiWord DMA modes. + */ + ali15x3_dma2_enable(drive, dma_base); + } else { + /* + * m5229_revision >= 0xC2 for UltraDMA modes. + */ + ali15x3_udma_enable(drive, dma_base); + } + } else { + /* + * Normal MultiWord DMA modes. + */ + ali15x3_dma2_enable(drive, dma_base); + } + } + + drive->using_dma = enable; /* on, off */ + return 0; +} + +static int ali15x3_config_drive_for_dma(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + + if ((m5229_revision<=0x20) && (drive->media!=ide_disk)) + return hwif->dmaproc(ide_dma_off_quietly, drive); + /* + * Even if the drive is not _currently_ in a DMA + * mode, we succeed, and we'll enable it manually + * below in alim15x3_dma_onoff + */ + if ((id != NULL) && (id->capability & 1) && hwif->autodma) { + if (id->field_valid & 0x0004) { + if (id->dma_ultra & 0x001F) + return hwif->dmaproc(ide_dma_on, drive); + } + if (id->field_valid & 0x0002) { + if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007)) + return hwif->dmaproc(ide_dma_on, drive); + } + } + return hwif->dmaproc(ide_dma_off_quietly, drive); +} + +static int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive) +{ + switch(func) { + case ide_dma_check: + return ali15x3_config_drive_for_dma(drive); + case ide_dma_on: + case ide_dma_off: + case ide_dma_off_quietly: + return ali15x3_dma_onoff(drive, (func == ide_dma_on)); + case ide_dma_write: + if ((m5229_revision < 0xC2) && (drive->media != ide_disk)) + return 1; /* try PIO instead of DMA */ + break; + default: + break; + } + + return ide_dmaproc(func, drive); /* use standard DMA stuff */ +} + +unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name) +{ + struct pci_dev *isa; + unsigned long fixdma_base = dev->resource[4].start; + byte tmpbyte; + + pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision); + + for (isa = pci_devices; isa; isa=isa->next) { + /* + * look for ISA bridge + */ + if (isa->vendor == PCI_VENDOR_ID_AL && + isa->device == PCI_DEVICE_ID_AL_M1533) { + isa_dev = isa; + break; + } + } + + if (!fixdma_base || fixdma_base == PCI_BASE_ADDRESS_IO_MASK) { + /* + * + */ + } else { + /* + * enable DMA capable bit, and "not" simplex only + */ + outb(inb(fixdma_base+2) & 0x60, fixdma_base+2); + + if (inb(fixdma_base+2) & 0x80) + printk("%s: simplex device: DMA will fail!!\n", name); + } + + /* + * FIXME !!! This detection needs to be in "ata66_ali15x3()" + * below as a standard detection return. + */ + + if (m5229_revision >= 0xC2) { + unsigned long flags; + /* + * 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 + */ + save_flags(flags); + cli(); + + /* + * 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); + } + restore_flags(flags); + /* + * Ultra66 cable detection (from Host View) + * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin + */ + pci_read_config_byte(dev, 0x4a, &tmpbyte); + /* + * 0x4a, bit0 is 0 => primary channel + * has 80-pin (from host view) + */ + if (!(tmpbyte & 0x01)) + cable_80_pin[0] = 1; + /* + * 0x4a, bit1 is 0 => secondary channel + * has 80-pin (from host view) + */ + if (!(tmpbyte & 0x02)) + cable_80_pin[1] = 1; + } else { + unsigned long flags; + /* + * 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); + save_flags(flags); + cli(); + /* + * clear bit 7 + */ + pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); + restore_flags(flags); + + /* + * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010 + */ + pci_read_config_byte(isa_dev, 0x5e, &tmpbyte); + chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0; + } + + return 0; +} + +unsigned int __init ata66_ali15x3 (ide_hwif_t *hwif) +{ + /* + * FIXME !!!! + * {0x4a,0x01,0x01}, {0x4a,0x02,0x02} + */ + return 0; +} + +void __init ide_init_ali15x3 (ide_hwif_t *hwif) +{ + byte ideic, inmir; + byte irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, + 1, 11, 0, 12, 0, 14, 0, 15 }; + + hwif->irq = hwif->channel ? 15 : 14; + + if (isa_dev) { + /* + * read IDE interface control + */ + pci_read_config_byte(isa_dev, 0x58, &ideic); + + /* bit0, bit1 */ + ideic = ideic & 0x03; + + /* get IRQ for IDE Controller */ + if ((hwif->channel && ideic == 0x03) || + (!hwif->channel && !ideic)) { + /* + * get SIRQ1 routing table + */ + pci_read_config_byte(isa_dev, 0x44, &inmir); + inmir = inmir & 0x0f; + hwif->irq = irq_routing_table[inmir]; + } else if (hwif->channel && !(ideic & 0x01)) { + /* + * get SIRQ2 routing table + */ + pci_read_config_byte(isa_dev, 0x75, &inmir); + inmir = inmir & 0x0f; + hwif->irq = irq_routing_table[inmir]; + } + } + + hwif->tuneproc = &ali15x3_tune_drive; + if ((hwif->dma_base) && (m5229_revision >= 0xC1)) { + /* + * M1543C or newer for DMAing + */ + hwif->dmaproc = &ali15x3_dmaproc; + hwif->autodma = 1; + } else { + hwif->autodma = 0; + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + } + +#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) + ali_proc = 1; + bmide_dev = hwif->pci_dev; + ali_display_info = &ali_get_info; +#endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ + + return; +} + +void ide_dmacapable_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) +{ + if ((dmabase) && (m5229_revision < 0x20)) { + return; + } + ide_setup_dma(hwif, dmabase, 8); +} diff --git a/drivers/block/cy82c693.c b/drivers/block/cy82c693.c index e204bc0e6..77fdf0821 100644 --- a/drivers/block/cy82c693.c +++ b/drivers/block/cy82c693.c @@ -1,8 +1,8 @@ /* - * linux/drivers/block/cy82c693.c Version 0.33 Jan. 23, 1999 + * linux/drivers/block/cy82c693.c Version 0.34 Sept 3, 1999 * - * Copyright (C) 1998, 1999 Andreas S. Krebs (akrebs@altavista.net), Maintainer - * Copyright (C) 1998 Andre Hedrick, Integrater + * Copyright (C) 1998-99 Andreas S. Krebs (akrebs@altavista.net), Maintainer + * Copyright (C) 1998-99 Andre Hedrick, Integrater * * CYPRESS CY82C693 chipset IDE controller * @@ -31,6 +31,7 @@ * * * History: + * AMH@1999-08-24: v0.34 init_cy82c693_chip moved to pci_init_cy82c693 * ASK@1999-01-23: v0.33 made a few minor code clean ups * removed DMA clock speed setting by default * added boot message @@ -53,7 +54,7 @@ #include "ide_modes.h" /* the current version */ -#define CY82_VERSION "CY82C693U driver v0.33 99-01-23 Andreas S. Krebs (akrebs@altavista.net)" +#define CY82_VERSION "CY82C693U driver v0.34 99-09-03 Andreas S. Krebs (akrebs@altavista.net)" /* * The following are used to debug the driver. @@ -377,20 +378,10 @@ static void cy82c693_tune_drive (ide_drive_t *drive, byte pio) unsigned int __init pci_init_cy82c693(struct pci_dev *dev, const char *name) { - return 0; -} - -static void init_cy82c693_chip (struct pci_dev *dev) -{ - static int initDone = 0; #ifdef CY82C693_SETDMA_CLOCK byte data; #endif /* CY82C693_SETDMA_CLOCK */ - if (initDone != 0) /* only perform setup once */ - return; - initDone = 1; - /* write info about this verion of the driver */ printk (KERN_INFO CY82_VERSION "\n"); @@ -401,7 +392,7 @@ static void init_cy82c693_chip (struct pci_dev *dev) data = IN_BYTE(CY82_DATA_PORT); #if CY82C693_DEBUG_INFO - printk (KERN_INFO "CY82U693: Peripheral Configuration Register: 0x%X\n", data); + printk (KERN_INFO "%s: Peripheral Configuration Register: 0x%X\n", name, data); #endif /* CY82C693_DEBUG_INFO */ /* @@ -422,10 +413,11 @@ static void init_cy82c693_chip (struct pci_dev *dev) OUT_BYTE(data, CY82_DATA_PORT); #if CY82C693_DEBUG_INFO - printk (KERN_INFO "CY82U693: New Peripheral Configuration Register: 0x%X\n", data); + printk (KERN_INFO "%s: New Peripheral Configuration Register: 0x%X\n", name, data); #endif /* CY82C693_DEBUG_INFO */ -#endif /* CY82C693_SETDMA_CLOCK */ +#endif /* CY82C693_SETDMA_CLOCK */ + return 0; } /* @@ -437,7 +429,5 @@ void __init ide_init_cy82c693(ide_hwif_t *hwif) if (hwif->dma_base) hwif->dmaproc = &cy82c693_dmaproc; hwif->tuneproc = &cy82c693_tune_drive; - - init_cy82c693_chip(hwif->pci_dev); } diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index aece0447d..3c9a35b97 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -26,6 +26,8 @@ extern int net_dev_init(void); extern void console_map_init(void); extern int soc_probe(void); extern int atmdev_init(void); +extern int i2o_init(void); +extern int cpqarray_init(void); void __init device_init(void) { diff --git a/drivers/block/hpt34x.c b/drivers/block/hpt34x.c index 284bf40bc..816b4b805 100644 --- a/drivers/block/hpt34x.c +++ b/drivers/block/hpt34x.c @@ -1,7 +1,9 @@ /* - * linux/drivers/block/hpt34x.c Version 0.25 July 11, 1999 + * linux/drivers/block/hpt34x.c Version 0.27 Sept 03, 1999 + * + * Copyright (C) 1998-99 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * - * Copyright (C) 1998-99 Andre Hedrick * * 00:12.0 Unknown mass storage controller: * Triones Technologies, Inc. @@ -14,9 +16,6 @@ * hdg: DMA 1 (0x0012 0x0052) (0x0030 0x0070) * hdh: DMA 1 (0x0052 0x0252) (0x0070 0x00f0) * - * drive_number - * = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); */ #include <linux/config.h> @@ -58,7 +57,7 @@ static void hpt34x_clear_chipset (ide_drive_t *drive) pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, ®1); pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, ®2); tmp1 = ((0x00 << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number)))); - tmp2 = ((0x00 << drive_number) | reg2); + tmp2 = (reg2 & ~(0x11 << drive_number)); pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1); pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2); } @@ -105,7 +104,7 @@ static int hpt34x_tune_chipset (ide_drive_t *drive, byte speed) * after the drive is reported by the OS. Initally for designed for * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc. */ -static int config_chipset_for_dma (ide_drive_t *drive) +static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) { struct hd_driveid *id = drive->id; byte speed = 0x00; @@ -117,76 +116,29 @@ static int config_chipset_for_dma (ide_drive_t *drive) return ((int) ide_dma_off_quietly); #endif /* HPT343_DISABLE_ALL_DMAING */ - if (id->dma_ultra & 0x0010) { - goto backspeed; - } else if (id->dma_ultra & 0x0008) { - goto backspeed; - } else if (id->dma_ultra & 0x0004) { -backspeed: - if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } + hpt34x_clear_chipset(drive); + + if ((id->dma_ultra & 0x0010) && ultra) { speed = XFER_UDMA_2; - } else if (id->dma_ultra & 0x0002) { - if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } + } else if ((id->dma_ultra & 0x0008) && ultra) { + speed = XFER_UDMA_2; + } 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) { - if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } + } else if ((id->dma_ultra & 0x0001) && ultra) { speed = XFER_UDMA_0; } else if (id->dma_mword & 0x0004) { - if (!((id->dma_mword >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0404; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_2; } else if (id->dma_mword & 0x0002) { - if (!((id->dma_mword >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0202; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_1; } else if (id->dma_mword & 0x0001) { - if (!((id->dma_mword >> 8) & 1)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0101; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_0; } else if (id->dma_1word & 0x0004) { - if (!((id->dma_1word >> 8) & 4)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_2; } else if (id->dma_1word & 0x0002) { - if (!((id->dma_1word >> 8) & 2)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_1; } else if (id->dma_1word & 0x0001) { - if (!((id->dma_1word >> 8) & 1)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_0; } else { return ((int) ide_dma_off_quietly); @@ -242,7 +194,6 @@ static void hpt34x_tune_drive (ide_drive_t *drive, byte pio) { byte speed; - hpt34x_clear_chipset(drive); switch(pio) { case 4: speed = XFER_PIO_4;break; case 3: speed = XFER_PIO_3;break; @@ -250,6 +201,7 @@ static void hpt34x_tune_drive (ide_drive_t *drive, byte pio) case 1: speed = XFER_PIO_1;break; default: speed = XFER_PIO_0;break; } + hpt34x_clear_chipset(drive); (void) hpt34x_tune_chipset(drive, speed); } @@ -268,7 +220,7 @@ static int config_drive_xfer_rate (ide_drive_t *drive) if (id->field_valid & 4) { if (id->dma_ultra & 0x0007) { /* Force if Capable UltraDMA */ - dma_func = config_chipset_for_dma(drive); + dma_func = config_chipset_for_dma(drive, 1); if ((id->field_valid & 2) && (dma_func != ide_dma_on)) goto try_dma_modes; @@ -278,7 +230,7 @@ try_dma_modes: if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007)) { /* Force if Capable regular DMA modes */ - dma_func = config_chipset_for_dma(drive); + dma_func = config_chipset_for_dma(drive, 0); if (dma_func != ide_dma_on) goto no_dma_set; } @@ -287,7 +239,7 @@ try_dma_modes: goto no_dma_set; } /* Consult the list of known "good" drives */ - dma_func = config_chipset_for_dma(drive); + dma_func = config_chipset_for_dma(drive, 0); if (dma_func != ide_dma_on) goto no_dma_set; } else { @@ -300,6 +252,12 @@ no_dma_set: config_chipset_for_pio(drive); } + +#if 0 + if (dma_func == ide_dma_on) + dma_func = ide_dma_off; +#endif + return HWIF(drive)->dmaproc(dma_func, drive); } @@ -313,22 +271,44 @@ no_dma_set: int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { + ide_hwif_t *hwif = HWIF(drive); + unsigned long dma_base = hwif->dma_base; + byte unit = (drive->select.b.unit & 0x01); + unsigned int count, reading = 0; + byte dma_stat; + switch (func) { - case ide_dma_check: - hpt34x_clear_chipset(drive); - return config_drive_xfer_rate(drive); -#if 0 case ide_dma_off: case ide_dma_off_quietly: + outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); + break; case ide_dma_on: + outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); + break; case ide_dma_check: return config_drive_xfer_rate(drive); case ide_dma_read: + reading = 1 << 3; case ide_dma_write: - case ide_dma_begin: - case ide_dma_end: - case ide_dma_test_irq: -#endif + if (!(count = ide_build_dmatable(drive, func))) + return 1; /* try PIO instead of DMA */ + outl(virt_to_bus(hwif->dmatable), dma_base + 4); /* PRD table */ + reading |= 0x01; + outb(reading, dma_base); /* specify r/w */ + outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ + drive->waiting_for_dma = 1; + if (drive->media != ide_disk) + return 0; + drive->timeout = WAIT_CMD; + ide_set_handler(drive, &ide_dma_intr); /* issue cmd to drive */ + OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); + 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 */ + return (dma_stat & 7) != 4; /* verify good DMA status */ default: break; } @@ -342,10 +322,17 @@ int hpt34x_dmaproc (ide_dma_action_t func, ide_drive_t *drive) unsigned int __init pci_init_hpt34x (struct pci_dev *dev, const char *name) { + int i = 0; + unsigned long hpt34xIoBase = dev->resource[4].start; unsigned short cmd; + unsigned long flags; + + __save_flags(flags); /* local CPU only */ + __cli(); /* local CPU only */ pci_write_config_byte(dev, HPT34X_PCI_INIT_REG, 0x00); pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (cmd & PCI_COMMAND_MEMORY) { if (dev->resource[PCI_ROM_RESOURCE].start) { pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); @@ -353,27 +340,28 @@ unsigned int __init pci_init_hpt34x (struct pci_dev *dev, const char *name) } pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); } else { - int i = 0; - unsigned long hpt34xIoBase = dev->resource[4].start; - - pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); - dev->resource[0].start = (hpt34xIoBase + 0x20); - dev->resource[1].start = (hpt34xIoBase + 0x34); - dev->resource[2].start = (hpt34xIoBase + 0x28); - dev->resource[3].start = (hpt34xIoBase + 0x3c); - for(i=0; i<4; i++) - dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; - /* - * Since 20-23 can be assigned and are R/W, we correct them. - */ - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->resource[0].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->resource[1].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->resource[2].start); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->resource[3].start); - - pci_write_config_word(dev, PCI_COMMAND, cmd); pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); } + + pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO); + dev->resource[0].start = (hpt34xIoBase + 0x20); + dev->resource[1].start = (hpt34xIoBase + 0x34); + dev->resource[2].start = (hpt34xIoBase + 0x28); + dev->resource[3].start = (hpt34xIoBase + 0x3c); + for(i=0; i<4; i++) + dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; + /* + * Since 20-23 can be assigned and are R/W, we correct them. + */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->resource[0].start); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->resource[1].start); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->resource[2].start); + 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 */ + return dev->irq; } diff --git a/drivers/block/hpt366.c b/drivers/block/hpt366.c index b61f71687..d45b5f719 100644 --- a/drivers/block/hpt366.c +++ b/drivers/block/hpt366.c @@ -1,11 +1,13 @@ /* - * linux/drivers/block/hpt366.c Version 0.12 August 16, 1999 + * linux/drivers/block/hpt366.c Version 0.13 Sept. 3, 1999 * * Copyright (C) 1999 Andre Hedrick <andre@suse.com> + * May be copied or modified under the terms of the GNU General Public License * - * drive_number - * = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + * Thanks to HighPoint Technologies for their assistance, and hardware. + * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his + * donation of an ABit BP6 mainboard, processor, and memory acellerated + * development and support. */ #include <linux/types.h> @@ -114,17 +116,18 @@ struct chipset_bus_clock_list_entry twenty_five_base [] = { }; #define HPT366_DEBUG_DRIVE_INFO 0 -#define HPT366_ALLOW_ATA66_4 0 +#define HPT366_ALLOW_ATA66_4 1 #define HPT366_ALLOW_ATA66_3 1 -#define HPT366_ALLOW_ATA33_2 1 -#define HPT366_ALLOW_ATA33_1 1 -#define HPT366_ALLOW_ATA33_0 1 extern char *ide_xfer_verbose (byte xfer_rate); +byte hpt363_shared_irq = 0; static int check_in_drive_lists (ide_drive_t *drive, const char **list) { struct hd_driveid *id = drive->id; +#if HPT366_DEBUG_DRIVE_INFO + printk("check_in_drive_lists(%s, %p)\n", drive->name, list); +#endif /* HPT366_DEBUG_DRIVE_INFO */ while (*list) { if (!strcmp(*list++,id->model)) { @@ -139,50 +142,62 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) static unsigned int pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) { +#if HPT366_DEBUG_DRIVE_INFO + printk("pci_bus_clock_list(speed=0x%02x, table=%p)\n", speed, chipset_table); +#endif /* HPT366_DEBUG_DRIVE_INFO */ for ( ; chipset_table->xfer_speed ; chipset_table++) - if (chipset_table->xfer_speed == speed) + if (chipset_table->xfer_speed == speed) { +#if HPT366_DEBUG_DRIVE_INFO + printk("pci_bus_clock_list: found match: 0x%08x\n", chipset_table->chipset_settings); +#endif /* HPT366_DEBUG_DRIVE_INFO */ return chipset_table->chipset_settings; + } +#if HPT366_DEBUG_DRIVE_INFO + printk("pci_bus_clock_list: using default: 0x%08x\n", 0x01208585); +#endif /* HPT366_DEBUG_DRIVE_INFO */ return 0x01208585; } static int hpt366_tune_chipset (ide_drive_t *drive, byte speed) { int err; - byte busclock; - #if HPT366_DEBUG_DRIVE_INFO int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); #endif /* HPT366_DEBUG_DRIVE_INFO */ - byte regtime = (drive->select.b.unit & 0x01) ? 0x43 : 0x40; + byte regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; unsigned int reg1 = 0; unsigned int reg2 = 0; +#if HPT366_DEBUG_DRIVE_INFO + printk("hpt366_tune_chipset(%s, speed=0x%02x)\n", drive->name, speed); +#endif /* HPT366_DEBUG_DRIVE_INFO */ + pci_read_config_dword(HWIF(drive)->pci_dev, regtime, ®1); - pci_read_config_byte(HWIF(drive)->pci_dev, regtime|0x01, &busclock); - switch(busclock) { - case 0xd9: + /* 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 0x85: + case 9: reg2 = pci_bus_clock_list(speed, twenty_five_base); break; - case 0xa7: default: + printk("hpt366: assuming 33Mhz PCI bus\n"); + case 7: reg2 = pci_bus_clock_list(speed, thirty_three_base); break; } - - if (drive->id->dword_io & 1) - reg2 |= 0x80000000; - else - reg2 &= ~0x80000000; + /* + * Disable on-chip PIO FIFO/buffer (to avoid problems handling I/O errors later) + */ + reg2 &= ~0x80000000; pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2); err = ide_config_drive_speed(drive, speed); #if HPT366_DEBUG_DRIVE_INFO - printk("%s: %s drive%d (0x%08x 0x%08x) 0x%04x\n", - drive->name, ide_xfer_verbose(speed), + printk("%s: speed=0x%02x(%s), drive%d, old=0x%08x, new=0x%08x, err=0x%04x\n", + drive->name, speed, ide_xfer_verbose(speed), drive_number, reg1, reg2, err); #endif /* HPT366_DEBUG_DRIVE_INFO */ return(err); @@ -203,127 +218,89 @@ static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; byte speed = 0x00; + unsigned int reg40 = 0; + int rval; if ((id->dma_ultra & 0x0010) && (!check_in_drive_lists(drive, bad_ata66_4)) && (HPT366_ALLOW_ATA66_4) && (HWIF(drive)->udma_four)) { - if (!((id->dma_ultra >> 8) & 16)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x1010; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_UDMA_4; } else if ((id->dma_ultra & 0x0008) && (!check_in_drive_lists(drive, bad_ata66_3)) && (HPT366_ALLOW_ATA66_3) && (HWIF(drive)->udma_four)) { - if (!((id->dma_ultra >> 8) & 8)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0808; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_UDMA_3; - } else if ((id->dma_ultra & 0x0004) && - (HPT366_ALLOW_ATA33_2) && - (!check_in_drive_lists(drive, bad_ata33))) { - if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && - (HPT366_ALLOW_ATA33_1) && - (!check_in_drive_lists(drive, bad_ata33))) { - if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; + } else if (id->dma_ultra && (!check_in_drive_lists(drive, bad_ata33))) { + 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; } - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && - (HPT366_ALLOW_ATA33_0) && - (!check_in_drive_lists(drive, bad_ata33))) { - if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } - speed = XFER_UDMA_0; } else if (id->dma_mword & 0x0004) { - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_mword >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0404; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_2; } else if (id->dma_mword & 0x0002) { - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_mword >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0202; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_1; } else if (id->dma_mword & 0x0001) { - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_mword >> 8) & 1)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0101; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_0; } else if (id->dma_1word & 0x0004) { - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_1word >> 8) & 4)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_2; } else if (id->dma_1word & 0x0002) { - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_1word >> 8) & 2)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_1; } else if (id->dma_1word & 0x0001) { - drive->id->dma_ultra &= ~0xFF00; - if (!((id->dma_1word >> 8) & 1)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_0; } else { +#if HPT366_DEBUG_DRIVE_INFO + printk("%s: config_chipset_for_dma: returning 'ide_dma_off_quietly'\n", drive->name); +#endif /* HPT366_DEBUG_DRIVE_INFO */ return ((int) ide_dma_off_quietly); } + /* Disable the "fast interrupt" prediction. + * Instead, always wait for the real interrupt from the drive! + */ + { + byte reg51h = 0; + pci_read_config_byte(HWIF(drive)->pci_dev, 0x51, ®51h); + if (reg51h & 0x80) + pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h & ~0x80); + } + + /* + * Preserve existing PIO settings: + */ + pci_read_config_dword(HWIF(drive)->pci_dev, 0x40, ®40); + speed = (speed & ~0xc0000000) | (reg40 & 0xc0000000); + +#if HPT366_DEBUG_DRIVE_INFO + printk("%s: config_chipset_for_dma: speed=0x%04x\n", drive->name, speed); +#endif /* HPT366_DEBUG_DRIVE_INFO */ (void) hpt366_tune_chipset(drive, speed); - return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : + rval = (int)( ((id->dma_ultra >> 11) & 3) ? 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); + +#if HPT366_DEBUG_DRIVE_INFO + printk("%s: config_chipset_for_dma: returning %d (%s)\n", drive->name, rval, rval == ide_dma_on ? "dma_on" : "dma_off"); +#endif /* HPT366_DEBUG_DRIVE_INFO */ + return rval; } static void config_chipset_for_pio (ide_drive_t *drive) { unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; unsigned short xfer_pio = drive->id->eide_pio_modes; - byte timing, speed, pio; + unsigned int reg40 = 0; +#if HPT366_DEBUG_DRIVE_INFO + printk("%s: config_chipset_for_pio\n", drive->name); +#endif /* HPT366_DEBUG_DRIVE_INFO */ pio = ide_get_best_pio_mode(drive, 255, 5, NULL); if (xfer_pio> 4) @@ -353,6 +330,14 @@ static void config_chipset_for_pio (ide_drive_t *drive) speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; break; } + /* + * Preserve existing DMA settings: + */ + pci_read_config_dword(HWIF(drive)->pci_dev, 0x40, ®40); + speed = (speed & ~0x30070000) | (reg40 & 0x30070000); +#if HPT366_DEBUG_DRIVE_INFO + printk("%s: config_chipset_for_pio: speed=0x%04x\n", drive->name, speed); +#endif /* HPT366_DEBUG_DRIVE_INFO */ (void) hpt366_tune_chipset(drive, speed); } @@ -428,8 +413,9 @@ no_dma_set: int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive) { +#if 0 byte reg50h = 0, reg52h = 0; - +#endif switch (func) { case ide_dma_check: return config_drive_xfer_rate(drive); @@ -463,28 +449,81 @@ int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive) unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name) { - byte ata66 = 0; + byte test = 0; - pci_read_config_byte(dev, 0x5a, &ata66); if (dev->resource[PCI_ROM_RESOURCE].start) pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); - printk("%s: reg5ah=0x%02x ATA-%s Cable Port%d\n", name, ata66, (ata66 & 0x02) ? "33" : "66", PCI_FUNC(dev->devfn)); + + pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test); + if (test != 0x08) + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x08); + + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test); + if (test != 0x78) + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); + + pci_read_config_byte(dev, PCI_MIN_GNT, &test); + if (test != 0x08) + pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); + + pci_read_config_byte(dev, PCI_MAX_LAT, &test); + if (test != 0x08) + pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); + return dev->irq; } +unsigned int __init ata66_hpt366 (ide_hwif_t *hwif) +{ + byte ata66 = 0; + + pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66); +#ifdef DEBUG + printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n", + ata66, (ata66 & 0x02) ? "33" : "66", + PCI_FUNC(hwif->pci_dev->devfn)); +#endif /* DEBUG */ + return ((ata66 & 0x02) ? 0 : 1); +} + void __init ide_init_hpt366 (ide_hwif_t *hwif) { +#if 0 + if ((PCI_FUNC(hwif->pci_dev->devfn) & 1) && (hpt363_shared_irq)) { + hwif->mate = &ide_hwifs[hwif->index-1]; + hwif->mate->mate = hwif; + hwif->serialized = hwif->mate->serialized = 1; + } +#endif + hwif->tuneproc = &hpt366_tune_drive; if (hwif->dma_base) { - byte ata66 = 0; - hwif->dmaproc = &hpt366_dmaproc; - pci_read_config_byte(hwif->pci_dev, 0x5a, &ata66); - hwif->udma_four = (ata66 & 0x02) ? 0 : 1; } else { - hwif->udma_four = 0; hwif->autodma = 0; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; } } + +void ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase) +{ + byte masterdma = 0, slavedma = 0; + byte dma_new = 0, dma_old = inb(dmabase+2); + unsigned long flags; + + __save_flags(flags); /* local CPU only */ + __cli(); /* local CPU only */ + + dma_new = dma_old; + pci_read_config_byte(hwif->pci_dev, 0x43, &masterdma); + pci_read_config_byte(hwif->pci_dev, 0x47, &slavedma); + + if (masterdma & 0x30) dma_new |= 0x20; + if (slavedma & 0x30) dma_new |= 0x40; + if (dma_new != dma_old) outb(dma_new, dmabase+2); + + __restore_flags(flags); /* local CPU only */ + + ide_setup_dma(hwif, dmabase, 8); +} diff --git a/drivers/block/icside.c b/drivers/block/icside.c index 629ad927d..5d007fce3 100644 --- a/drivers/block/icside.c +++ b/drivers/block/icside.c @@ -288,7 +288,6 @@ icside_build_dmatable(ide_drive_t *drive, int reading) static int icside_config_drive(ide_drive_t *drive, int mode) { - ide_hwif_t *hwif = HWIF(drive); int speed, err; if (mode == 2) { @@ -382,7 +381,8 @@ icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive) if (drive->media != ide_disk) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD); + drive->timeout = WAIT_CMD; + ide_set_handler(drive, &ide_dma_intr); OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c index b3ba03562..19fe18fe0 100644 --- a/drivers/block/ide-cd.c +++ b/drivers/block/ide-cd.c @@ -339,14 +339,15 @@ void cdrom_analyze_sense_data (ide_drive_t *drive, failed_command->c[0] == GPCMD_READ_SUBCHANNEL) return; } + if (reqbuf->error_code == 0x70 && reqbuf->sense_key == 0x02 && ((reqbuf->asc == 0x3a && reqbuf->ascq == 0x00) || (reqbuf->asc == 0x04 && reqbuf->ascq == 0x01))) { /* * Suppress the following errors: - * "Medium not present", and "in progress of becoming ready", - * to keep the noise level down to a dull roar. + * "Medium not present", "in progress of becoming ready", + * and "writing" to keep the noise level down to a dull roar. */ return; } @@ -431,6 +432,19 @@ void cdrom_analyze_sense_data (ide_drive_t *drive, printk ("\"\n"); } + /* The SKSV bit specifies validity of the sense_key_specific + * in the next two commands. It is bit 7 of the first byte. + * In the case of NOT_READY, if SKSV is set the drive can + * give us nice ETA readings. + */ + if (reqbuf->sense_key == NOT_READY && + (reqbuf->sense_key_specific[0] & 0x80)) { + int progress = (reqbuf->sense_key_specific[1] << 8 | + reqbuf->sense_key_specific[2]) * 100; + printk(" Command is %02d%% complete\n", progress / 0xffff); + + } + if (reqbuf->sense_key == ILLEGAL_REQUEST && (reqbuf->sense_key_specific[0] & 0x80) != 0) { printk (" Error in %s byte %d", @@ -466,21 +480,6 @@ void cdrom_analyze_sense_data (ide_drive_t *drive, #endif /* not VERBOSE_IDE_CD_ERRORS */ } - -/* Fix up a possibly partially-processed request so that we can - start it over entirely, or even put it back on the request queue. */ -static void restore_request (struct request *rq) -{ - if (rq->buffer != rq->bh->b_data) { - int n = (rq->buffer - rq->bh->b_data) / SECTOR_SIZE; - rq->buffer = rq->bh->b_data; - rq->nr_sectors += n; - rq->sector -= n; - } - rq->current_nr_sectors = rq->bh->b_size >> SECTOR_BITS; -} - - static void cdrom_queue_request_sense (ide_drive_t *drive, struct semaphore *sem, struct atapi_request_sense *reqbuf, @@ -533,10 +532,8 @@ static void cdrom_end_request (int uptodate, ide_drive_t *drive) struct packet_command *pc = (struct packet_command *) rq->buffer; cdrom_analyze_sense_data (drive, - (struct atapi_request_sense *) - (pc->buffer - pc->c[4]), - (struct packet_command *) - pc->sense_data); + (struct atapi_request_sense *) (pc->buffer - pc->c[4]), + (struct packet_command *) pc->sense_data); } if (rq->cmd == READ && !rq->current_nr_sectors) uptodate = 1; @@ -680,7 +677,7 @@ static int cdrom_start_packet_command (ide_drive_t *drive, int xferlen, struct cdrom_info *info = drive->driver_data; /* Wait for the controller to be idle. */ - if (ide_wait_stat (drive, 0, BUSY_STAT, WAIT_READY)) return 1; + if (ide_wait_stat(drive, 0, BUSY_STAT, WAIT_READY)) return 1; if (info->dma) info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive); @@ -699,7 +696,7 @@ static int cdrom_start_packet_command (ide_drive_t *drive, int xferlen, (void) (HWIF(drive)->dmaproc(ide_dma_begin, drive)); if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { - ide_set_handler (drive, handler, WAIT_CMD); + ide_set_handler (drive, handler); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */ @@ -716,9 +713,14 @@ static int cdrom_start_packet_command (ide_drive_t *drive, int xferlen, HANDLER is the interrupt handler to call when the command completes or there's data ready. */ static int cdrom_transfer_packet_command (ide_drive_t *drive, - char *cmd_buf, int cmd_len, + unsigned char *cmd_buf, int cmd_len, ide_handler_t *handler) { + /* don't timeout for blank and format commands. they may take + * a _very_ long time. */ + if (cmd_buf[0] == GPCMD_BLANK || cmd_buf[0] == GPCMD_FORMAT_UNIT) + drive->timeout = 0; + if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { /* Here we should have been called after receiving an interrupt from the device. DRQ should how be set. */ @@ -734,7 +736,7 @@ static int cdrom_transfer_packet_command (ide_drive_t *drive, } /* Arm the interrupt handler. */ - ide_set_handler (drive, handler, WAIT_CMD); + ide_set_handler (drive, handler); /* Send the command to the device. */ atapi_output_bytes (drive, cmd_buf, cmd_len); @@ -770,13 +772,12 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, /* If we don't yet have a sector buffer, try to allocate one. If we can't get one atomically, it's not fatal -- we'll just throw the data away rather than caching it. */ - if (info->sector_buffer == NULL) { - info->sector_buffer = (char *) kmalloc (SECTOR_BUFFER_SIZE, - GFP_ATOMIC); + if (info->buffer == NULL) { + info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_ATOMIC); /* If we couldn't get a buffer, don't try to buffer anything... */ - if (info->sector_buffer == NULL) + if (info->buffer == NULL) sectors_to_buffer = 0; } @@ -785,7 +786,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, info->sector_buffered = sector; /* Read the data into the buffer. */ - dest = info->sector_buffer + info->nsectors_buffered * SECTOR_SIZE; + dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE; while (sectors_to_buffer > 0) { atapi_input_bytes (drive, dest, SECTOR_SIZE); --sectors_to_buffer; @@ -802,7 +803,6 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, } } - /* * Check the contents of the interrupt reason register from the cdrom * and attempt to recover if there are problems. Returns 0 if everything's @@ -827,6 +827,12 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) atapi_output_bytes (drive, &dum, sizeof (dum)); len -= sizeof (dum); } + } else if (ireason == 1) { + /* Some drives (ASUS) seem to tell us that status + * info is available. just get it and ignore. + */ + GET_STAT(); + return 0; } else { /* Drive wants a command packet, or invalid ireason... */ printk ("%s: cdrom_read_intr: bad interrupt reason %d\n", @@ -837,7 +843,6 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason) return -1; } - /* * Interrupt routine. Called when a read request has completed. */ @@ -912,8 +917,7 @@ static void cdrom_read_intr (ide_drive_t *drive) /* First, figure out if we need to bit-bucket any of the leading sectors. */ - nskip = MIN ((int)(rq->current_nr_sectors - - (rq->bh->b_size >> SECTOR_BITS)), + nskip = MIN ((int)(rq->current_nr_sectors - (rq->bh->b_size >> SECTOR_BITS)), sectors_to_transfer); while (nskip > 0) { @@ -939,8 +943,7 @@ static void cdrom_read_intr (ide_drive_t *drive) /* If the buffers are full, cache the rest of the data in our internal buffer. */ if (rq->current_nr_sectors == 0) { - cdrom_buffer_sectors (drive, - rq->sector, sectors_to_transfer); + cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer); sectors_to_transfer = 0; } else { /* Transfer data to the buffers. @@ -952,8 +955,7 @@ static void cdrom_read_intr (ide_drive_t *drive) /* Read this_transfer sectors into the current buffer. */ while (this_transfer > 0) { - atapi_input_bytes (drive, - rq->buffer, SECTOR_SIZE); + atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE); rq->buffer += SECTOR_SIZE; --rq->nr_sectors; --rq->current_nr_sectors; @@ -966,10 +968,9 @@ static void cdrom_read_intr (ide_drive_t *drive) /* Done moving data! Wait for another interrupt. */ - ide_set_handler (drive, &cdrom_read_intr, WAIT_CMD); + ide_set_handler(drive, &cdrom_read_intr); } - /* * Try to satisfy some of the current read request from our cached data. * Returns nonzero if the request has been completed, zero otherwise. @@ -980,7 +981,7 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) struct request *rq = HWGROUP(drive)->rq; /* Can't do anything if there's no buffer. */ - if (info->sector_buffer == NULL) return 0; + if (info->buffer == NULL) return 0; /* Loop while this request needs data and the next block is present in our cache. */ @@ -991,7 +992,7 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) cdrom_end_request (1, drive); memcpy (rq->buffer, - info->sector_buffer + + info->buffer + (rq->sector - info->sector_buffered) * SECTOR_SIZE, SECTOR_SIZE); rq->buffer += SECTOR_SIZE; @@ -1026,8 +1027,6 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) return 0; } - - /* * Routine to send a read packet command to the drive. * This is usually called directly from cdrom_start_read. @@ -1056,14 +1055,13 @@ static void cdrom_start_read_continuation (ide_drive_t *drive) nskip = (sector % SECTORS_PER_FRAME); if (nskip > 0) { /* Sanity check... */ - if (rq->current_nr_sectors != - (rq->bh->b_size >> SECTOR_BITS)) { - printk ("%s: cdrom_start_read_continuation: buffer botch (%ld)\n", + if (rq->current_nr_sectors != (rq->bh->b_size >> SECTOR_BITS) && + (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); return; } - sector -= nskip; nsect += nskip; rq->current_nr_sectors += nskip; @@ -1091,9 +1089,10 @@ static void cdrom_start_read_continuation (ide_drive_t *drive) &cdrom_read_intr); } + #define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */ -#define IDECD_SEEK_TIMER (2 * WAIT_MIN_SLEEP) /* 40 ms */ -#define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */ +#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */ +#define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */ static void cdrom_seek_intr (ide_drive_t *drive) { @@ -1107,7 +1106,7 @@ static void cdrom_seek_intr (ide_drive_t *drive) if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) { if (--retry == 0) { - printk ("%s: disabled DSC seek overlap\n", drive->name); + printk("%s: disabled DSC seek overlap\n", drive->name); drive->dsc_overlap = 0; } } @@ -1127,7 +1126,7 @@ static void cdrom_start_seek_continuation (ide_drive_t *drive) memset (&pc.c, 0, sizeof (pc.c)); pc.c[0] = GPCMD_SEEK; - put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]); + put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]); (void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c), &cdrom_seek_intr); } @@ -1140,6 +1139,19 @@ static void cdrom_start_seek (ide_drive_t *drive, unsigned int block) cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation); } +/* Fix up a possibly partially-processed request so that we can + start it over entirely, or even put it back on the request queue. */ +static void restore_request (struct request *rq) +{ + if (rq->buffer != rq->bh->b_data) { + int n = (rq->buffer - rq->bh->b_data) / SECTOR_SIZE; + rq->buffer = rq->bh->b_data; + rq->nr_sectors += n; + rq->sector -= n; + } + rq->current_nr_sectors = rq->bh->b_size >> SECTOR_BITS; +} + /* * Start a read request from the CD-ROM. */ @@ -1162,25 +1174,22 @@ static void cdrom_start_read (ide_drive_t *drive, unsigned int block) restore_request (rq); /* Satisfy whatever we can of this request from our cached sector. */ - if (cdrom_read_from_buffer (drive)) + if (cdrom_read_from_buffer(drive)) return; - /* Clear the local sector buffer. */ info->nsectors_buffered = 0; - if (drive->using_dma && (rq->sector % SECTORS_PER_FRAME == 0) && (rq->nr_sectors % SECTORS_PER_FRAME == 0)) + /* use dma, if possible. */ + if (drive->using_dma && (rq->sector % SECTORS_PER_FRAME == 0) && + (rq->nr_sectors % SECTORS_PER_FRAME == 0)) info->dma = 1; else info->dma = 0; /* Start sending the read request to the drive. */ - cdrom_start_packet_command (drive, 32768, - cdrom_start_read_continuation); + cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation); } - - - /**************************************************************************** * Execute all other packet commands. */ @@ -1197,6 +1206,9 @@ static void cdrom_pc_intr (ide_drive_t *drive) struct request *rq = HWGROUP(drive)->rq; struct packet_command *pc = (struct packet_command *)rq->buffer; + /* restore timeout after blank or format command */ + drive->timeout = WAIT_CMD; + /* Check for errors. */ if (cdrom_decode_status (drive, 0, &stat)) return; @@ -1282,7 +1294,7 @@ static void cdrom_pc_intr (ide_drive_t *drive) } /* Now we wait for another interrupt. */ - ide_set_handler (drive, &cdrom_pc_intr, WAIT_CMD); + ide_set_handler (drive, &cdrom_pc_intr); } @@ -1334,6 +1346,7 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc) if (pc->sense_data == NULL) pc->sense_data = &my_reqbuf; pc->sense_data->sense_key = 0; + /* Start of retry loop. */ do { ide_init_drive_cmd (&req); @@ -1353,7 +1366,7 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc) if (reqbuf->sense_key == UNIT_ATTENTION) cdrom_saw_media_change (drive); else if (reqbuf->sense_key == NOT_READY && - reqbuf->asc == 4) { + reqbuf->asc == 4 && reqbuf->ascq != 4) { /* The drive is in the process of loading a disk. Retry, but wait a little to give the drive time to complete the load. */ @@ -1368,7 +1381,6 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc) /* End of retry loop. */ } while (pc->stat != 0 && retries >= 0); - /* Return an error if the command failed. */ if (pc->stat != 0) return -EIO; @@ -1397,25 +1409,17 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc) static void ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block) { - if (rq -> cmd == PACKET_COMMAND || rq -> cmd == REQUEST_SENSE_COMMAND) - cdrom_do_packet_command (drive); - else if (rq -> cmd == RESET_DRIVE_COMMAND) { - cdrom_end_request (1, drive); - ide_do_reset (drive); - return; - } else if (rq -> cmd != READ) { - printk ("ide-cd: bad cmd %d\n", rq -> cmd); - cdrom_end_request (0, drive); - } else { - struct cdrom_info *info = drive->driver_data; + struct cdrom_info *info = drive->driver_data; + switch (rq->cmd) { + 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) { - ide_stall_queue (drive, IDECD_SEEK_TIMER); + ide_stall_queue(drive, IDECD_SEEK_TIMER); return; } printk ("%s: DSC timeout\n", drive->name); @@ -1427,6 +1431,26 @@ void ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long bloc else cdrom_start_read (drive, block); info->last_block = block; + break; + } + + case PACKET_COMMAND: + case REQUEST_SENSE_COMMAND: { + cdrom_do_packet_command(drive); + break; + } + + case RESET_DRIVE_COMMAND: { + cdrom_end_request(1, drive); + ide_do_reset(drive); + break; + } + + default: { + printk("ide-cd: bad cmd %d\n", rq -> cmd); + cdrom_end_request(0, drive); + break; + } } } @@ -1600,7 +1624,7 @@ cdrom_read_capacity (ide_drive_t *drive, unsigned *capacity, stat = cdrom_queue_packet_command (drive, &pc); if (stat == 0) - *capacity = ntohl (capbuf.lba); + *capacity = be32_to_cpu(capbuf.lba); return stat; } @@ -1879,64 +1903,7 @@ int cdrom_get_toc_entry (ide_drive_t *drive, int track, -/* This gets the mechanism status per ATAPI draft spec 2.6 */ -static int -cdrom_read_mech_status (ide_drive_t *drive, char *buf, int buflen, - struct atapi_request_sense *reqbuf) -{ - struct packet_command pc; - - memset (&pc, 0, sizeof (pc)); - pc.sense_data = reqbuf; - - pc.buffer = buf; - pc.buflen = buflen; - pc.c[0] = GPCMD_MECHANISM_STATUS; - pc.c[8] = (buflen >> 8); - pc.c[9] = (buflen & 0xff); - return cdrom_queue_packet_command (drive, &pc); -} - -/* Read the drive mechanism status and slot table into our internal buffer. - If the buffer does not yet exist, allocate it. */ -static int -cdrom_read_changer_info (ide_drive_t *drive) -{ - int nslots; - struct cdrom_info *info = drive->driver_data; - - if (info->changer_info) - nslots = info->changer_info->hdr.nslots; - - else { - struct atapi_mechstat_header mechbuf; - int stat; - - stat = cdrom_read_mech_status (drive, - (char *)&mechbuf, - sizeof (mechbuf), - NULL); - if (stat) - return stat; - - nslots = mechbuf.nslots; - info->changer_info = - (struct atapi_changer_info *) - kmalloc (sizeof (struct atapi_changer_info) + - nslots * sizeof (struct atapi_slot), - GFP_KERNEL); - - if (info->changer_info == NULL) - return -ENOMEM; - } - return cdrom_read_mech_status - (drive, - (char *)&info->changer_info->hdr, - sizeof (struct atapi_mechstat_header) + - nslots * sizeof (struct atapi_slot), - NULL); -} /* the generic packet interface to cdrom.c */ static int ide_cdrom_packet(struct cdrom_device_info *cdi, @@ -1952,8 +1919,7 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi, memcpy(pc.c, cgc->cmd, CDROM_PACKET_SIZE); pc.buffer = cgc->buffer; pc.buflen = cgc->buflen; - cgc->stat = cdrom_queue_packet_command(drive, &pc); - return cgc->stat; + return cgc->stat = cdrom_queue_packet_command(drive, &pc); } static @@ -2130,16 +2096,19 @@ static int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) { ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct cdrom_info *info = drive->driver_data; if (slot_nr == CDSL_CURRENT) { - struct atapi_request_sense my_reqbuf; - int stat = cdrom_check_status (drive, &my_reqbuf); - if (stat == 0 || my_reqbuf.sense_key == UNIT_ATTENTION) + struct atapi_request_sense sense; + int stat = cdrom_check_status (drive, &sense); + if (stat == 0 || sense.sense_key == UNIT_ATTENTION) + return CDS_DISC_OK; + + if (sense.sense_key == NOT_READY && sense.asc == 0x04 && + sense.ascq == 0x04) return CDS_DISC_OK; - if (my_reqbuf.sense_key == NOT_READY) { + if (sense.sense_key == NOT_READY) { /* ATAPI doesn't have anything that can help us decide whether the drive is really emtpy or the tray is just open. irk. */ @@ -2147,24 +2116,8 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr) } return CDS_DRIVE_NOT_READY; - } - -#if ! STANDARD_ATAPI - else if (cdi->sanyo_slot > 0) - return CDS_NO_INFO; -#endif /* not STANDARD_ATAPI */ - - else { - struct atapi_changer_info *ci; - int stat = cdrom_read_changer_info (drive); - if (stat < 0) - return stat; - ci = info->changer_info; - - if (ci->slots[slot_nr].disc_present) - return CDS_DISC_OK; - else - return CDS_NO_DISC; + } else { + return -EINVAL; } } @@ -2215,47 +2168,14 @@ int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi, int slot_nr) { ide_drive_t *drive = (ide_drive_t*) cdi->handle; - struct cdrom_info *info = drive->driver_data; - struct atapi_request_sense reqbuf; - int retval; if (slot_nr == CDSL_CURRENT) { (void) cdrom_check_status (drive, NULL); - retval = CDROM_STATE_FLAGS (drive)->media_changed; CDROM_STATE_FLAGS (drive)->media_changed = 0; + return CDROM_STATE_FLAGS (drive)->media_changed; + } else { + return -EINVAL; } - -#if ! STANDARD_ATAPI - else if (cdi->sanyo_slot > 0) { - retval = 0; - } -#endif /* not STANDARD_ATAPI */ - - else { - struct atapi_changer_info *ci; - int stat = cdrom_read_changer_info (drive); - if (stat < 0) - return stat; - ci = info->changer_info; - - /* This test may be redundant with cdrom.c. */ - if (slot_nr < 0 || slot_nr >= ci->hdr.nslots) - return -EINVAL; - - retval = ci->slots[slot_nr].change; - } - - /* if the media has changed, check if a disc is in the drive - and read the toc info. */ - if (retval || !CDROM_STATE_FLAGS (drive)->toc_valid) { - /* if cdrom_read_toc fails, return 1 to indicate - that a disc change has occured. there might not - be a disc in the drive. */ - if ((retval = cdrom_read_toc (drive, &reqbuf))) - return 1; - } - - return retval; } @@ -2361,11 +2281,12 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) * be queued with ide_cdrom_packet(), which extracts the * drive from cdi->handle. Since this device hasn't been * registered with the Uniform layer yet, it can't do this. - * Same goes cdi->ops. + * Same goes for cdi->ops. */ cdi->handle = (ide_drive_t *) drive; cdi->ops = &ide_cdrom_dops; - do { /* we seem to get stat=0x01,err=0x00 the first time (??) */ + /* we seem to get stat=0x01,err=0x00 the first time (??) */ + do { if (attempts-- <= 0) return 0; stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0); @@ -2402,14 +2323,9 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) #endif /* not STANDARD_ATAPI */ if (buf.cap.mechtype == mechtype_individual_changer || buf.cap.mechtype == mechtype_cartridge_changer) { - struct atapi_mechstat_header mechbuf; - - stat = cdrom_read_mech_status (drive, (char*)&mechbuf, - sizeof (mechbuf), NULL); - if (!stat) { + if ((nslots = cdrom_number_of_slots(cdi)) > 1) { CDROM_CONFIG_FLAGS (drive)->is_changer = 1; CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 1; - nslots = mechbuf.nslots; } } @@ -2445,7 +2361,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) else printk (" drive"); - printk (", %dkB Cache", ntohs(buf.cap.buffer_size)); + printk (", %dkB Cache", be16_to_cpu(buf.cap.buffer_size)); if (drive->using_dma) { if ((drive->id->field_valid & 4) && @@ -2473,7 +2389,6 @@ static void ide_cdrom_add_settings(ide_drive_t *drive) ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); } - static int ide_cdrom_setup (ide_drive_t *drive) { @@ -2482,13 +2397,12 @@ int ide_cdrom_setup (ide_drive_t *drive) int minor = drive->select.b.unit << PARTN_BITS; int nslots; - kdev_t dev = MKDEV(HWIF(drive)->major, minor); - - set_device_ro (dev, 1); + set_device_ro(MKDEV(HWIF(drive)->major, minor), 1); blksize_size[HWIF(drive)->major][minor] = CD_FRAMESIZE; - drive->special.all = 0; - drive->ready_stat = 0; + drive->special.all = 0; + drive->ready_stat = 0; + drive->timeout = WAIT_CMD; CDROM_STATE_FLAGS (drive)->media_changed = 1; CDROM_STATE_FLAGS (drive)->toc_valid = 0; @@ -2589,11 +2503,13 @@ int ide_cdrom_setup (ide_drive_t *drive) } #endif /* not STANDARD_ATAPI */ - info->toc = NULL; - info->sector_buffer = NULL; - info->sector_buffered = 0; - info->nsectors_buffered = 0; + info->toc = NULL; + info->buffer = NULL; + info->sector_buffered = 0; + info->nsectors_buffered = 0; info->changer_info = NULL; + info->last_block = 0; + info->start_seek = 0; nslots = ide_cdrom_probe_capabilities (drive); @@ -2653,15 +2569,15 @@ int ide_cdrom_cleanup(ide_drive_t *drive) if (ide_unregister_subdriver (drive)) return 1; - if (info->sector_buffer != NULL) - kfree (info->sector_buffer); + if (info->buffer != NULL) + kfree(info->buffer); if (info->toc != NULL) - kfree (info->toc); + kfree(info->toc); if (info->changer_info != NULL) - kfree (info->changer_info); + kfree(info->changer_info); if (devinfo->handle == drive && unregister_cdrom (devinfo)) printk ("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); - kfree (info); + kfree(info); drive->driver_data = NULL; return 0; } diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h index ae1a252ed..b65baa5fe 100644 --- a/drivers/block/ide-cd.h +++ b/drivers/block/ide-cd.h @@ -34,19 +34,13 @@ #define NO_DOOR_LOCKING 0 #endif - -/* Size of buffer to allocate, in blocks, for audio reads. */ - -#ifndef CDROM_NBLOCKS_BUFFER -#define CDROM_NBLOCKS_BUFFER 8 -#endif - - /************************************************************************/ -#define SECTOR_SIZE 512 -#define SECTOR_BITS 9 -#define SECTORS_PER_FRAME (CD_FRAMESIZE / SECTOR_SIZE) +#define SECTOR_SIZE 512 +#define SECTOR_BITS 9 +#define SECTORS_PER_FRAME (CD_FRAMESIZE / SECTOR_SIZE) +#define SECTOR_BUFFER_SIZE (CD_FRAMESIZE * 32) +#define SECTORS_BUFFER (SECTOR_BUFFER_SIZE / SECTOR_SIZE) #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -84,7 +78,8 @@ struct ide_cd_config_flags { __u8 seeking : 1; /* Seeking in progress */ __u8 audio_play : 1; /* can do audio related commands */ __u8 close_tray : 1; /* can close the tray */ - __u8 reserved : 4; + __u8 writing : 1; /* pseudo write in progress */ + __u8 reserved : 3; byte max_speed; /* Max speed of the drive */ }; #define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags)) @@ -96,7 +91,8 @@ struct ide_cd_state_flags { __u8 media_changed : 1; /* Driver has noticed a media change. */ __u8 toc_valid : 1; /* Saved TOC information is current. */ __u8 door_locked : 1; /* We think that the drive door is locked. */ - __u8 reserved : 5; + __u8 writing : 1; /* the drive is currently writing */ + __u8 reserved : 4; byte current_speed; /* Current speed of the drive */ }; #define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags)) @@ -487,13 +483,11 @@ struct atapi_slot { byte reserved2[3]; }; - struct atapi_changer_info { struct atapi_mechstat_header hdr; struct atapi_slot slots[0]; }; - /* Extra per-device info for cdrom drives. */ struct cdrom_info { @@ -502,17 +496,9 @@ struct cdrom_info { struct atapi_toc *toc; - /* Sector buffer. If a read request wants only the first part - of a cdrom block, we cache the rest of the block here, - in the expectation that the data is going to be wanted soon. - SECTOR_BUFFERED is the number of the first buffered sector, - and NSECTORS_BUFFERED is the number of sectors in the buffer. - Before the buffer is allocated, we should have - SECTOR_BUFFER == NULL and NSECTORS_BUFFERED == 0. */ - - unsigned long sector_buffered; - unsigned long nsectors_buffered; - char *sector_buffer; + unsigned long sector_buffered; + unsigned long nsectors_buffered; + unsigned char *buffer; /* The result of the last successful request sense command on this device. */ @@ -533,10 +519,6 @@ struct cdrom_info { struct cdrom_device_info devinfo; }; - -#define SECTOR_BUFFER_SIZE CD_FRAMESIZE - - /**************************************************************************** * Descriptions of ATAPI error codes. */ @@ -652,6 +634,7 @@ const struct { { 0x000013, "Play operation successfully completed" }, { 0x000014, "Play operation stopped due to error" }, { 0x000015, "No current audio status to return" }, + { 0x010c0a, "Write error - padding blocks added" }, { 0x011700, "Recovered data with no error correction applied" }, { 0x011701, "Recovered data with retries" }, { 0x011702, "Recovered data with positive head offset" }, @@ -668,6 +651,7 @@ const struct { { 0x015d01, "Failure prediction threshold exceeded - Predicted media failure" }, { 0x015dff, "Failure prediction threshold exceeded - False" }, + { 0x017301, "Power calibration area almost full" }, { 0x020400, "Logical unit not ready - cause not reportable" }, /* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */ { 0x020401, @@ -680,9 +664,35 @@ const struct { { 0x023a00, "Medium not present" }, { 0x025300, "Media load or eject failed" }, { 0x025700, "Unable to recover table of contents" }, + { 0x030300, "Peripheral device write fault" }, + { 0x030301, "No write current" }, + { 0x030302, "Excessive write errors" }, + { 0x030c00, "Write error" }, + { 0x030c01, "Write error - Recovered with auto reallocation" }, + { 0x030c02, "Write error - auto reallocation failed" }, + { 0x030c03, "Write error - recommend reassignment" }, + { 0x030c04, "Compression check miscompare error" }, + { 0x030c05, "Data expansion occurred during compress" }, + { 0x030c06, "Block not compressible" }, + { 0x030c07, "Write error - recovery needed" }, + { 0x030c08, "Write error - recovery failed" }, + { 0x030c09, "Write error - loss of streaming" }, { 0x031100, "Unrecovered read error" }, { 0x031106, "CIRC unrecovered error" }, { 0x033101, "Format command failed" }, + { 0x033200, "No defect spare location available" }, + { 0x033201, "Defect list update failure" }, + { 0x035100, "Erase failure" }, + { 0x037200, "Session fixation error" }, + { 0x037201, "Session fixation error writin lead-in" }, + { 0x037202, "Session fixation error writin lead-out" }, + { 0x037300, "CD control error" }, + { 0x037302, "Power calibration area is full" }, + { 0x037303, "Power calibration area error" }, + { 0x037304, "Program memory area / RMA update failure" }, + { 0x037305, "Program memory area / RMA is full" }, + { 0x037306, "Program memory area / RMA is (almost) full" }, + { 0x040200, "No seek complete" }, { 0x040300, "Write fault" }, { 0x040900, "Track following error" }, @@ -700,11 +710,15 @@ const struct { { 0x052000, "Invalid command operation code" }, { 0x052c00, "Command sequence error" }, { 0x052100, "Logical block address out of range" }, + { 0x052102, "Invalid address for write" }, { 0x052400, "Invalid field in command packet" }, { 0x052600, "Invalid field in parameter list" }, { 0x052601, "Parameter not supported" }, { 0x052602, "Parameter value invalid" }, { 0x052700, "Write protected media" }, + { 0x052c00, "Command sequence error" }, + { 0x052c03, "Current program area is not empty" }, + { 0x052c04, "Current program area is empty" }, { 0x053001, "Cannot read medium - unknown format" }, { 0x053002, "Cannot read medium - incompatible format" }, { 0x053900, "Saving parameters not supported" }, @@ -713,11 +727,15 @@ const struct { { 0x055500, "System resource failure" }, { 0x056300, "End of user area encountered on this track" }, { 0x056400, "Illegal mode for this track or incompatible medium" }, - { 0x056f00, - "Copy protection key exchange failure - Authentication failure" }, + { 0x056f00, "Copy protection key exchange failure - Authentication failure" }, { 0x056f01, "Copy protection key exchange failure - Key not present" }, - { 0x056f02, - "Copy protection key exchange failure - Key not established" }, + { 0x056f02, "Copy protection key exchange failure - Key not established" }, + { 0x056f03, "Read of scrambled sector without authentication" }, + { 0x056f04, "Media region code is mismatched to logical unit" }, + { 0x056f05, "Drive region must be permanent / region reset count error" }, + { 0x057203, "Session fixation error - incomplete track in session" }, + { 0x057204, "Empty or partially written reserved track" }, + { 0x057205, "No more RZONE reservations are allowed" }, { 0x05bf00, "Loss of streaming" }, { 0x062800, "Not ready to ready transition, medium may have changed" }, { 0x062900, "Power on, reset or hardware reset occurred" }, diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c index d2941a1ab..8fa7745b4 100644 --- a/drivers/block/ide-disk.c +++ b/drivers/block/ide-disk.c @@ -175,7 +175,7 @@ read_next: if (i > 0) { if (msect) goto read_next; - ide_set_handler (drive, &read_intr, WAIT_CMD); + ide_set_handler (drive, &read_intr); } } @@ -206,7 +206,7 @@ static void write_intr (ide_drive_t *drive) ide_end_request(1, hwgroup); if (i > 0) { idedisk_output_data (drive, rq->buffer, SECTOR_WORDS); - ide_set_handler (drive, &write_intr, WAIT_CMD); + ide_set_handler (drive, &write_intr); } goto out; } @@ -271,7 +271,7 @@ static void multwrite_intr (ide_drive_t *drive) if (stat & DRQ_STAT) { if (rq->nr_sectors) { ide_multwrite(drive, drive->mult_count); - ide_set_handler (drive, &multwrite_intr, WAIT_CMD); + ide_set_handler (drive, &multwrite_intr); goto out; } } else { @@ -385,7 +385,7 @@ static void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long bl if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive))) return; #endif /* CONFIG_BLK_DEV_IDEDMA */ - ide_set_handler(drive, &read_intr, WAIT_CMD); + ide_set_handler(drive, &read_intr); OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG); return; } @@ -404,10 +404,10 @@ static void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long bl __cli(); /* local CPU only */ if (drive->mult_count) { HWGROUP(drive)->wrq = *rq; /* scratchpad */ - ide_set_handler (drive, &multwrite_intr, WAIT_CMD); + ide_set_handler (drive, &multwrite_intr); ide_multwrite(drive, drive->mult_count); } else { - ide_set_handler (drive, &write_intr, WAIT_CMD); + ide_set_handler (drive, &write_intr); idedisk_output_data(drive, rq->buffer, SECTOR_WORDS); } return; @@ -506,6 +506,7 @@ static void idedisk_pre_reset (ide_drive_t *drive) drive->special.all = 0; drive->special.b.set_geometry = 1; drive->special.b.recalibrate = 1; + drive->timeout = WAIT_CMD; if (OK_TO_RESET_CONTROLLER) drive->mult_count = 0; if (!drive->keep_settings) diff --git a/drivers/block/ide-dma.c b/drivers/block/ide-dma.c index d3c657516..338d51c9a 100644 --- a/drivers/block/ide-dma.c +++ b/drivers/block/ide-dma.c @@ -420,7 +420,8 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive) drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD);/* issue cmd to drive */ + drive->timeout = WAIT_CMD; + ide_set_handler(drive, &ide_dma_intr);/* issue cmd to drive */ OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); case ide_dma_begin: /* Note that this is done *after* the cmd has @@ -460,7 +461,7 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive) int ide_release_dma (ide_hwif_t *hwif) { if (hwif->dmatable) { - clear_page((unsigned long)hwif->dmatable); /* clear PRD 1st */ + clear_page((void *)hwif->dmatable); /* clear PRD 1st */ free_page((unsigned long)hwif->dmatable); /* free PRD 2nd */ } if ((hwif->dma_extra) && (hwif->channel == 0)) @@ -537,14 +538,7 @@ unsigned long __init ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const switch(dev->device) { case PCI_DEVICE_ID_CMD_643: -#ifdef CONFIG_BLK_DEV_ALI15X3 case PCI_DEVICE_ID_AL_M5219: - case PCI_DEVICE_ID_AL_M5229: - /* - * Ali 15x3 chipsets know as ALI IV and V report - * this as simplex, skip this test for them. - */ -#endif /* CONFIG_BLK_DEV_ALI15X3 */ outb(inb(dma_base+2) & 0x60, dma_base+2); if (inb(dma_base+2) & 0x80) { printk("%s: simplex device: DMA forced\n", name); diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c index f1c8baef8..3db1c1515 100644 --- a/drivers/block/ide-floppy.c +++ b/drivers/block/ide-floppy.c @@ -916,7 +916,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive) 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); + ide_set_handler (drive,&idefloppy_pc_intr); return; } #if IDEFLOPPY_DEBUG_LOG @@ -938,7 +938,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive) pc->actually_transferred+=bcount.all; /* Update the current position */ pc->current_position+=bcount.all; - ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD); /* And set the interrupt handler again */ + ide_set_handler (drive,&idefloppy_pc_intr); /* And set the interrupt handler again */ } static void idefloppy_transfer_pc (ide_drive_t *drive) @@ -956,7 +956,7 @@ static void idefloppy_transfer_pc (ide_drive_t *drive) ide_do_reset (drive); return; } - ide_set_handler (drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD); /* Set the interrupt routine */ + ide_set_handler (drive, &idefloppy_pc_intr); /* Set the interrupt routine */ atapi_output_bytes (drive, floppy->pc->c, 12); /* Send the actual packet */ } @@ -1025,7 +1025,7 @@ static void idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc) #endif /* CONFIG_BLK_DEV_IDEDMA */ if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { - ide_set_handler (drive, &idefloppy_transfer_pc, IDEFLOPPY_WAIT_CMD); + ide_set_handler (drive, &idefloppy_transfer_pc); OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* Issue the packet command */ } else { OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); @@ -1519,6 +1519,7 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) *((unsigned short *) &gcw) = drive->id->config; drive->driver_data = floppy; drive->ready_stat = 0; + drive->timeout = IDEFLOPPY_WAIT_CMD; memset (floppy, 0, sizeof (idefloppy_floppy_t)); floppy->drive = drive; floppy->pc = floppy->pc_stack; diff --git a/drivers/block/ide-geometry.c b/drivers/block/ide-geometry.c index 974fb24f1..44aa1844d 100644 --- a/drivers/block/ide-geometry.c +++ b/drivers/block/ide-geometry.c @@ -5,6 +5,9 @@ #include <asm/io.h> +extern ide_drive_t * get_info_ptr(kdev_t); +extern unsigned long current_capacity (ide_drive_t *); + /* * We query CMOS about hard disks : it could be that we have a SCSI/ESDI/etc * controller that is BIOS compatible with ST-506, and thus showing up in our diff --git a/drivers/block/ide-pci.c b/drivers/block/ide-pci.c index 311bd470b..73ffa67ea 100644 --- a/drivers/block/ide-pci.c +++ b/drivers/block/ide-pci.c @@ -57,8 +57,9 @@ #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}) #define DEVID_CX5530 ((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE}) +#define DEVID_AMD7409 ((ide_pci_devid_t){PCI_VENDOR_ID_AMD, 0x7409}) -#define IDE_IGNORE ((void *)-1) +#define IDE_IGNORE ((void *)-1) #ifdef CONFIG_BLK_DEV_TRM290 extern void ide_init_trm290(ide_hwif_t *); @@ -106,54 +107,66 @@ extern void ide_init_rz1000(ide_hwif_t *); #define INIT_RZ1000 IDE_IGNORE #endif -#ifdef CONFIG_BLK_DEV_VIA82C586 -extern unsigned int pci_init_via82c568(struct pci_dev *, const char *); -extern void ide_init_via82c586(ide_hwif_t *); -extern void ide_dmacapable_via82c586(ide_hwif_t *, unsigned long dmabase); -#define PCI_VIA82C586 &pci_init_via82c568 -#define INIT_VIA82C586 &ide_init_via82c586 -#define DMA_VIA82C586 &ide_dmacapable_via82c586 +#ifdef CONFIG_BLK_DEV_VIA82CXXX +extern unsigned int pci_init_via82cxxx(struct pci_dev *, const char *); +extern unsigned int ata66_via82cxxx(ide_hwif_t *); +extern void ide_init_via82cxxx(ide_hwif_t *); +extern void ide_dmacapable_via82cxxx(ide_hwif_t *, unsigned long); +#define PCI_VIA82CXXX &pci_init_via82cxxx +#define ATA66_VIA82CXXX &ata66_via82cxxx +#define INIT_VIA82CXXX &ide_init_via82cxxx +#define DMA_VIA82CXXX &ide_dmacapable_via82cxxx #else -#define PCI_VIA82C586 NULL -#define INIT_VIA82C586 NULL -#define DMA_VIA82C586 NULL +#define PCI_VIA82CXXX NULL +#define ATA66_VIA82CXXX NULL +#define INIT_VIA82CXXX NULL +#define DMA_VIA82CXXX NULL #endif #ifdef CONFIG_BLK_DEV_ALI15X3 extern unsigned int pci_init_ali15x3(struct pci_dev *, const char *); +extern unsigned int ata66_ali15x3(ide_hwif_t *); extern void ide_init_ali15x3(ide_hwif_t *); +extern void ide_dmacapable_ali15x3(ide_hwif_t *, unsigned long); #define PCI_ALI15X3 &pci_init_ali15x3 -#define INIT_ALI15X3 &ide_init_ali15x3 +#define ATA66_ALI15X3 &ata66_ali15x3 +#define INIT_ALI15X3 &ide_init_ali15x3 +#define DMA_ALI15X3 &ide_dmacapable_ali15x3 #else #define PCI_ALI15X3 NULL -#define INIT_ALI15X3 NULL +#define ATA66_ALI15X3 NULL +#define INIT_ALI15X3 NULL +#define DMA_ALI15X3 NULL #endif #ifdef CONFIG_BLK_DEV_CY82C693 extern unsigned int pci_init_cy82c693(struct pci_dev *, const char *); extern void ide_init_cy82c693(ide_hwif_t *); #define PCI_CY82C693 &pci_init_cy82c693 -#define INIT_CY82C693 &ide_init_cy82c693 +#define INIT_CY82C693 &ide_init_cy82c693 #else #define PCI_CY82C693 NULL -#define INIT_CY82C693 NULL +#define INIT_CY82C693 NULL #endif #ifdef CONFIG_BLK_DEV_PDC202XX 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 PCI_PDC202XX &pci_init_pdc202xx -#define INIT_PDC202XX &ide_init_pdc202xx +#define ATA66_PDC202XX &ata66_pdc202xx +#define INIT_PDC202XX &ide_init_pdc202xx #else #define PCI_PDC202XX NULL -#define INIT_PDC202XX NULL +#define ATA66_PDC202XX NULL +#define INIT_PDC202XX NULL #endif #ifdef CONFIG_BLK_DEV_PIIX extern void ide_init_piix(ide_hwif_t *); -#define INIT_PIIX &ide_init_piix +#define INIT_PIIX &ide_init_piix #else -#define INIT_PIIX NULL +#define INIT_PIIX NULL #endif #ifdef CONFIG_BLK_DEV_AEC6210 @@ -167,29 +180,40 @@ extern unsigned int pci_init_aec6210(struct pci_dev *, const char *); extern unsigned int pci_init_hpt34x(struct pci_dev *, const char *); extern void ide_init_hpt34x(ide_hwif_t *); #define PCI_HPT34X &pci_init_hpt34x -#define INIT_HPT34X &ide_init_hpt34x +#define INIT_HPT34X &ide_init_hpt34x #else #define PCI_HPT34X NULL -#define INIT_HPT34X NULL +#define INIT_HPT34X NULL #endif #ifdef CONFIG_BLK_DEV_HPT366 +extern byte hpt363_shared_irq; 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 PCI_HPT366 &pci_init_hpt366 +#define ATA66_HPT366 &ata66_hpt366 #define INIT_HPT366 &ide_init_hpt366 +#define DMA_HPT366 &ide_dmacapable_hpt366 #else +static byte hpt363_shared_irq = 0; #define PCI_HPT366 NULL -#define INIT_HPT366 IDE_IGNORE +#define ATA66_HPT366 NULL +#define INIT_HPT366 NULL +#define DMA_HPT366 NULL #endif #ifdef CONFIG_BLK_DEV_SIS5513 extern unsigned int pci_init_sis5513(struct pci_dev *, const char *); +extern unsigned int ata66_sis5513(ide_hwif_t *); extern void ide_init_sis5513(ide_hwif_t *); #define PCI_SIS5513 &pci_init_sis5513 +#define ATA66_SIS5513 &ata66_sis5513 #define INIT_SIS5513 &ide_init_sis5513 #else #define PCI_SIS5513 NULL +#define ATA66_SIS5513 NULL #define INIT_SIS5513 NULL #endif @@ -206,49 +230,48 @@ typedef struct ide_pci_device_s { ide_pci_devid_t devid; const 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; - byte sixtysix; unsigned int extra; } ide_pci_device_t; static ide_pci_device_t ide_pci_chipsets[] __initdata = { - {DEVID_PIIXa, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, - {DEVID_PIIXb, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, - {DEVID_PIIX3, "PIIX3", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, - {DEVID_PIIX4, "PIIX4", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0, 0 }, - {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_VP_IDE, "VP_IDE", PCI_VIA82C586, INIT_VIA82C586, DMA_VIA82C586, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0, 0 }, - {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 0, 16 }, - {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 1, 48 }, - {DEVID_RZ1000, "RZ1000", NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_RZ1001, "RZ1001", NULL, INIT_RZ1000, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_SAMURAI, "SAMURAI", NULL, INIT_SAMURAI, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_CMD640, "CMD640", NULL, IDE_IGNORE, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_NS87410, "NS87410", NULL, NULL, NULL, {{0x43,0x08,0x08}, {0x47,0x08,0x08}}, ON_BOARD, 0, 0 }, - {DEVID_SIS5513, "SIS5513", PCI_SIS5513, INIT_SIS5513, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, ON_BOARD, 1, 0 }, - {DEVID_CMD643, "CMD643", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_CMD646, "CMD646", NULL, INIT_CMD646, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0, 0 }, - {DEVID_HT6565, "HT6565", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_OPTI621, "OPTI621", NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_OPTI621X,"OPTI621X", NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_TRM290, "TRM290", NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_NS87415, "NS87415", NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0, 0 }, - {DEVID_W82C105, "W82C105", NULL, INIT_W82C105, NULL, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0, 0 }, - {DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_UM8886BF,"UM8886BF", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_HPT34X, "HPT34X", PCI_HPT34X, INIT_HPT34X, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0, 16 }, - {DEVID_HPT366, "HPT366", PCI_HPT366, INIT_HPT366, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 1, 256 }, - {DEVID_ALI15X3, "ALI15X3", PCI_ALI15X3, INIT_ALI15X3, NULL, {{0x09,0x20,0x20}, {0x09,0x10,0x10}}, ON_BOARD, 0, 0 }, - {DEVID_CY82C693,"CY82C693", PCI_CY82C693, INIT_CY82C693, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_HINT, "HINT_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {DEVID_CX5530, "CX5530", NULL, INIT_CX5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }, - {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0, 0 }}; - -static byte hpt363_shared_irq = 0; + {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_PIIX3, "PIIX3", NULL, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4, "PIIX4", NULL, NULL, 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_VP_IDE, "VP_IDE", PCI_VIA82CXXX, ATA66_VIA82CXXX,INIT_VIA82CXXX, DMA_VIA82CXXX, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, + {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_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", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_CMD646, "CMD646", NULL, NULL, INIT_CMD646, NULL, {{0x00,0x00,0x00}, {0x51,0x80,0x80}}, ON_BOARD, 0 }, + {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_AEC6210, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 }, + {DEVID_W82C105, "W82C105", NULL, NULL, INIT_W82C105, NULL, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, 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, 256 }, + {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_CX5530, "CX5530", NULL, NULL, INIT_CX5530, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {DEVID_AMD7409, "AMD7409", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, + {IDE_PCI_DEVID_NULL, "PCI_IDE", 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 @@ -260,24 +283,24 @@ static unsigned int __init ide_special_settings (struct pci_dev *dev, const char switch(dev->device) { case PCI_DEVICE_ID_TTI_HPT343: { + int i; + unsigned long hpt34xIoBase = dev->resource[4].start; unsigned short pcicmd = 0; pci_write_config_byte(dev, 0x80, 0x00); pci_read_config_word(dev, PCI_COMMAND, &pcicmd); if (!(pcicmd & PCI_COMMAND_MEMORY)) { - int i; - unsigned long hpt34xIoBase = dev->resource[4].start; - - dev->resource[0].start = (hpt34xIoBase + 0x20); - dev->resource[1].start = (hpt34xIoBase + 0x34); - dev->resource[2].start = (hpt34xIoBase + 0x28); - dev->resource[3].start = (hpt34xIoBase + 0x3c); - for(i=0; i<4; i++) - dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); } else { pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0); } + + dev->resource[0].start = (hpt34xIoBase + 0x20); + dev->resource[1].start = (hpt34xIoBase + 0x34); + dev->resource[2].start = (hpt34xIoBase + 0x28); + dev->resource[3].start = (hpt34xIoBase + 0x3c); + for(i=0; i<4; i++) + dev->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; } case PCI_DEVICE_ID_TTI_HPT366: case PCI_DEVICE_ID_PROMISE_20246: @@ -530,8 +553,7 @@ check_if_enabled: hwif->irq = hwif->channel ? 15 : 14; goto bypass_umc_dma; } - if ((!d->sixtysix) && (hwif->udma_four)) - hwif->udma_four = 0; + hwif->udma_four = (d->ata66_check) ? d->ata66_check(hwif) : 0; #ifdef CONFIG_BLK_DEV_IDEDMA if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) || IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) @@ -582,40 +604,35 @@ bypass_umc_dma: static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_device_t *d) { - struct pci_dev *dev2; + struct pci_dev *dev2 = NULL, *findev; ide_pci_device_t *d2; unsigned char pin1 = 0, pin2 = 0; - d2 = d; if (PCI_FUNC(dev->devfn) & 1) return; - - for (dev2=pci_devices; dev2; dev2=dev2->next) { - if ((dev2->vendor == dev->vendor) && - (dev2->device == dev->device) && - (PCI_FUNC(dev2->devfn) & 1)) - break; - } pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); - if (dev2) { - pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); - hpt363_shared_irq = (pin1 != pin2) ? 1 : 0; - } - - if (hpt363_shared_irq) { - printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", - d->name, pin1, pin2); + for (findev=pci_devices; findev; findev=findev->next) { + 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_irq = (pin1 != pin2) ? 1 : 0; + if (hpt363_shared_irq) { + d->bootable = ON_BOARD; + printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2); + } + break; + } } - - 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); - - if (dev2 && !hpt363_shared_irq) { - printk("%s: IDE controller on PCI bus %02x dev %02x\n", - d2->name, dev2->bus->number, dev2->devfn); - ide_setup_pci_device(dev2, d2); - } + 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 --git a/drivers/block/ide-pmac.c b/drivers/block/ide-pmac.c index 1ad5b3b96..c3e800249 100644 --- a/drivers/block/ide-pmac.c +++ b/drivers/block/ide-pmac.c @@ -363,7 +363,8 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) drive->waiting_for_dma = 1; if (drive->media != ide_disk) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD); + drive->timeout = WAIT_CMD; + ide_set_handler(drive, &ide_dma_intr); OUT_BYTE(func==ide_dma_write? WIN_WRITEDMA: WIN_READDMA, IDE_COMMAND_REG); case ide_dma_begin: diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c index 62008341e..d430c5b1d 100644 --- a/drivers/block/ide-probe.c +++ b/drivers/block/ide-probe.c @@ -42,7 +42,6 @@ #include <linux/delay.h> #include <linux/ide.h> - #include <asm/byteorder.h> #include <asm/irq.h> #include <asm/uaccess.h> @@ -85,6 +84,9 @@ static inline void do_identify (ide_drive_t *drive, byte cmd) ide_fixstring (id->fw_rev, sizeof(id->fw_rev), bswap); ide_fixstring (id->serial_no, sizeof(id->serial_no), bswap); + if (strstr(id->model, "E X A B Y T E N E S T")) + return; + id->model[sizeof(id->model)-1] = '\0'; /* we depend on this a lot! */ printk("%s: %s, ", drive->name, id->model); drive->present = 1; @@ -324,6 +326,35 @@ static int do_probe (ide_drive_t *drive, byte cmd) } /* + * + */ +static void enable_nest (ide_drive_t *drive) +{ + unsigned long timeout; + + printk("%s: enabling %s -- ", HWIF(drive)->name, drive->id->model); + SELECT_DRIVE(HWIF(drive), drive); + ide_delay_50ms(); + OUT_BYTE(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG); + timeout = jiffies + WAIT_WORSTCASE; + do { + if (jiffies > timeout) { + printk("failed (timeout)\n"); + return; + } + ide_delay_50ms(); + } while (GET_STAT() & BUSY_STAT); + ide_delay_50ms(); + if (!OK_STAT(GET_STAT(), 0, BAD_STAT)) + printk("failed (status = 0x%02x)\n", GET_STAT()); + else + printk("success\n"); + if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ + (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ + } +} + +/* * probe_for_drive() tests for existence of a given drive using do_probe(). * * Returns: 0 no device was found @@ -336,6 +367,8 @@ static inline byte probe_for_drive (ide_drive_t *drive) if (do_probe(drive, WIN_IDENTIFY) >= 2) { /* if !(success||timed-out) */ (void) do_probe(drive, WIN_PIDENTIFY); /* look for ATAPI device */ } + if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T")) + enable_nest(drive); if (!drive->present) return 0; /* drive not found */ if (drive->id == NULL) { /* identification failed? */ diff --git a/drivers/block/ide-proc.c b/drivers/block/ide-proc.c index 8afe1568f..48d77c160 100644 --- a/drivers/block/ide-proc.c +++ b/drivers/block/ide-proc.c @@ -73,14 +73,21 @@ #define MIN(a,b) (((a) < (b)) ? (a) : (b)) #endif -#ifdef CONFIG_BLK_DEV_VIA82C586 -int (*via_display_info)(char *, char **, off_t, int, int) = NULL; -#endif /* CONFIG_BLK_DEV_VIA82C586 */ - #ifdef CONFIG_BLK_DEV_ALI15X3 +extern byte ali_proc; int (*ali_display_info)(char *, char **, off_t, int, int) = NULL; #endif /* CONFIG_BLK_DEV_ALI15X3 */ +#ifdef CONFIG_BLK_DEV_SIS5513 +extern byte sis_proc; +int (*sis_display_info)(char *, char **, off_t, int, int) = NULL; +#endif /* CONFIG_BLK_DEV_SIS5513 */ + +#ifdef CONFIG_BLK_DEV_VIA82CXXX +extern byte via_proc; +int (*via_display_info)(char *, char **, off_t, int, int) = NULL; +#endif /* CONFIG_BLK_DEV_VIA82CXXX */ + static int ide_getxdigit(char c) { int digit; @@ -243,7 +250,27 @@ static int proc_ide_write_config } #endif /* CONFIG_BLK_DEV_IDEPCI */ } else { /* not pci */ -#ifndef CONFIG_Q40 +#if !defined(__mc68000__) && !defined(CONFIG_APUS) + +/* + * Geert Uytterhoeven + * + * unless you can explain me what it really does. + * On m68k, we don't have outw() and outl() yet, + * and I need a good reason to implement it. + * + * BTW, IMHO the main remaining portability problem with the IDE driver + * is that it mixes IO (ioport) and MMIO (iomem) access on different platforms. + * + * I think all accesses should be done using + * + * ide_in[bwl](ide_device_instance, offset) + * ide_out[bwl](ide_device_instance, value, offset) + * + * so the architecture specific code can #define ide_{in,out}[bwl] to the + * appropriate function. + * + */ switch (digits) { case 2: outb(val, reg); break; @@ -252,7 +279,7 @@ static int proc_ide_write_config case 8: outl(val, reg); break; } -#endif /* CONFIG_Q40 */ +#endif /* !__mc68000__ && !CONFIG_APUS */ } } } @@ -750,18 +777,24 @@ void proc_ide_create(void) ent = create_proc_entry("drivers", 0, proc_ide_root); if (!ent) return; ent->read_proc = proc_ide_read_drivers; -#ifdef CONFIG_BLK_DEV_VIA82C586 - if (via_display_info) { - ent = create_proc_entry("via", 0, proc_ide_root); - ent->get_info = via_display_info; - } -#endif /* CONFIG_BLK_DEV_VIA82C586 */ #ifdef CONFIG_BLK_DEV_ALI15X3 - if (ali_display_info) { + if ((ali_display_info) && (ali_proc)) { ent = create_proc_entry("ali", 0, proc_ide_root); ent->get_info = ali_display_info; } #endif /* CONFIG_BLK_DEV_ALI15X3 */ +#ifdef CONFIG_BLK_DEV_SIS5513 + if ((sis_display_info) && (sis_proc)) { + ent = create_proc_entry("sis", 0, proc_ide_root); + ent->get_info = sis_display_info; + } +#endif /* CONFIG_BLK_DEV_SIS5513 */ +#ifdef CONFIG_BLK_DEV_VIA82CXXX + if ((via_display_info) && (via_proc)) { + ent = create_proc_entry("via", 0, proc_ide_root); + ent->get_info = via_display_info; + } +#endif /* CONFIG_BLK_DEV_VIA82CXXX */ } void proc_ide_destroy(void) @@ -770,14 +803,18 @@ void proc_ide_destroy(void) * Mmmm.. does this free up all resources, * or do we need to do a more proper cleanup here ?? */ -#ifdef CONFIG_BLK_DEV_VIA82C586 - if (via_display_info) - remove_proc_entry("ide/via",0); -#endif /* CONFIG_BLK_DEV_VIA82C586 */ #ifdef CONFIG_BLK_DEV_ALI15X3 - if (ali_display_info) + if ((ali_display_info) && (ali_proc)) remove_proc_entry("ide/ali",0); #endif /* CONFIG_BLK_DEV_ALI15X3 */ +#ifdef CONFIG_BLK_DEV_SIS5513 + if ((sis_display_info) && (sis_proc)) + remove_proc_entry("ide/sis", 0); +#endif /* CONFIG_BLK_DEV_SIS5513 */ +#ifdef CONFIG_BLK_DEV_VIA82CXXX + if ((via_display_info) && (via_proc)) + remove_proc_entry("ide/via",0); +#endif /* CONFIG_BLK_DEV_VIA82CXXX */ remove_proc_entry("ide/drivers", 0); destroy_proc_ide_interfaces(); remove_proc_entry("ide", 0); diff --git a/drivers/block/ide-tape.c b/drivers/block/ide-tape.c index 6e8313733..bbf222338 100644 --- a/drivers/block/ide-tape.c +++ b/drivers/block/ide-tape.c @@ -1833,7 +1833,7 @@ static void idetape_pc_intr (ide_drive_t *drive) 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); - ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD); + ide_set_handler (drive,&idetape_pc_intr); return; } #if IDETAPE_DEBUG_LOG @@ -1855,7 +1855,7 @@ static void idetape_pc_intr (ide_drive_t *drive) pc->actually_transferred+=bcount.all; /* Update the current position */ pc->current_position+=bcount.all; - ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD); /* And set the interrupt handler again */ + ide_set_handler (drive,&idetape_pc_intr); /* And set the interrupt handler again */ } /* @@ -1928,7 +1928,7 @@ static void idetape_transfer_pc(ide_drive_t *drive) ide_do_reset (drive); return; } - ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD); /* Set the interrupt routine */ + ide_set_handler(drive, &idetape_pc_intr); /* Set the interrupt routine */ atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */ } @@ -1995,7 +1995,7 @@ static void idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc) } #endif /* CONFIG_BLK_DEV_IDEDMA */ if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { - ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD); + ide_set_handler(drive, &idetape_transfer_pc); OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); } else { OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); @@ -3579,6 +3579,7 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) spin_lock_init(&tape->spinlock); drive->driver_data = tape; drive->ready_stat = 0; /* An ATAPI device ignores DRDY */ + drive->timeout = IDETAPE_WAIT_CMD; #ifdef CONFIG_BLK_DEV_IDEPCI /* * These two ide-pci host adapters appear to need this disabled. diff --git a/drivers/block/ide.c b/drivers/block/ide.c index d2cb4b34b..f0c9d58da 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -149,9 +149,9 @@ #include <linux/kmod.h> #endif /* CONFIG_KMOD */ -#ifdef CONFIG_BLK_DEV_VIA82C586 -extern byte fifoconfig; /* defined in via82c586.c used by ide_setup()*/ -#endif +#ifdef CONFIG_BLK_DEV_VIA82CXXX +extern byte fifoconfig; /* defined in via82cxxx.c used by ide_setup() */ +#endif /* CONFIG_BLK_DEV_VIA82CXXX */ static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, @@ -498,13 +498,25 @@ void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup) } /* + * The below two are helpers used when modifying the drive timeout. + */ +static inline unsigned long set_timeout(ide_drive_t *drive, unsigned long timeout) +{ + unsigned long foo = drive->timeout; + drive->timeout = timeout; + return foo; +} + +#define restore_timeout(drive, old) (drive->timeout = old) + +/* * This should get invoked any time we exit the driver to * wait for an interrupt response from a drive. handler() points * at the appropriate code to handle the next interrupt, and a * timer is started to prevent us from waiting forever in case * something goes wrong (see the ide_timer_expiry() handler later on). */ -void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout) +void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler) { unsigned long flags; ide_hwgroup_t *hwgroup = HWGROUP(drive); @@ -517,8 +529,11 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int t } #endif hwgroup->handler = handler; - hwgroup->timer.expires = jiffies + timeout; - add_timer(&(hwgroup->timer)); + /* 0 means don't timeout */ + if (drive->timeout && !timer_pending(&hwgroup->timer)) { + hwgroup->timer.expires = jiffies + drive->timeout; + add_timer(&(hwgroup->timer)); + } spin_unlock_irqrestore(&hwgroup->spinlock, flags); } @@ -565,6 +580,7 @@ static void do_reset1 (ide_drive_t *, int); /* needed below */ static void atapi_reset_pollfunc (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); + unsigned long old_timeout; byte stat; SELECT_DRIVE(HWIF(drive),drive); @@ -574,7 +590,9 @@ static void atapi_reset_pollfunc (ide_drive_t *drive) printk("%s: ATAPI reset complete\n", drive->name); } else { if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { - ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20); + old_timeout = set_timeout(drive, HZ / 20); + ide_set_handler (drive, &atapi_reset_pollfunc); + restore_timeout(drive, old_timeout); return; /* continue polling */ } hwgroup->poll_timeout = 0; /* end of polling */ @@ -595,11 +613,14 @@ static void reset_pollfunc (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); + unsigned long old_timeout; byte tmp; if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) { if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) { - ide_set_handler (drive, &reset_pollfunc, HZ/20); + old_timeout = set_timeout(drive, HZ / 20); + ide_set_handler (drive, &reset_pollfunc); + restore_timeout(drive, old_timeout); return; /* continue polling */ } printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); @@ -667,6 +688,7 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi) unsigned long flags; ide_hwif_t *hwif = HWIF(drive); ide_hwgroup_t *hwgroup = HWGROUP(drive); + unsigned long old_timeout; __save_flags(flags); /* local CPU only */ __cli(); /* local CPU only */ @@ -678,7 +700,9 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi) udelay (20); OUT_BYTE (WIN_SRST, IDE_COMMAND_REG); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20); + old_timeout = set_timeout(drive, HZ / 20); + ide_set_handler (drive, &atapi_reset_pollfunc); + restore_timeout(drive, old_timeout); __restore_flags (flags); /* local CPU only */ return; } @@ -708,7 +732,18 @@ static void do_reset1 (ide_drive_t *drive, int do_not_try_atapi) OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */ udelay(10); /* more than enough time */ hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler (drive, &reset_pollfunc, HZ/20); + old_timeout = set_timeout(drive, HZ / 20); + ide_set_handler (drive, &reset_pollfunc); + restore_timeout(drive, old_timeout); + + /* + * Some weird controller like resetting themselves to a strange + * state when the disks are reset this way. At least, the Winbond + * 553 documentation says that + */ + if (hwif->resetproc != NULL) + hwif->resetproc(drive); + #endif /* OK_TO_RESET_CONTROLLER */ __restore_flags (flags); /* local CPU only */ @@ -899,7 +934,7 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat) */ void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler) { - ide_set_handler (drive, handler, WAIT_CMD); + ide_set_handler (drive, handler); if (IDE_CONTROL_REG) OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ OUT_BYTE(nsect,IDE_NSECTOR_REG); @@ -1018,6 +1053,10 @@ static void execute_drive_cmd (ide_drive_t *drive, struct request *rq) if (args[0] == WIN_SMART) { OUT_BYTE(0x4f, IDE_LCYL_REG); OUT_BYTE(0xc2, IDE_HCYL_REG); + OUT_BYTE(args[2],IDE_FEATURE_REG); + OUT_BYTE(args[1],IDE_SECTOR_REG); + ide_cmd(drive, args[0], args[3], &drive_cmd_intr); + return; } OUT_BYTE(args[2],IDE_FEATURE_REG); ide_cmd(drive, args[0], args[1], &drive_cmd_intr); @@ -1218,13 +1257,37 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags bdev->current_request = hwgroup->rq = drive->queue; spin_unlock_irqrestore(&io_request_lock, io_flags); +#if 0 if (hwif->irq != masked_irq) - disable_irq(hwif->irq); + disable_irq_nosync(hwif->irq); spin_unlock_irqrestore(&hwgroup->spinlock, *hwgroup_flags); start_request(drive); spin_lock_irqsave(&hwgroup->spinlock, *hwgroup_flags); if (hwif->irq != masked_irq) enable_irq(hwif->irq); +#else + + if (masked_irq && hwif->irq != masked_irq) { + printk("%s: (disable_irq) %smasked_irq %d\n", + drive->name, + masked_irq ? "" : "un_", hwif->irq); + +#if 0 + disable_irq(hwif->irq); +#else + disable_irq_nosync(hwif->irq); +#endif + } + spin_unlock_irqrestore(&hwgroup->spinlock, *hwgroup_flags); + start_request(drive); + spin_lock_irqsave(&hwgroup->spinlock, *hwgroup_flags); + if (masked_irq && hwif->irq != masked_irq) { + printk("%s: (enable_irq) %smasked_irq %d\n", + drive->name, + masked_irq ? "" : "un_", hwif->irq); + enable_irq(hwif->irq); + } +#endif } } @@ -1373,8 +1436,8 @@ void ide_timer_expiry (unsigned long data) } hwgroup->busy = 1; /* should already be "1" */ hwgroup->handler = NULL; - del_timer(&hwgroup->timer); /* Is this needed?? */ - if (hwgroup->poll_timeout != 0) { /* polling in progress? */ + /* polling in progress or just don't timeout */ + if (hwgroup->poll_timeout != 0) { spin_unlock_irqrestore(&hwgroup->spinlock, flags); handler(drive); } else if (drive_is_ready(drive)) { @@ -1612,8 +1675,10 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio } spin_unlock_irqrestore(&io_request_lock, flags); do_hwgroup_request(hwgroup); - if (action == ide_wait && rq->rq_status != RQ_INACTIVE) + if (action == ide_wait) { down(&sem); /* wait for it to be serviced */ + rq->sem = NULL; + } return rq->errors ? -EIO : 0; /* return -EIO if errors */ } @@ -2270,8 +2335,13 @@ void ide_delay_50ms (void) int ide_config_drive_speed (ide_drive_t *drive, byte speed) { + struct hd_driveid *id = drive->id; + unsigned long flags; int err; + __save_flags(flags); /* local CPU only */ + __cli(); /* local CPU only */ + /* * Don't use ide_wait_cmd here - it will * attempt to set_geometry and recalibrate, @@ -2287,6 +2357,109 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed) err = ide_wait_stat(drive, DRIVE_READY, BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD); +#if 0 + if (IDE_CONTROL_REG) + OUT_BYTE(drive->ctl, IDE_CONTROL_REG); +#endif + + __restore_flags(flags); /* local CPU only */ + + switch(speed) { + case XFER_UDMA_4: + if (!((id->dma_ultra >> 8) & 16)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x1010; + } + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_UDMA_3: + if (!((id->dma_ultra >> 8) & 8)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0808; + } + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_UDMA_2: + if (!((id->dma_ultra >> 8) & 4)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0404; + } + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_UDMA_1: + if (!((id->dma_ultra >> 8) & 2)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0202; + } + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_UDMA_0: + if (!((id->dma_ultra >> 8) & 1)) { + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_ultra |= 0x0101; + } + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_MW_DMA_2: + drive->id->dma_ultra &= ~0xFF00; + if (!((id->dma_mword >> 8) & 4)) { + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_mword |= 0x0404; + } + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_MW_DMA_1: + drive->id->dma_ultra &= ~0xFF00; + if (!((id->dma_mword >> 8) & 2)) { + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_mword |= 0x0202; + } + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_MW_DMA_0: + drive->id->dma_ultra &= ~0xFF00; + if (!((id->dma_mword >> 8) & 1)) { + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_mword |= 0x0101; + } + drive->id->dma_1word &= ~0x0F00; + break; + case XFER_SW_DMA_2: + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + if (!((id->dma_1word >> 8) & 4)) { + drive->id->dma_1word &= ~0x0F00; + drive->id->dma_1word |= 0x0404; + } + break; + case XFER_SW_DMA_1: + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + if (!((id->dma_1word >> 8) & 2)) { + drive->id->dma_1word &= ~0x0F00; + drive->id->dma_1word |= 0x0202; + } + break; + case XFER_SW_DMA_0: + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + if (!((id->dma_1word >> 8) & 1)) { + drive->id->dma_1word &= ~0x0F00; + drive->id->dma_1word |= 0x0101; + } + break; + default: + drive->id->dma_ultra &= ~0xFF00; + drive->id->dma_mword &= ~0x0F00; + drive->id->dma_1word &= ~0x0F00; + break; + } + return(err); } @@ -2803,7 +2976,7 @@ void __init ide_setup (char *s) } } -#if defined(CONFIG_BLK_DEV_VIA82C586) +#if defined(CONFIG_BLK_DEV_VIA82CXXX) /* * Look for drive option "splitfifo=..." */ @@ -2853,7 +3026,7 @@ void __init ide_setup (char *s) fifoconfig = tmp; goto done; } -#endif /* defined(CONFIG_BLK_DEV_VIA82C586) */ +#endif /* defined(CONFIG_BLK_DEV_VIA82CXXX) */ if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e') goto bad_option; @@ -3393,6 +3566,7 @@ EXPORT_SYMBOL(do_ide9_request); EXPORT_SYMBOL(ide_scan_devices); 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); @@ -3464,7 +3638,11 @@ static void __init parse_options (char *line) while ((line = next) != NULL) { if ((next = strchr(line,' ')) != NULL) *next++ = 0; - if (!strncmp(line,"ide",3) || (!strncmp(line,"hd",2) && line[2] != '=')) + if (!strncmp(line,"ide",3) || +#ifdef CONFIG_BLK_DEV_VIA82CXXX + !strncmp(line,"splitfifo",9) || +#endif /* CONFIG_BLK_DEV_VIA82CXXX */ + (!strncmp(line,"hd",2) && line[2] != '=')) ide_setup(line); } } diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 0114dd8ec..9366a8856 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -416,10 +416,6 @@ void make_request(int major,int rw, struct buffer_head * bh) count = bh->b_size >> 9; sector = bh->b_rsector; - /* We'd better have a real physical mapping! */ - if (!buffer_mapped(bh)) - BUG(); - /* It had better not be a new buffer by the time we see it */ if (buffer_new(bh)) BUG(); @@ -480,6 +476,13 @@ void make_request(int major,int rw, struct buffer_head * bh) goto end_io; } + /* We'd better have a real physical mapping! + Check this bit only if the buffer was dirty and just locked + down by us so at this point flushpage will block and + won't clear the mapped bit under us. */ + if (!buffer_mapped(bh)) + BUG(); + /* look for a free request. */ /* Loop uses two requests, 1 for loop and 1 for the real device. * Cut max_req in half to avoid running out and deadlocking. */ @@ -694,7 +697,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[]) sorry: for (i = 0; i < nr; i++) { - clear_bit(BH_Dirty, &bh[i]->b_state); + mark_buffer_clean(bh[i]); /* remeber to refile it */ clear_bit(BH_Uptodate, &bh[i]->b_state); bh[i]->b_end_io(bh[i], 0); } diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 027517320..96e0e421e 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -214,8 +214,11 @@ static int pcd_drive_reset(struct cdrom_device_info *cdi); static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn); static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg); +static int pcd_packet(struct cdrom_device_info *cdi, + struct cdrom_generic_command *cgc); static int pcd_detect(void); +static void pcd_probe_capabilities(void); static void do_pcd_read_drq(void); static void do_pcd_request(void); static void do_pcd_read(void); @@ -276,14 +279,18 @@ static struct cdrom_device_ops pcd_dops = { pcd_drive_reset, pcd_audio_ioctl, 0, /* dev_ioctl */ - CDC_CLOSE_TRAY | - CDC_OPEN_TRAY | - CDC_LOCK | - CDC_MCN | - CDC_MEDIA_CHANGED | - CDC_RESET | - CDC_PLAY_AUDIO, - 0 + CDC_CLOSE_TRAY | + CDC_OPEN_TRAY | + CDC_LOCK | + CDC_MCN | + CDC_MEDIA_CHANGED | + CDC_RESET | + CDC_PLAY_AUDIO | + CDC_GENERIC_PACKET | + CDC_CD_R | + CDC_CD_RW, + 0, + pcd_packet, }; static void pcd_init_units( void ) @@ -325,6 +332,9 @@ int pcd_init (void) /* preliminary initialisation */ if (pcd_detect()) return -1; + /* get the atapi capabilities page */ + pcd_probe_capabilities(); + if (register_blkdev(MAJOR_NR,name,&cdrom_fops)) { printk("pcd: unable to get major number %d\n",MAJOR_NR); return -1; @@ -525,6 +535,16 @@ static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun ) return r; } +static int pcd_packet(struct cdrom_device_info *cdi, + struct cdrom_generic_command *cgc) +{ + char *un_cmd; + int unit = DEVICE_NR(cdi->dev); + + un_cmd = cgc->cmd; + return pcd_atapi(unit,un_cmd,cgc->buflen,cgc->buffer, "generic packet"); +} + #define DBMSG(msg) ((verbose>1)?(msg):NULL) static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr) @@ -667,6 +687,32 @@ static int pcd_probe( int unit, int ms, char * id ) return -1; } +static void pcd_probe_capabilities( void ) + +{ int unit, r; + char buffer[32]; + char cmd[12]={0x5a,1<<3,0x2a,0,0,0,0,18,0,0,0,0}; + + for (unit=0;unit<PCD_UNITS;unit++) { + if (!PCD.present) continue; + r = pcd_atapi(unit,cmd,18, buffer,"mode sense capabilities"); + if (r) continue; + /* we should now have the cap page */ + if ((buffer[11] & 1) == 0) + PCD.info.mask |= CDC_CD_R; + if ((buffer[11] & 2) == 0) + PCD.info.mask |= CDC_CD_RW; + if ((buffer[12] & 1) == 0) + PCD.info.mask |= CDC_PLAY_AUDIO; + if ((buffer[14] & 1) == 0) + PCD.info.mask |= CDC_LOCK; + if ((buffer[14] & 8) == 0) + PCD.info.mask |= CDC_OPEN_TRAY; + if ((buffer[14] >> 6) == 0) + PCD.info.mask |= CDC_CLOSE_TRAY; + } +} + static int pcd_detect( void ) { char id[18]; @@ -836,63 +882,6 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi, switch (cmd) { - case CDROMPAUSE: - - { char cmd[12]={GPCMD_PAUSE_RESUME,0,0,0,0,0,0,0,0,0,0,0}; - - return (pcd_atapi(unit,cmd,0,NULL,"pause")) * EIO; - } - - case CDROMRESUME: - - { char cmd[12]={GPCMD_PAUSE_RESUME,0,0,0,0,0,0,0,1,0,0,0}; - - return (pcd_atapi(unit,cmd,0,NULL,"resume")) * EIO; - } - - case CDROMPLAYMSF: - - { char cmd[12]={GPCMD_PLAY_AUDIO_MSF,0,0,0,0,0,0,0,0,0,0,0}; - struct cdrom_msf* msf = (struct cdrom_msf*)arg; - - cmd[3] = msf->cdmsf_min0; - cmd[4] = msf->cdmsf_sec0; - cmd[5] = msf->cdmsf_frame0; - cmd[6] = msf->cdmsf_min1; - cmd[7] = msf->cdmsf_sec1; - cmd[8] = msf->cdmsf_frame1; - - return (pcd_atapi(unit,cmd,0,NULL,"play msf")) * EIO; - } - - case CDROMPLAYBLK: - - { char cmd[12]={GPCMD_PLAY_AUDIO_10,0,0,0,0,0,0,0,0,0,0,0}; - struct cdrom_blk* blk = (struct cdrom_blk*)arg; - - cmd[2] = blk->from >> 24; - cmd[3] = blk->from >> 16; - cmd[4] = blk->from >> 8; - cmd[5] = blk->from; - cmd[7] = blk->len >> 8; - cmd[8] = blk->len; - - return (pcd_atapi(unit,cmd,0,NULL,"play block")) * EIO; - } - - case CDROMPLAYTRKIND: - - { char cmd[12]={GPCMD_PLAYAUDIO_TI,0,0,0,0,0,0,0,0,0,0,0}; - struct cdrom_ti* ti = (struct cdrom_ti*)arg; - - cmd[4] = ti->cdti_trk0; - cmd[5] = ti->cdti_ind0; - cmd[7] = ti->cdti_trk1; - cmd[8] = ti->cdti_ind1; - - return (pcd_atapi(unit,cmd,0,NULL,"play track")) * EIO; - } - case CDROMREADTOCHDR: { char cmd[12]={GPCMD_READ_TOC_PMA_ATIP,0,0,0,0,0,0,0,12,0,0,0}; @@ -936,97 +925,6 @@ static int pcd_audio_ioctl(struct cdrom_device_info *cdi, return r * EIO; } - case CDROMSTOP: - - { char cmd[12]={GPCMD_START_STOP_UNIT,1,0,0,0,0,0,0,0,0,0,0}; - - return (pcd_atapi(unit,cmd,0,NULL,"stop")) * EIO; - } - - case CDROMSTART: - - { char cmd[12]={GPCMD_START_STOP_UNIT,1,0,0,1,0,0,0,0,0,0,0}; - - return (pcd_atapi(unit,cmd,0,NULL,"start")) * EIO; - } - - case CDROMVOLCTRL: - - { char cmd[12]={GPCMD_MODE_SENSE_10,0,0,0,0,0,0,0,0,0,0,0}; - char buffer[32]; - char mask[32]; - struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg; - - cmd[2] = 0xe; - cmd[4] = 28; - - if (pcd_atapi(unit,cmd,28,buffer,"mode sense vol")) - return -EIO; - - cmd[2] = 0x4e; - - if (pcd_atapi(unit,cmd,28,buffer,"mode sense vol mask")) - return -EIO; - - buffer[0] = 0; - - buffer[21] = volctrl->channel0 & mask[21]; - buffer[23] = volctrl->channel1 & mask[23]; - buffer[25] = volctrl->channel2 & mask[25]; - buffer[27] = volctrl->channel3 & mask[27]; - - cmd[0] = 0x55; - cmd[1] = 0x10; - - return pcd_atapi(unit,cmd,28,buffer,"mode select vol") * EIO; - } - - case CDROMVOLREAD: - - { char cmd[12]={GPCMD_MODE_SENSE_10,0,0,0,0,0,0,0,0,0,0,0}; - char buffer[32]; - struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg; - int r; - - cmd[2] = 0xe; - cmd[4] = 28; - - r = pcd_atapi(unit,cmd,28,buffer,"mode sense vol read"); - - volctrl->channel0 = buffer[21]; - volctrl->channel1 = buffer[23]; - volctrl->channel2 = buffer[25]; - volctrl->channel3 = buffer[27]; - - return r * EIO; - } - - - case CDROMSUBCHNL: - - { char cmd[12]={GPCMD_READ_SUBCHANNEL,2,0x40,1,0,0,0,0,16,0,0,0}; - struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg; - char buffer[32]; - - if (pcd_atapi(unit,cmd,16,buffer,"read subchannel")) - return -EIO; - - subchnl->cdsc_audiostatus = buffer[1]; - subchnl->cdsc_format = CDROM_MSF; - subchnl->cdsc_ctrl = buffer[5] & 0xf; - subchnl->cdsc_trk = buffer[6]; - subchnl->cdsc_ind = buffer[7]; - - subchnl->cdsc_reladdr.msf.minute = buffer[13]; - subchnl->cdsc_reladdr.msf.second = buffer[14]; - subchnl->cdsc_reladdr.msf.frame = buffer[15]; - subchnl->cdsc_absaddr.msf.minute = buffer[9]; - subchnl->cdsc_absaddr.msf.second = buffer[10]; - subchnl->cdsc_absaddr.msf.frame = buffer[11]; - - return 0; - } - default: return -ENOSYS; diff --git a/drivers/block/pdc202xx.c b/drivers/block/pdc202xx.c index aeffcc9ba..2155aa8af 100644 --- a/drivers/block/pdc202xx.c +++ b/drivers/block/pdc202xx.c @@ -1,8 +1,8 @@ /* - * linux/drivers/block/pdc202xx.c Version 0.26 May 12, 1999 + * linux/drivers/block/pdc202xx.c Version 0.27 Sept. 3, 1999 * - * Copyright (C) 1998-99 Andre Hedrick - * (hedrick@astro.dyer.vanderbilt.edu) + * Copyright (C) 1998-99 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * * 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. @@ -72,6 +72,12 @@ * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); */ +/* + * Portions Copyright (C) 1999 Promise Technology, Inc. + * Author: Frank Tiernan (frankt@promise.com) + * Released under terms of General Public License + */ + #include <linux/types.h> #include <linux/kernel.h> #include <linux/delay.h> @@ -88,6 +94,8 @@ #include <asm/io.h> #include <asm/irq.h> +#include "ide_modes.h" + #define PDC202XX_DEBUG_DRIVE_INFO 0 #define PDC202XX_DECODE_REGISTER_INFO 0 @@ -208,27 +216,78 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; + unsigned long high_16 = dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK; int err; unsigned int drive_conf; byte drive_pci; - byte test1, test2, speed; - byte AP, BP, CP, DP, EP; + byte test1, test2, speed = -1; + byte AP, BP, CP, DP, TB, TC; + unsigned short EP; + byte CLKSPD = IN_BYTE(high_16 + 0x11); int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); byte udma_66 = ((id->word93 & 0x2000) && (hwif->udma_four)) ? 1 : 0; - byte udma_33 = ultra ? (inb((dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK) + 0x001f) & 1) : 0; - - pci_read_config_byte(dev, 0x50, &EP); + byte udma_33 = ultra ? (inb(high_16 + 0x001f) & 1) : 0; + + /* + * Set the control register to use the 66Mhz system + * clock for UDMA 3/4 mode operation. If one drive on + * a channel is U66 capable but the other isn't we + * fall back to U33 mode. The BIOS INT 13 hooks turn + * the clock on then off for each read/write issued. I don't + * do that here because it would require modifying the + * kernel, seperating the fop routines from the kernel or + * somehow hooking the fops calls. It may also be possible to + * leave the 66Mhz clock on and readjust the timing + * parameters. + */ + + byte mask = hwif->channel ? 0x08 : 0x02; + unsigned short c_mask = hwif->channel ? (1<<11) : (1<<10); + byte ultra_66 = ((id->dma_ultra & 0x0010) || (id->dma_ultra & 0x0008)) ? 1 : 0; + + pci_read_config_word(dev, 0x50, &EP); + + if ((ultra_66) && (EP & c_mask)) { +#ifdef DEBUG + printk("ULTRA66: %s channel of Ultra 66 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 */ + /* Secondary : zero out fourth bit */ + OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11)); + } else { + if (ultra_66) { + /* + * check to make sure drive on same channel + * is u66 capable + */ + if (hwif->drives[!(drive_number%2)].id) { + if ((hwif->drives[!(drive_number%2)].id->dma_ultra & 0x0010) || + (hwif->drives[!(drive_number%2)].id->dma_ultra & 0x0008)) { + OUT_BYTE(CLKSPD | mask, (high_16 + 0x11)); + } else { + OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11)); + } + } else { /* udma4 drive by itself */ + OUT_BYTE(CLKSPD | mask, (high_16 + 0x11)); + } + } + } switch(drive_number) { case 0: drive_pci = 0x60; pci_read_config_dword(dev, drive_pci, &drive_conf); + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + goto chipset_is_set; pci_read_config_byte(dev, (drive_pci), &test1); if (!(test1 & SYNC_ERRDY_EN)) pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN); break; case 1: drive_pci = 0x64; pci_read_config_dword(dev, drive_pci, &drive_conf); + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + goto chipset_is_set; pci_read_config_byte(dev, 0x60, &test1); pci_read_config_byte(dev, (drive_pci), &test2); if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN)) @@ -236,12 +295,16 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) break; case 2: drive_pci = 0x68; pci_read_config_dword(dev, drive_pci, &drive_conf); + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + goto chipset_is_set; pci_read_config_byte(dev, (drive_pci), &test1); if (!(test1 & SYNC_ERRDY_EN)) pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN); break; case 3: drive_pci = 0x6c; pci_read_config_dword(dev, drive_pci, &drive_conf); + if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) + goto chipset_is_set; pci_read_config_byte(dev, 0x68, &test1); pci_read_config_byte(dev, (drive_pci), &test2); if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN)) @@ -251,6 +314,8 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) return ide_dma_off; } +chipset_is_set: + if (drive->media != ide_disk) return ide_dma_off_quietly; @@ -285,127 +350,46 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) pci_read_config_byte(dev, (drive_pci)|0x02, &CP); if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) { - if (!((id->dma_ultra >> 8) & 16)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x1010; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } /* speed 8 == UDMA mode 4 == speed 6 plus cable */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x20); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x01); - speed = XFER_UDMA_4; + speed = XFER_UDMA_4; TB = 0x20; TC = 0x01; } else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) { - if (!((id->dma_ultra >> 8) & 8)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0808; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } /* speed 7 == UDMA mode 3 == speed 5 plus cable */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x40); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x02); - speed = XFER_UDMA_3; + speed = XFER_UDMA_3; TB = 0x40; TC = 0x02; } else if ((id->dma_ultra & 0x0004) && (udma_33)) { - if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } /* speed 6 == UDMA mode 2 */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x20); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x01); - speed = XFER_UDMA_2; + speed = XFER_UDMA_2; TB = 0x20; TC = 0x01; } else if ((id->dma_ultra & 0x0002) && (udma_33)) { - if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } /* speed 5 == UDMA mode 1 */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x40); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x02); - speed = XFER_UDMA_1; + speed = XFER_UDMA_1; TB = 0x40; TC = 0x02; } else if ((id->dma_ultra & 0x0001) && (udma_33)) { - if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } /* speed 4 == UDMA mode 0 */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x03); - speed = XFER_UDMA_0; + speed = XFER_UDMA_0; TB = 0x60; TC = 0x03; } else if (id->dma_mword & 0x0004) { - if (!((id->dma_mword >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0404; - drive->id->dma_1word &= ~0x0F00; - } /* speed 4 == DMA mode 2 multi-word */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x03); - speed = XFER_MW_DMA_2; + speed = XFER_MW_DMA_2; TB = 0x60; TC = 0x03; } else if (id->dma_mword & 0x0002) { - if (!((id->dma_mword >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0202; - drive->id->dma_1word &= ~0x0F00; - } /* speed 3 == DMA mode 1 multi-word */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x04); - speed = XFER_MW_DMA_1; + speed = XFER_MW_DMA_1; TB = 0x60; TC = 0x04; } else if (id->dma_mword & 0x0001) { - if (!((id->dma_mword >> 8) & 1)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0101; - drive->id->dma_1word &= ~0x0F00; - } /* speed 2 == DMA mode 0 multi-word */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x05); - speed = XFER_MW_DMA_0; + speed = XFER_MW_DMA_0; TB = 0x60; TC = 0x05; } else if (id->dma_1word & 0x0004) { - if (!((id->dma_1word >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0404; - } /* speed 2 == DMA mode 2 single-word */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x05); - speed = XFER_SW_DMA_2; + speed = XFER_SW_DMA_2; TB = 0x60; TC = 0x05; } else if (id->dma_1word & 0x0002) { - if (!((id->dma_1word >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0202; - } /* speed 1 == DMA mode 1 single-word */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x80); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x06); - speed = XFER_SW_DMA_1; + speed = XFER_SW_DMA_1; TB = 0x80; TC = 0x06; } else if (id->dma_1word & 0x0001) { - if (!((id->dma_1word >> 8) & 1)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0101; - } /* speed 0 == DMA mode 0 single-word */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP|0xC0); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x0B); - speed = XFER_SW_DMA_0; + speed = XFER_SW_DMA_0; TB = 0xC0; TC = 0x0B; } else { /* restore original pci-config space */ pci_write_config_dword(dev, drive_pci, drive_conf); return ide_dma_off_quietly; } - err = ide_config_drive_speed(drive, speed); + pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); + pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); #if PDC202XX_DECODE_REGISTER_INFO pci_read_config_byte(dev, (drive_pci), &AP); @@ -418,6 +402,8 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) decode_registers(REG_D, DP); #endif /* PDC202XX_DECODE_REGISTER_INFO */ + err = ide_config_drive_speed(drive, speed); + #if PDC202XX_DEBUG_DRIVE_INFO printk("%s: %s drive%d 0x%08x ", drive->name, ide_xfer_verbose(speed), @@ -441,6 +427,83 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) * 11, 5, 4, 3, 2, 1, 0 */ +static int config_chipset_for_pio (ide_drive_t *drive, byte pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + byte drive_pci, speed; + byte AP, BP, TA, TB; + + int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + int err; + + switch (drive_number) { + case 0: drive_pci = 0x60; break; + case 1: drive_pci = 0x64; break; + case 2: drive_pci = 0x68; break; + case 3: drive_pci = 0x6c; break; + default: return 1; + } + + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + + + if ((AP & 0x0F) || (BP & 0x07)) { + /* clear PIO modes of lower 8421 bits of A Register */ + pci_write_config_byte(dev, (drive_pci), AP & ~0x0F); + pci_read_config_byte(dev, (drive_pci), &AP); + + /* clear PIO modes of lower 421 bits of B Register */ + pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + } + + pio = (pio == 5) ? 4 : pio; + switch (ide_get_best_pio_mode(drive, 255, pio, NULL)) { + case 4: speed = XFER_PIO_4; TA=0x01; TB=0x04; break; + case 3: speed = XFER_PIO_3; TA=0x02; TB=0x06; break; + case 2: speed = XFER_PIO_2; TA=0x03; TB=0x08; break; + case 1: speed = XFER_PIO_1; TA=0x05; TB=0x0C; break; + case 0: + default: speed = XFER_PIO_0; TA=0x09; TB=0x13; break; + } + pci_write_config_byte(dev, (drive_pci), AP|TA); + pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); + +#if PDC202XX_DECODE_REGISTER_INFO + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + pci_read_config_byte(dev, (drive_pci)|0x03, &DP); + + decode_registers(REG_A, AP); + decode_registers(REG_B, BP); + decode_registers(REG_C, CP); + decode_registers(REG_D, DP); +#endif /* PDC202XX_DECODE_REGISTER_INFO */ + + err = ide_config_drive_speed(drive, speed); + +#if PDC202XX_DEBUG_DRIVE_INFO + printk("%s: %s drive%d 0x%08x ", + drive->name, ide_xfer_verbose(speed), + drive_number, drive_conf); + pci_read_config_dword(dev, drive_pci, &drive_conf); + printk("0x%08x\n", drive_conf); +#endif /* PDC202XX_DEBUG_DRIVE_INFO */ + + return err; +} + +static void pdc202xx_tune_drive (ide_drive_t *drive, byte pio) +{ + (void) config_chipset_for_pio(drive, pio); +} + static int config_drive_xfer_rate (ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -450,9 +513,10 @@ static int config_drive_xfer_rate (ide_drive_t *drive) if (id && (id->capability & 1) && hwif->autodma) { /* Consult the list of known "bad" drives */ if (ide_dmaproc(ide_dma_bad_drive, drive)) { - return HWIF(drive)->dmaproc(ide_dma_off, drive); + dma_func = ide_dma_off; + goto fast_ata_pio; } - + dma_func = ide_dma_off_quietly; if (id->field_valid & 4) { if (id->dma_ultra & 0x001F) { /* Force if Capable UltraDMA */ @@ -463,17 +527,31 @@ static int config_drive_xfer_rate (ide_drive_t *drive) } } else if (id->field_valid & 2) { try_dma_modes: - if ((id->dma_mword & 0x0004) || - (id->dma_1word & 0x0004)) { + if ((id->dma_mword & 0x0007) || + (id->dma_1word & 0x0007)) { /* Force if Capable regular DMA modes */ dma_func = config_chipset_for_dma(drive, 0); + if (dma_func != ide_dma_on) + goto no_dma_set; + } + } else if (ide_dmaproc(ide_dma_good_drive, drive)) { + if (id->eide_dma_time > 150) { + goto no_dma_set; } - } else if ((ide_dmaproc(ide_dma_good_drive, drive)) && - (id->eide_dma_time > 150)) { /* Consult the list of known "good" drives */ dma_func = config_chipset_for_dma(drive, 0); + if (dma_func != ide_dma_on) + goto no_dma_set; + } else { + goto fast_ata_pio; } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: + dma_func = ide_dma_off_quietly; +no_dma_set: + (void) config_chipset_for_pio(drive, 5); } + return HWIF(drive)->dmaproc(dma_func, drive); } @@ -498,6 +576,26 @@ unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name) byte primary_mode = inb(high_16 + 0x001a); byte secondary_mode = inb(high_16 + 0x001b); + if (dev->device == PCI_DEVICE_ID_PROMISE_20262) { + int i = 0; + /* + * software reset - this is required because the bios + * will set UDMA timing on if the hdd supports it. The + * user may want to turn udma off. A bug in the pdc20262 + * is that it cannot handle a downgrade in timing from UDMA + * to DMA. Disk accesses after issuing a set feature command + * will result in errors. A software reset leaves the timing + * registers intact, but resets the drives. + */ + + OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f); + ide_delay_50ms(); + ide_delay_50ms(); + OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f); + for (i=0; i<40; i++) + ide_delay_50ms(); + } + 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); @@ -547,24 +645,23 @@ unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name) return dev->irq; } +unsigned int __init ata66_pdc202xx (ide_hwif_t *hwif) +{ + unsigned short mask = (hwif->channel) ? (1<<11) : (1<<10); + unsigned short CIS; + + pci_read_config_word(hwif->pci_dev, 0x50, &CIS); + return ((CIS & mask) ? 0 : 1); +} + void __init ide_init_pdc202xx (ide_hwif_t *hwif) { + hwif->tuneproc = &pdc202xx_tune_drive; + if (hwif->dma_base) { hwif->dmaproc = &pdc202xx_dmaproc; - - switch(hwif->pci_dev->device) { - case PCI_DEVICE_ID_PROMISE_20262: -#if 0 - { - unsigned long high_16 = hwif->pci_dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK; - hwif->udma_four = 1; - } -#endif - break; - case PCI_DEVICE_ID_PROMISE_20246: - default: - hwif->udma_four = 0; - break; - } + } else { + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; } } diff --git a/drivers/block/pdc4030.c b/drivers/block/pdc4030.c index 84fbb4856..080d353a5 100644 --- a/drivers/block/pdc4030.c +++ b/drivers/block/pdc4030.c @@ -162,6 +162,7 @@ int __init setup_pdc4030 (ide_hwif_t *hwif) if (!hwif) return 0; drive = &hwif->drives[0]; + drive->timeout = HZ/100; hwif2 = &ide_hwifs[hwif->index+1]; if (hwif->chipset == ide_pdc4030) /* we've already been found ! */ return 1; @@ -169,7 +170,8 @@ int __init setup_pdc4030 (ide_hwif_t *hwif) if (IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF) { return 0; } - OUT_BYTE(0x08,IDE_CONTROL_REG); + if (IDE_CONTROL_REG) + OUT_BYTE(0x08,IDE_CONTROL_REG); if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) { return 0; } @@ -307,6 +309,9 @@ static void promise_read_intr (ide_drive_t *drive) unsigned int sectors_left, sectors_avail, nsect; struct request *rq; + /* reset timeout */ + drive->timeout = HZ/100; + if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) { ide_error(drive, "promise_read_intr", stat); return; @@ -361,7 +366,8 @@ read_next: if (stat & DRQ_STAT) goto read_again; if (stat & BUSY_STAT) { - ide_set_handler (drive, &promise_read_intr, WAIT_CMD); + drive->timeout = WAIT_CMD; + ide_set_handler (drive, &promise_read_intr); #ifdef DEBUG_READ printk(KERN_DEBUG "%s: promise_read: waiting for" "interrupt\n", drive->name); @@ -390,7 +396,7 @@ static void promise_complete_pollfunc(ide_drive_t *drive) if (GET_STAT() & BUSY_STAT) { if (time_before(jiffies, hwgroup->poll_timeout)) { - ide_set_handler(drive, &promise_complete_pollfunc, 1); + ide_set_handler(drive, &promise_complete_pollfunc); return; /* continue polling... */ } hwgroup->poll_timeout = 0; @@ -419,7 +425,7 @@ static void promise_write_pollfunc (ide_drive_t *drive) if (IN_BYTE(IDE_NSECTOR_REG) != 0) { if (time_before(jiffies, hwgroup->poll_timeout)) { - ide_set_handler (drive, &promise_write_pollfunc, 1); + ide_set_handler (drive, &promise_write_pollfunc); return; /* continue polling... */ } hwgroup->poll_timeout = 0; @@ -433,7 +439,7 @@ static void promise_write_pollfunc (ide_drive_t *drive) */ ide_multwrite(drive, 4); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler(drive, &promise_complete_pollfunc, 1); + ide_set_handler(drive, &promise_complete_pollfunc); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", drive->name, GET_STAT()); @@ -466,7 +472,7 @@ static void promise_write (ide_drive_t *drive) if (rq->nr_sectors > 4) { ide_multwrite(drive, rq->nr_sectors - 4); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler (drive, &promise_write_pollfunc, 1); + ide_set_handler (drive, &promise_write_pollfunc); } else { /* * There are 4 or fewer sectors to transfer, do them all in one go @@ -474,7 +480,7 @@ static void promise_write (ide_drive_t *drive) */ ide_multwrite(drive, rq->nr_sectors); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - ide_set_handler(drive, &promise_complete_pollfunc, 1); + ide_set_handler(drive, &promise_complete_pollfunc); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " "status = %02x\n", drive->name, GET_STAT()); @@ -517,7 +523,8 @@ void do_pdc4030_io (ide_drive_t *drive, struct request *rq) printk(KERN_DEBUG "%s: read: waiting for " "interrupt\n", drive->name); #endif - ide_set_handler(drive, &promise_read_intr, WAIT_CMD); + drive->timeout = WAIT_CMD; + ide_set_handler(drive, &promise_read_intr); return; } udelay(1); diff --git a/drivers/block/piix.c b/drivers/block/piix.c index b1fd76014..a9bcb347c 100644 --- a/drivers/block/piix.c +++ b/drivers/block/piix.c @@ -1,8 +1,9 @@ /* - * linux/drivers/block/piix.c Version 0.25 July 11, 1999 + * linux/drivers/block/piix.c Version 0.27 Sept. 3, 1999 * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer - * Copyright (C) 1998-1999 Andre Hedrick, Author and Maintainer + * Copyright (C) 1998-1999 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * * PIO mode setting function for Intel chipsets. * For use instead of BIOS settings. @@ -182,30 +183,13 @@ static int piix_config_drive_for_dma(ide_drive_t *drive) } } - if ((id->dma_ultra & 0x0010) && (ultra)) { - goto backspeed; - } else if ((id->dma_ultra & 0x0008) && (ultra)) { - goto backspeed; - } else if ((id->dma_ultra & 0x0004) && (ultra)) { -backspeed: - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0x0F00; - drive->id->dma_ultra |= 0x0404; - } + if (((id->dma_ultra & 0x0010) || (id->dma_ultra & 0x0008) || (id->dma_ultra & 0x0004)) && (ultra)) { u_speed = 2 << (drive_number * 4); if (!(reg4a & u_speed)) { pci_write_config_word(dev, 0x4a, reg4a|u_speed); } speed = XFER_UDMA_2; } else if ((id->dma_ultra & 0x0002) && (ultra)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0x0F00; - drive->id->dma_ultra |= 0x0202; - } u_speed = 1 << (drive_number * 4); if (!(reg4a & u_speed)) { pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); @@ -213,12 +197,6 @@ backspeed: } speed = XFER_UDMA_1; } else if ((id->dma_ultra & 0x0001) && (ultra)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0x0F00; - drive->id->dma_ultra |= 0x0101; - } u_speed = 0 << (drive_number * 4); if (!(reg4a & u_speed)) { pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); @@ -228,32 +206,14 @@ backspeed: } else if (id->dma_mword & 0x0004) { if (reg4a & a_speed) pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - drive->id->dma_ultra &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - if (!((id->dma_mword >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0404; - } speed = XFER_MW_DMA_2; } else if (id->dma_mword & 0x0002) { if (reg4a & a_speed) pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - drive->id->dma_ultra &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - if (!((id->dma_mword >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0202; - } speed = XFER_MW_DMA_1; } else if (id->dma_1word & 0x0004) { if (reg4a & a_speed) pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); - drive->id->dma_ultra &= ~0x0F00; - drive->id->dma_mword &= ~0x0F00; - if (!((id->dma_1word >> 8) & 4)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0404; - } speed = XFER_SW_DMA_2; } else { speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); @@ -264,10 +224,7 @@ backspeed: (void) ide_config_drive_speed(drive, speed); #if PIIX_DEBUG_DRIVE_INFO - printk("%s: %s drive%d ", - drive->name, - ide_xfer_verbose(speed), - drive_number); + printk("%s: %s drive%d ", drive->name, ide_xfer_verbose(speed), drive_number); printk("\n"); #endif /* PIIX_DEBUG_DRIVE_INFO */ @@ -291,7 +248,7 @@ static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive) } #endif /* CONFIG_BLK_DEV_PIIX_TUNING */ -void ide_init_piix (ide_hwif_t *hwif) +void __init ide_init_piix (ide_hwif_t *hwif) { hwif->tuneproc = &piix_tune_drive; diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 7aeb3a30f..7c2b23dab 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -704,8 +704,9 @@ void __init initrd_load(void) #define OF(args) args +#ifndef memzero #define memzero(s, n) memset ((s), 0, (n)) - +#endif typedef unsigned char uch; typedef unsigned short ush; diff --git a/drivers/block/sis5513.c b/drivers/block/sis5513.c index 08bbb1c91..8a3abd025 100644 --- a/drivers/block/sis5513.c +++ b/drivers/block/sis5513.c @@ -1,11 +1,11 @@ /* - * linux/drivers/block/sis5513.c Version 0.06 July 11, 1999 + * linux/drivers/block/sis5513.c Version 0.07 Sept. 3, 1999 * - * Copyright (C) 1999 Andre Hedrick + * Copyright (C) 1999 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * - * drive_number - * = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - * = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); + * Thanks to SIS Taiwan for direct support and hardware. + * Tested and designed on the SiS620/5513 chipset. */ #include <linux/types.h> @@ -27,10 +27,178 @@ #include "ide_modes.h" +#define SIS5513_DEBUG_DRIVE_INFO 0 + +#define DISPLAY_SIS_TIMINGS + static struct pci_dev *host_dev; -#define SIS5513_DEBUG_DRIVE_INFO 0 +#if 0 +static struct _pio_mode_mapping { + byte data_active; + byte recovery; + byte pio_mode; +} pio_mode_mapping[] = { + { 8, 12, 0 }, + { 6, 7, 1 }, + { 4, 4, 2 }, + { 3, 3, 3 }, + { 3, 1, 4 } +}; + +static struct _dma_mode_mapping { + byte data_active; + byte recovery; + byte dma_mode; +} dma_mode_mapping[] = { + { 8, 8, 0 }, + { 3, 2, 1 }, + { 3, 1, 2 } +}; + +static struct _udma_mode_mapping { + byte cycle_time; + char * udma_mode; +} udma_mode_mapping[] = { + { 8, "Mode 0" }, + { 6, "Mode 1" }, + { 4, "Mode 2" }, + { 3, "Mode 3" }, + { 2, "Mode 4" }, + { 0, "Undefined" } +}; + +static __inline__ char * find_udma_mode (byte cycle_time) +{ + int n; + + for (n = 0; n <= 4; n++) + if (udma_mode_mapping[n].cycle_time <= cycle_time) + return udma_mode_mapping[n].udma_mode; + return udma_mode_mapping[4].udma_mode; +} +#endif + +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) +#include <linux/stat.h> +#include <linux/proc_fs.h> + +static int sis_get_info(char *, char **, off_t, int, int); +extern int (*sis_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */ +struct pci_dev *bmide_dev; + +static char *cable_type[] = { + "80 pins", + "40 pins" +}; + +static char *recovery_time [] ={ + "12 PCICLK", "1 PCICLK", + "2 PCICLK", "3 PCICLK", + "4 PCICLK", "5 PCICLCK", + "6 PCICLK", "7 PCICLCK", + "8 PCICLK", "9 PCICLCK", + "10 PCICLK", "11 PCICLK", + "13 PCICLK", "14 PCICLK", + "15 PCICLK", "15 PCICLK" +}; + +static char *cycle_time [] = { + "Undefined", "2 CLCK", + "3 CLK", "4 CLK", + "5 CLK", "6 CLK", + "7 CLK", "8 CLK" +}; + +static char *active_time [] = { + "8 PCICLK", "1 PCICLCK", + "2 PCICLK", "2 PCICLK", + "4 PCICLK", "5 PCICLK", + "6 PCICLK", "12 PCICLK" +}; + +static int sis_get_info (char *buffer, char **addr, off_t offset, int count, int dummy) +{ + int rc; + char *p = buffer; + byte reg,reg1; +#if 0 + byte cyc, rec, act; +#endif + u16 reg2, reg3; + + p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n"); + rc = pci_read_config_byte(bmide_dev, 0x4a, ®); + p += sprintf(p, "Channel Status: %s \t \t \t \t %s \n", + (reg & 0x02) ? "On" : "Off", + (reg & 0x04) ? "On" : "Off"); + + rc = pci_read_config_byte(bmide_dev, 0x09, ®); + p += sprintf(p, "Operation Mode: %s \t \t \t %s \n", + (reg & 0x01) ? "Native" : "Compatible", + (reg & 0x04) ? "Native" : "Compatible"); + + rc = pci_read_config_byte(bmide_dev, 0x48, ®); + p += sprintf(p, "Cable Type: %s \t \t \t %s\n", + (reg & 0x10) ? cable_type[1] : cable_type[0], + (reg & 0x20) ? cable_type[1] : cable_type[0]); + + rc = pci_read_config_word(bmide_dev, 0x4c, ®2); + rc = pci_read_config_word(bmide_dev, 0x4e, ®3); + p += sprintf(p, "Prefetch Count: %d \t \t \t \t %d\n", + reg2, reg3); + + rc = pci_read_config_byte(bmide_dev, 0x4b, ®); + p += sprintf(p, "Drvie 0: Postwrite %s \t \t Postwrite %s\n", + (reg & 0x10) ? "Enabled" : "Disabled", + (reg & 0x40) ? "Enabled" : "Disabled"); + p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", + (reg & 0x01) ? "Enabled" : "Disabled", + (reg & 0x04) ? "Enabled" : "Disabled"); + + rc = pci_read_config_byte(bmide_dev, 0x41, ®); + rc = pci_read_config_byte(bmide_dev, 0x45, ®1); + p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", + (reg & 0x80) ? "Enabled" : "Disabled", + (reg1 & 0x80) ? "Enabled" : "Disabled"); + p += sprintf(p, " UDMA Cycle Time %s \t UDMA Cycle Time %s\n", + cycle_time[(reg & 0x70) >> 4], cycle_time[(reg1 & 0x70) >> 4]); + p += sprintf(p, " Data Active Time %s \t Data Active Time %s\n", + active_time[(reg & 0x07)], active_time[(reg &0x07)] ); + + rc = pci_read_config_byte(bmide_dev, 0x40, ®); + rc = pci_read_config_byte(bmide_dev, 0x44, ®1); + p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", + recovery_time[(reg & 0x0f)], recovery_time[(reg1 & 0x0f)]); + + + rc = pci_read_config_byte(bmide_dev, 0x4b, ®); + p += sprintf(p, "Drvie 1: Postwrite %s \t \t Postwrite %s\n", + (reg & 0x20) ? "Enabled" : "Disabled", + (reg & 0x80) ? "Enabled" : "Disabled"); + p += sprintf(p, " Prefetch %s \t \t Prefetch %s\n", + (reg & 0x02) ? "Enabled" : "Disabled", + (reg & 0x08) ? "Enabled" : "Disabled"); + + rc = pci_read_config_byte(bmide_dev, 0x43, ®); + rc = pci_read_config_byte(bmide_dev, 0x47, ®1); + p += sprintf(p, " UDMA %s \t \t \t UDMA %s\n", + (reg & 0x80) ? "Enabled" : "Disabled", + (reg1 & 0x80) ? "Enabled" : "Disabled"); + p += sprintf(p, " UDMA Cycle Time %s \t UDMA Cycle Time %s\n", + cycle_time[(reg & 0x70) >> 4], cycle_time[(reg1 & 0x70) >> 4]); + p += sprintf(p, " Data Active Time %s \t Data Active Time %s\n", + active_time[(reg & 0x07)], active_time[(reg &0x07)] ); + + rc = pci_read_config_byte(bmide_dev, 0x42, ®); + rc = pci_read_config_byte(bmide_dev, 0x46, ®1); + p += sprintf(p, " Data Recovery Time %s \t Data Recovery Time %s\n", + recovery_time[(reg & 0x0f)], recovery_time[(reg1 & 0x0f)]); + return p-buffer; +} +#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ +byte sis_proc = 0; extern char *ide_xfer_verbose (byte xfer_rate); /* @@ -79,36 +247,18 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) } if ((id->dma_ultra & 0x0010) && (ultra) && (udma_66) && (four_two)) { - if (!((id->dma_ultra >> 8) & 16)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x1010; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } if (!(test2 & 0x90)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); pci_write_config_byte(dev, drive_pci|0x01, test2|0x90); } speed = XFER_UDMA_4; } else if ((id->dma_ultra & 0x0008) && (ultra) && (udma_66) && (four_two)) { - if (!((id->dma_ultra >> 8) & 8)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0808; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } if (!(test2 & 0xA0)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); pci_write_config_byte(dev, drive_pci|0x01, test2|0xA0); } speed = XFER_UDMA_3; } else if ((id->dma_ultra & 0x0004) && (ultra)) { - if (!((id->dma_ultra >> 8) & 4)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } mask = (four_two) ? 0xB0 : 0xA0; if (!(test2 & mask)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); @@ -116,12 +266,6 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) } speed = XFER_UDMA_2; } else if ((id->dma_ultra & 0x0002) && (ultra)) { - if (!((id->dma_ultra >> 8) & 2)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } mask = (four_two) ? 0xD0 : 0xC0; if (!(test2 & mask)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); @@ -129,58 +273,22 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) } speed = XFER_UDMA_1; } else if ((id->dma_ultra & 0x0001) && (ultra)) { - if (!((id->dma_ultra >> 8) & 1)) { - drive->id->dma_ultra &= ~0xFF00; - drive->id->dma_ultra |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_1word &= ~0x0F00; - } if (!(test2 & unmask)) { pci_write_config_byte(dev, drive_pci|0x01, test2 & ~unmask); pci_write_config_byte(dev, drive_pci|0x01, test2|unmask); } speed = XFER_UDMA_0; } else if (id->dma_mword & 0x0004) { - if (!((id->dma_mword >> 8) & 4)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0404; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_2; } else if (id->dma_mword & 0x0002) { - if (!((id->dma_mword >> 8) & 2)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0202; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_1; } else if (id->dma_mword & 0x0001) { - if (!((id->dma_mword >> 8) & 1)) { - drive->id->dma_mword &= ~0x0F00; - drive->id->dma_mword |= 0x0101; - drive->id->dma_1word &= ~0x0F00; - } speed = XFER_MW_DMA_0; } else if (id->dma_1word & 0x0004) { - if (!((id->dma_1word >> 8) & 4)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0404; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_2; } else if (id->dma_1word & 0x0002) { - if (!((id->dma_1word >> 8) & 2)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0202; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_1; } else if (id->dma_1word & 0x0001) { - if (!((id->dma_1word >> 8) & 1)) { - drive->id->dma_1word &= ~0x0F00; - drive->id->dma_1word |= 0x0101; - drive->id->dma_mword &= ~0x0F00; - } speed = XFER_SW_DMA_0; } else { return ((int) ide_dma_off_quietly); @@ -189,10 +297,7 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra) err = ide_config_drive_speed(drive, speed); #if SIS5513_DEBUG_DRIVE_INFO - printk("%s: %s drive%d\n", - drive->name, - ide_xfer_verbose(speed), - drive_number); + printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive_number); #endif /* SIS5513_DEBUG_DRIVE_INFO */ return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : @@ -333,10 +438,9 @@ int sis5513_dmaproc (ide_dma_action_t func, ide_drive_t *drive) unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) { struct pci_dev *host; - byte latency = 0, reg48h = 0; + byte latency = 0; pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency); - pci_read_config_byte(dev, 0x48, ®48h); for (host = pci_devices; host; host=host->next) { if (host->vendor == PCI_VENDOR_ID_SI && @@ -344,30 +448,18 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) if (latency != 0x10) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10); host_dev = host; - printk("%s: Chipset Core ATA-66, SiS620\n", name); - printk("%s: Primary ATA-%s, Secondary ATA-%s Cable Detect\n", - name, - (reg48h & 0x10) ? "33" : "66", - (reg48h & 0x20) ? "33" : "66"); break; } else if (host->vendor == PCI_VENDOR_ID_SI && host->device == PCI_DEVICE_ID_SI_530) { host_dev = host; - printk("%s: Chipset Core ATA-66, SiS530\n", name); - printk("%s: Primary ATA-%s, Secondary ATA-%s Cable Detect\n", - name, - (reg48h & 0x10) ? "33" : "66", - (reg48h & 0x20) ? "33" : "66"); break; } else if (host->vendor == PCI_VENDOR_ID_SI && host->device == PCI_DEVICE_ID_SI_5600) { host_dev = host; - printk("SIS5600:%s Chipset Core ATA-33\n", name); break; } else if (host->vendor == PCI_VENDOR_ID_SI && host->device == PCI_DEVICE_ID_SI_5597) { host_dev = host; - printk("SIS5597:%s Chipset Core ATA-33\n", name); break; } } @@ -377,18 +469,38 @@ unsigned int __init pci_init_sis5513 (struct pci_dev *dev, const char *name) pci_read_config_byte(dev, 0x52, ®52h); if (!(reg52h & 0x04)) + /* set IDE controller to operate in Compabitility mode obly */ pci_write_config_byte(dev, 0x52, reg52h|0x04); +#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) + sis_proc = 1; + bmide_dev = dev; + sis_display_info = &sis_get_info; +#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ } - return 0; } -void __init ide_init_sis5513 (ide_hwif_t *hwif) +unsigned int __init ata66_sis5513 (ide_hwif_t *hwif) { - byte reg48h = 0; + byte reg48h = 0, ata66 = 0; byte mask = hwif->channel ? 0x20 : 0x10; - pci_read_config_byte(hwif->pci_dev, 0x48, ®48h); + + if (host_dev) { + switch(host_dev->device) { + case PCI_DEVICE_ID_SI_530: + case PCI_DEVICE_ID_SI_620: + ata66 = (reg48h & mask) ? 0 : 1; + default: + break; + } + } + return (ata66); +} + +void __init ide_init_sis5513 (ide_hwif_t *hwif) +{ + hwif->irq = hwif->channel ? 15 : 14; if (!(hwif->dma_base)) @@ -398,20 +510,15 @@ void __init ide_init_sis5513 (ide_hwif_t *hwif) switch(host_dev->device) { case PCI_DEVICE_ID_SI_530: case PCI_DEVICE_ID_SI_620: - hwif->autodma = 1; - hwif->udma_four = (reg48h & mask) ? 0 : 1; - hwif->dmaproc = &sis5513_dmaproc; - return; case PCI_DEVICE_ID_SI_5600: case PCI_DEVICE_ID_SI_5597: hwif->autodma = 1; - hwif->udma_four = 0; hwif->dmaproc = &sis5513_dmaproc; - return; + break; default: hwif->autodma = 0; - hwif->udma_four = 0; - return; + break; } } + return; } diff --git a/drivers/block/sl82c105.c b/drivers/block/sl82c105.c index d4e22d33b..fa47adbb7 100644 --- a/drivers/block/sl82c105.c +++ b/drivers/block/sl82c105.c @@ -5,7 +5,7 @@ * * Maintainer unknown. * - * Drive tuning added from Corel Computer's kernel sources + * Drive tuning added from Rebel.com's kernel sources * -- Russell King (15/11/98) linux@arm.linux.org.uk */ diff --git a/drivers/block/trm290.c b/drivers/block/trm290.c index ad6a75d0f..5c7c8fd3c 100644 --- a/drivers/block/trm290.c +++ b/drivers/block/trm290.c @@ -192,7 +192,8 @@ static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive) outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */ if (drive->media != ide_disk) return 0; - ide_set_handler(drive, &ide_dma_intr, WAIT_CMD); + drive->timeout = WAIT_CMD; + ide_set_handler(drive, &ide_dma_intr); OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); return 0; case ide_dma_begin: diff --git a/drivers/block/via82c586.c b/drivers/block/via82cxxx.c index e5697014e..e6f61c03f 100644 --- a/drivers/block/via82c586.c +++ b/drivers/block/via82cxxx.c @@ -1,9 +1,12 @@ /* - * linux/drivers/block/via82c586.c Version 0.04 July 11, 1999 + * linux/drivers/block/via82cxxx.c Version 0.05 Sept. 03, 1999 * - * Copyright (C) 1998 Michel Aubry, Maintainer - * Copyright (C) 1998 Andre Hedrick, Maintainer + * Copyright (C) 1998-99 Michel Aubry, Maintainer + * Copyright (C) 1999 Jeff Garzik, MVP4 Support (jgarzik@pobox.com) + * Copyright (C) 1998-99 Andre Hedrick (andre@suse.com) + * May be copied or modified under the terms of the GNU General Public License * + * The VIA MVP-4 is reported OK with UDMA. * The VIA MVP-3 is reported OK with UDMA. * The TX Pro III is also reported OK with UDMA. * @@ -57,8 +60,44 @@ #include <asm/io.h> -static struct pci_dev *host_dev; -static struct pci_dev *isa_dev; +static struct pci_dev *host_dev = NULL; +static struct pci_dev *isa_dev = NULL; + +static const struct { + const char *name; + unsigned short host_id; +} ApolloHostChipInfo[] = { + { "VT 82C585 Apollo VP1/VPX", PCI_DEVICE_ID_VIA_82C585, }, + { "VT 82C595 Apollo VP2", PCI_DEVICE_ID_VIA_82C595, }, + { "VT 82C597 Apollo VP3", PCI_DEVICE_ID_VIA_82C597_0, }, + { "VT 82C598 Apollo MVP3", PCI_DEVICE_ID_VIA_82C598_0, }, + { "VT 82C680 Apollo P6", PCI_DEVICE_ID_VIA_82C680, }, + { "VT 82C691 Apollo Pro", PCI_DEVICE_ID_VIA_82C691, }, + { "VT 82C693 Apollo Pro Plus", PCI_DEVICE_ID_VIA_82C693, }, + { "Apollo MVP4", PCI_DEVICE_ID_VIA_8501_0, }, +}; + +#define NUM_APOLLO_ISA_CHIP_DEVICES 2 +#define VIA_FLAG_CHECK_REV 0x00000001 +#define VIA_FLAG_ATA_66 0x00000002 + +static const struct { + unsigned short host_id; + unsigned short isa_id; + unsigned int flags; +} ApolloISAChipInfo[] = { + { PCI_DEVICE_ID_VIA_82C585, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, + { PCI_DEVICE_ID_VIA_82C595, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, + { PCI_DEVICE_ID_VIA_82C597_0, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, + { PCI_DEVICE_ID_VIA_82C598_0, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, + { PCI_DEVICE_ID_VIA_82C598_0, PCI_DEVICE_ID_VIA_82C596, 0 }, + { PCI_DEVICE_ID_VIA_82C680, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV }, + { PCI_DEVICE_ID_VIA_82C691, PCI_DEVICE_ID_VIA_82C596, 0 }, + { PCI_DEVICE_ID_VIA_82C693, PCI_DEVICE_ID_VIA_82C596, 0 }, + { PCI_DEVICE_ID_VIA_8501_0, PCI_DEVICE_ID_VIA_82C686, VIA_FLAG_ATA_66 }, +}; + +#define arraysize(x) (sizeof(x)/sizeof(*(x))) #define DISPLAY_VIA_TIMINGS @@ -298,6 +337,7 @@ static int via_get_info (char *buffer, char **addr, off_t offset, int count, int * Used to set Fifo configuration via kernel command line: */ +byte via_proc = 0; byte fifoconfig = 0; static byte newfifo = 0; @@ -340,8 +380,8 @@ static void set_via_timings (ide_hwif_t *hwif) /* * setting Channel read and End-of-sector FIFO flush. * (This feature ensures that FIFO flush is enabled: - * - for read DMA when interrupt asserts the given channel. - * - at the end of each sector for the given channel.) + * - for read DMA when interrupt asserts the given channel. + * - at the end of each sector for the given channel.) */ if ((rc = pci_read_config_byte(dev, 0x46, &via_config))) errors++; @@ -363,7 +403,7 @@ static void set_via_timings (ide_hwif_t *hwif) } /* - * Sets VIA 82c586 FIFO configuration: + * Sets VIA 82cxxx FIFO configuration: * This chipsets gets a splitable fifo. This can be driven either by command * line option (eg "splitfifo=2,2,3" which asks this driver to switch all the * 16 fifo levels to the second drive, and give it a threshold of 3 for (u)dma @@ -435,139 +475,71 @@ static int via_set_fifoconfig(ide_hwif_t *hwif) (newfifo & 0x01) ? "1/4" : "1/2")); #if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) + via_proc = 1; bmide_dev = hwif->pci_dev; via_display_info = &via_get_info; #endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS*/ return 0; } -unsigned int __init pci_init_via82c568 (struct pci_dev *dev, const char *name) +unsigned int __init pci_init_via82cxxx (struct pci_dev *dev, const char *name) { struct pci_dev *host; struct pci_dev *isa; + int i, j, ata33, ata66; byte revision = 0; - for (host = pci_devices; host; host=host->next) { - if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C585) { - host_dev = host; - printk("VT 82C585 Apollo VP1/VPX"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C586_1) { - isa_dev = isa; - pci_read_config_byte(isa_dev, 0x0d, &revision); - if (revision >= 0x20) - printk(" Chipset Core ATA-33"); - break; - } - } - printk("\n"); - break; - } else if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C595) { - host_dev = host; - printk("VT 82C595 Apollo VP2"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C586_1) { - isa_dev = isa; - pci_read_config_byte(isa_dev, 0x0d, &revision); - if (revision >= 0x20) - printk(" Chipset Core ATA-33"); - break; - } - } - printk("\n"); - break; - } else if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C597_0) { - host_dev = host; - printk("VT 82C597 Apollo VP3"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C586_1) { - isa_dev = isa; - pci_read_config_byte(isa_dev, 0x0d, &revision); - if (revision >= 0x20) - printk(" Chipset Core ATA-33"); - break; - } - } - printk("\n"); - break; - } else if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C598_0) { - host_dev = host; - printk("VT 82C598 Apollo MVP3"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C586_1) { - isa_dev = isa; - pci_read_config_byte(isa_dev, 0x0d, &revision); - if (revision >= 0x20) - printk(" Chipset Core ATA-33"); - break; - } else if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C596) { - isa_dev = isa; - printk(" Chipset Core ATA-33"); - break; - } - } - printk("\n"); - break; - } else if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C680) { - host_dev = host; - printk("VT 82C680 Apollo P6"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C586_1) { - isa_dev = isa; - pci_read_config_byte(isa_dev, 0x0d, &revision); - if (revision >= 0x20) - printk(" Chipset Core ATA-33"); - break; - } + for (i = 0; i < arraysize (ApolloHostChipInfo) && !host_dev; i++) { + host = pci_find_device (PCI_VENDOR_ID_VIA, + ApolloHostChipInfo[i].host_id, + NULL); + if (!host) + continue; + + host_dev = host; + printk(ApolloHostChipInfo[i].name); + + for (j = 0; j < arraysize (ApolloISAChipInfo) && !isa_dev; j++) { + if (ApolloISAChipInfo[j].host_id != + ApolloHostChipInfo[i].host_id) + continue; + + isa = pci_find_device (PCI_VENDOR_ID_VIA, + ApolloISAChipInfo[i].isa_id, + NULL); + if (!isa) + continue; + + isa_dev = isa; + + ata33 = 1; + ata66 = 0; + + if (ApolloISAChipInfo[i].flags & VIA_FLAG_CHECK_REV) { + pci_read_config_byte(isa_dev, 0x0d, &revision); + ata33 = (revision >= 0x20) ? 1 : 0; + } else if (ApolloISAChipInfo[i].flags & VIA_FLAG_ATA_66) { + ata33 = 0; + ata66 = 1; } - printk("\n"); - break; - } else if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C691) { - host_dev = host; - printk("VT 82C691 Apollo Pro"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C596) { - isa_dev = isa; - printk(" Chipset Core ATA-33"); - break; - } - } - printk("\n"); - break; - } else if (host->vendor == PCI_VENDOR_ID_VIA && - host->device == PCI_DEVICE_ID_VIA_82C693) { - host_dev = host; - printk("VT 82C693 Apollo Pro Plus"); - for (isa = pci_devices; isa; isa=isa->next) { - if (isa->vendor == PCI_VENDOR_ID_VIA && - isa->device == PCI_DEVICE_ID_VIA_82C596) { - isa_dev = isa; - printk(" Chipset Core ATA-33"); - break; - } - } - printk("\n"); - break; + + if (ata33 | ata66) + printk(" Chipset Core ATA-%s", ata66 ? "66" : "33"); } + printk("\n"); } + + return 0; +} + +unsigned int __init ata66_via82cxxx (ide_hwif_t *hwif) +{ + /* (Jeff Garzik) FIXME!!! for MVP4 */ return 0; } -void __init ide_init_via82c586 (ide_hwif_t *hwif) +void __init ide_init_via82cxxx (ide_hwif_t *hwif) { set_via_timings(hwif); } @@ -581,7 +553,7 @@ void __init ide_init_via82c586 (ide_hwif_t *hwif) * bypasses the setup if not capable. */ -void ide_dmacapable_via82c586 (ide_hwif_t *hwif, unsigned long dmabase) +void ide_dmacapable_via82cxxx (ide_hwif_t *hwif, unsigned long dmabase) { if (!done) { via_set_fifoconfig(hwif); |