From b1489009963b8c5132f2ffe23483e811d9ae5607 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 8 Dec 2006 02:39:58 -0800 Subject: [PATCH] ide: more conversion to pci_get APIs This completes IDE except for one use which requires a new core PCI function and will be polished up at the end Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/alim15x3.c | 16 ++++++++-------- drivers/ide/pci/pdc202xx_new.c | 7 +++++-- drivers/ide/pci/sis5513.c | 3 ++- 3 files changed, 15 insertions(+), 11 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index d419e4bb54f..89109be5162 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -586,11 +586,11 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c { unsigned long flags; u8 tmpbyte; - struct pci_dev *north = pci_find_slot(0, PCI_DEVFN(0,0)); + struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0)); pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision); - isa_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); + isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); #if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) if (!ali_proc) { @@ -613,8 +613,7 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c * clear bit 7 */ pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F); - local_irq_restore(flags); - return 0; + goto out; } /* @@ -637,10 +636,8 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c * box without a device at 0:0.0. The ALi bridge will be at * 0:0.0 so if we didn't find one we know what is cooking. */ - if (north && north->vendor != PCI_VENDOR_ID_AL) { - local_irq_restore(flags); - return 0; - } + if (north && north->vendor != PCI_VENDOR_ID_AL) + goto out; if (m5229_revision < 0xC5 && isa_dev) { @@ -661,6 +658,9 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02); } } +out: + pci_dev_put(north); + pci_dev_put(isa_dev); local_irq_restore(flags); return 0; } diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 6c097e80b4d..0592dc0f96c 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -362,6 +362,7 @@ static int __devinit init_setup_pdc20270(struct pci_dev *dev, ide_pci_device_t *d) { struct pci_dev *findev = NULL; + int ret; if ((dev->bus->self && dev->bus->self->vendor == PCI_VENDOR_ID_DEC) && @@ -369,14 +370,16 @@ static int __devinit init_setup_pdc20270(struct pci_dev *dev, if (PCI_SLOT(dev->devfn) & 2) return -ENODEV; d->extra = 0; - while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { + while ((findev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { if ((findev->vendor == dev->vendor) && (findev->device == dev->device) && (PCI_SLOT(findev->devfn) & 2)) { if (findev->irq != dev->irq) { findev->irq = dev->irq; } - return ide_setup_pci_devices(dev, findev, d); + ret = ide_setup_pci_devices(dev, findev, d); + pci_dev_put(findev); + return ret; } } } diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 92edf76bd7a..6b313139b5e 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -800,9 +800,10 @@ static unsigned int __devinit init_chipset_sis5513 (struct pci_dev *dev, const c if (trueid == 0x5517) { /* SiS 961/961B */ - lpc_bridge = pci_find_slot(0x00, 0x10); /* Bus 0, Dev 2, Fn 0 */ + lpc_bridge = pci_get_slot(dev->bus, 0x10); /* Bus 0, Dev 2, Fn 0 */ pci_read_config_byte(lpc_bridge, PCI_REVISION_ID, &sbrev); pci_read_config_byte(dev, 0x49, &prefctl); + pci_dev_put(lpc_bridge); if (sbrev == 0x10 && (prefctl & 0x80)) { printk(KERN_INFO "SIS5513: SiS 961B MuTIOL IDE UDMA133 controller\n"); -- cgit v1.2.3 From b10a06866600d1eda9e72ff328999e70f077fb3a Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 8 Dec 2006 02:39:59 -0800 Subject: [PATCH] pdc202xx_new: fix PIO mode setup Fix pdcnew_tune_drive() to always set the PIO mode requested, not pick the best possible one, change pdcnew_config_drive_xfer_rate() accordingly, and get rid of the duplicate tuneproc() call in config_chipset_for_dma(). Signed-off-by: Sergei Shtylyov Cc: Alan Cox Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/pdc202xx_new.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 0592dc0f96c..3ca581063f7 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -9,6 +9,7 @@ * Split from: * linux/drivers/ide/pdc202xx.c Version 0.35 Mar. 30, 2002 * Copyright (C) 1998-2002 Andre Hedrick + * Copyright (C) 2005-2006 MontaVista Software, Inc. * Portions Copyright (C) 1999 Promise Technology, Inc. * Author: Frank Tiernan (frankt@promise.com) * Released under terms of General Public License @@ -168,12 +169,8 @@ static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) */ static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio) { - u8 speed; - - if (pio == 5) pio = 4; - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL); - - (void)pdcnew_new_tune_chipset(drive, speed); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + (void)pdcnew_new_tune_chipset(drive, XFER_PIO_0 + pio); } static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif) @@ -207,10 +204,8 @@ static int config_chipset_for_dma (ide_drive_t *drive) speed = ide_dma_speed(drive, pdcnew_ratemask(drive)); - if (!(speed)) { - hwif->tuneproc(drive, 5); + if (!speed) return 0; - } (void) hwif->speedproc(drive, speed); return ide_dma_enable(drive); @@ -234,7 +229,7 @@ static int pdcnew_config_drive_xfer_rate (ide_drive_t *drive) } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: - hwif->tuneproc(drive, 5); + hwif->tuneproc(drive, 255); return hwif->ide_dma_off_quietly(drive); } /* IORDY not supported */ -- cgit v1.2.3 From dd607d23ff4cc004da2986d0b264a972c6a2da3e Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 8 Dec 2006 02:40:01 -0800 Subject: [PATCH] sl82c105: straighten up IDE control/status register caching Straighten up the IDE control/status register caching -- you *really* can't cache the shared register per-channel and hope that it won't get out ouf sync. Set the PIO fallback mode to PIO0 for the slave drive as well as master -- there was no point in having them different (most probably a resutl of typo). Do a bit of reformat and cleanup while at it... Signed-off-by: Sergei Shtylyov Acked-by: Alan Cox Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/sl82c105.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index 0b4b6049851..5afefe8692f 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -299,14 +299,14 @@ static void sl82c105_selectproc(ide_drive_t *drive) //DBG(("sl82c105_selectproc(drive:%s)\n", drive->name)); mask = hwif->channel ? CTRL_P1F16 : CTRL_P0F16; - old = val = *((u32 *)&hwif->hwif_data); + old = val = (u32)pci_get_drvdata(dev); if (drive->using_dma) val &= ~mask; else val |= mask; if (old != val) { pci_write_config_dword(dev, 0x40, val); - *((u32 *)&hwif->hwif_data) = val; + pci_set_drvdata(dev, (void *)val); } } @@ -316,14 +316,13 @@ static void sl82c105_selectproc(ide_drive_t *drive) */ static void sl82c105_resetproc(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = HWIF(drive)->pci_dev; u32 val; DBG(("sl82c105_resetproc(drive:%s)\n", drive->name)); pci_read_config_dword(dev, 0x40, &val); - *((u32 *)&hwif->hwif_data) = val; + pci_set_drvdata(dev, (void *)val); } /* @@ -394,6 +393,7 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c pci_read_config_dword(dev, 0x40, &val); val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; pci_write_config_dword(dev, 0x40, val); + pci_set_drvdata(dev, (void *)val); return dev->irq; } @@ -404,30 +404,25 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; unsigned int rev; u8 dma_state; - u32 val; - + DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); hwif->tuneproc = tune_sl82c105; hwif->selectproc = sl82c105_selectproc; hwif->resetproc = sl82c105_resetproc; - - /* Default to PIO 0 for fallback unless tuned otherwise, - * we always autotune PIO, this is done before DMA is - * checked, so there is no risk of accidentally disabling - * DMA - */ + + /* + * Default to PIO 0 for fallback unless tuned otherwise. + * We always autotune PIO, this is done before DMA is checked, + * so there's no risk of accidentally disabling DMA + */ hwif->drives[0].pio_speed = XFER_PIO_0; hwif->drives[0].autotune = 1; - hwif->drives[1].pio_speed = XFER_PIO_1; + hwif->drives[1].pio_speed = XFER_PIO_0; hwif->drives[1].autotune = 1; - pci_read_config_dword(dev, 0x40, &val); - *((u32 *)&hwif->hwif_data) = val; - hwif->atapi_dma = 0; hwif->mwdma_mask = 0; hwif->swdma_mask = 0; -- cgit v1.2.3 From 6451956a24963d3eb1655fd039762ae42ac48da7 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 10 Dec 2006 02:18:53 -0800 Subject: [PATCH] ide: complete switch to pci_get The reverse get function allows the final piece of the switching for the old IDE layer Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/setup-pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 0719b648482..695e23904d3 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -844,11 +844,11 @@ void __init ide_scan_pcibus (int scan_direction) pre_init = 0; if (!scan_direction) { - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { ide_scan_pcidev(dev); } } else { - while ((dev = pci_find_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { ide_scan_pcidev(dev); } } -- cgit v1.2.3 From 47694bb86af3648d4ec34c7afd46653cefc9b359 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 10 Dec 2006 02:19:13 -0800 Subject: [PATCH] pdc202xx_new: fix PLL/timing issues Fix the CRC errors in the higher UltraDMA modes with the Promise PDC20268 and newer chips that always occur on non-x86 machines and when there are more than 2 adapters on x86 machines. Fix the overclocking issue for PDC20269 and newer chips that occurs when an UltraDMA/133 capable drive is connected. Here's the summary of changes: - add code to detect the PLL input clock detection and setup it output clock, remove the PowerMac hacks; - replace the macros accessing the indexed regiters with functions, switch to using them where appropriate, gather the PIO/MWDMA/UDMA timings into tables; - rewrite the speedproc() handler to set the drive's transfer mode first, and then override the timing registers set by hardware on UltraDMA/133 chips; - use better criterion for determining higher UltraDMA modes, and add comment concerning the doubtful value of the code enabling IORDY/prefetch; - replace the stupid 'pdcnew_new_' prefixes with mere 'pdcnew_'; - get rid of unneded spaces, parens and type casts, clean up some printk's, add some new lines here and there... This work is loosely based on these former patches by Albert Lee: [1] http://marc.theaimsgroup.com/?l=linux-ide&m=110992442032300 [2] http://marc.theaimsgroup.com/?l=linux-ide&m=110992457729382 [3] http://marc.theaimsgroup.com/?l=linux-ide&m=110992474205555 [4] http://marc.theaimsgroup.com/?l=linux-ide&m=111019224802939 Some PLL clock detection code was backported from his pata_pdc2027x driver... This code has been successfully tested by me on PDC2026[89] chips. I tried to keep this rework as several patches but it made no sense: [2] was largely a modification of the non-working timing override code, [3] by itself extended the overclocking issue to the case of non-UltraDMA/133 drives, and finally, the cleanup patch based on [1] ended up rejected... Signed-off-by: Sergei Shtylyov Cc: Albert Lee Acked-by: Alan Cox Cc: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/pdc202xx_new.c | 483 ++++++++++++++++++++++++++++++++--------- 1 file changed, 375 insertions(+), 108 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 3ca581063f7..7cb48576e47 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -39,6 +39,14 @@ #define PDC202_DEBUG_CABLE 0 +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt, args...) printk("%s: " fmt, __FUNCTION__, ## args) +#else +#define DBG(fmt, args...) +#endif + static const char *pdc_quirk_drives[] = { "QUANTUM FIREBALLlct08 08", "QUANTUM FIREBALLP KA6.4", @@ -51,37 +59,11 @@ static const char *pdc_quirk_drives[] = { NULL }; -#define set_2regs(a, b) \ - do { \ - hwif->OUTB((a + adj), indexreg); \ - hwif->OUTB(b, datareg); \ - } while(0) - -#define set_ultra(a, b, c) \ - do { \ - set_2regs(0x10,(a)); \ - set_2regs(0x11,(b)); \ - set_2regs(0x12,(c)); \ - } while(0) - -#define set_ata2(a, b) \ - do { \ - set_2regs(0x0e,(a)); \ - set_2regs(0x0f,(b)); \ - } while(0) - -#define set_pio(a, b, c) \ - do { \ - set_2regs(0x0c,(a)); \ - set_2regs(0x0d,(b)); \ - set_2regs(0x13,(c)); \ - } while(0) - -static u8 pdcnew_ratemask (ide_drive_t *drive) +static u8 max_dma_rate(struct pci_dev *pdev) { u8 mode; - switch(HWIF(drive)->pci_dev->device) { + switch(pdev->device) { case PCI_DEVICE_ID_PROMISE_20277: case PCI_DEVICE_ID_PROMISE_20276: case PCI_DEVICE_ID_PROMISE_20275: @@ -96,12 +78,21 @@ static u8 pdcnew_ratemask (ide_drive_t *drive) default: return 0; } - if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); + return mode; } -static int check_in_drive_lists (ide_drive_t *drive, const char **list) +static u8 pdcnew_ratemask(ide_drive_t *drive) +{ + u8 mode = max_dma_rate(HWIF(drive)->pci_dev); + + if (!eighty_ninty_three(drive)) + mode = min_t(u8, mode, 1); + + return mode; +} + +static int check_in_drive_lists(ide_drive_t *drive, const char **list) { struct hd_driveid *id = drive->id; @@ -121,43 +112,141 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) return 0; } -static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) +/** + * get_indexed_reg - Get indexed register + * @hwif: for the port address + * @index: index of the indexed register + */ +static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index) +{ + u8 value; + + hwif->OUTB(index, hwif->dma_vendor1); + value = hwif->INB(hwif->dma_vendor3); + + DBG("index[%02X] value[%02X]\n", index, value); + return value; +} + +/** + * set_indexed_reg - Set indexed register + * @hwif: for the port address + * @index: index of the indexed register + */ +static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value) +{ + hwif->OUTB(index, hwif->dma_vendor1); + hwif->OUTB(value, hwif->dma_vendor3); + DBG("index[%02X] value[%02X]\n", index, value); +} + +/* + * ATA Timing Tables based on 133 MHz PLL output clock. + * + * If the PLL outputs 100 MHz clock, the ASIC hardware will set + * the timing registers automatically when "set features" command is + * issued to the device. However, if the PLL output clock is 133 MHz, + * the following tables must be used. + */ +static struct pio_timing { + u8 reg0c, reg0d, reg13; +} pio_timings [] = { + { 0xfb, 0x2b, 0xac }, /* PIO mode 0, IORDY off, Prefetch off */ + { 0x46, 0x29, 0xa4 }, /* PIO mode 1, IORDY off, Prefetch off */ + { 0x23, 0x26, 0x64 }, /* PIO mode 2, IORDY off, Prefetch off */ + { 0x27, 0x0d, 0x35 }, /* PIO mode 3, IORDY on, Prefetch off */ + { 0x23, 0x09, 0x25 }, /* PIO mode 4, IORDY on, Prefetch off */ +}; + +static struct mwdma_timing { + u8 reg0e, reg0f; +} mwdma_timings [] = { + { 0xdf, 0x5f }, /* MWDMA mode 0 */ + { 0x6b, 0x27 }, /* MWDMA mode 1 */ + { 0x69, 0x25 }, /* MWDMA mode 2 */ +}; + +static struct udma_timing { + u8 reg10, reg11, reg12; +} udma_timings [] = { + { 0x4a, 0x0f, 0xd5 }, /* UDMA mode 0 */ + { 0x3a, 0x0a, 0xd0 }, /* UDMA mode 1 */ + { 0x2a, 0x07, 0xcd }, /* UDMA mode 2 */ + { 0x1a, 0x05, 0xcd }, /* UDMA mode 3 */ + { 0x1a, 0x03, 0xcd }, /* UDMA mode 4 */ + { 0x1a, 0x02, 0xcb }, /* UDMA mode 5 */ + { 0x1a, 0x01, 0xcb }, /* UDMA mode 6 */ +}; + +static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = HWIF(drive); - unsigned long indexreg = hwif->dma_vendor1; - unsigned long datareg = hwif->dma_vendor3; - u8 thold = 0x10; - u8 adj = (drive->dn%2) ? 0x08 : 0x00; - u8 speed = ide_rate_filter(pdcnew_ratemask(drive), xferspeed); - - if (speed == XFER_UDMA_2) { - hwif->OUTB((thold + adj), indexreg); - hwif->OUTB((hwif->INB(datareg) & 0x7f), datareg); - } + u8 adj = (drive->dn & 1) ? 0x08 : 0x00; + int err; - switch (speed) { - case XFER_UDMA_7: - speed = XFER_UDMA_6; - case XFER_UDMA_6: set_ultra(0x1a, 0x01, 0xcb); break; - case XFER_UDMA_5: set_ultra(0x1a, 0x02, 0xcb); break; - case XFER_UDMA_4: set_ultra(0x1a, 0x03, 0xcd); break; - case XFER_UDMA_3: set_ultra(0x1a, 0x05, 0xcd); break; - case XFER_UDMA_2: set_ultra(0x2a, 0x07, 0xcd); break; - case XFER_UDMA_1: set_ultra(0x3a, 0x0a, 0xd0); break; - case XFER_UDMA_0: set_ultra(0x4a, 0x0f, 0xd5); break; - case XFER_MW_DMA_2: set_ata2(0x69, 0x25); break; - case XFER_MW_DMA_1: set_ata2(0x6b, 0x27); break; - case XFER_MW_DMA_0: set_ata2(0xdf, 0x5f); break; - case XFER_PIO_4: set_pio(0x23, 0x09, 0x25); break; - case XFER_PIO_3: set_pio(0x27, 0x0d, 0x35); break; - case XFER_PIO_2: set_pio(0x23, 0x26, 0x64); break; - case XFER_PIO_1: set_pio(0x46, 0x29, 0xa4); break; - case XFER_PIO_0: set_pio(0xfb, 0x2b, 0xac); break; - default: - ; - } + speed = ide_rate_filter(pdcnew_ratemask(drive), speed); + + /* + * Issue SETFEATURES_XFER to the drive first. PDC202xx hardware will + * automatically set the timing registers based on 100 MHz PLL output. + */ + err = ide_config_drive_speed(drive, speed); + + /* + * As we set up the PLL to output 133 MHz for UltraDMA/133 capable + * chips, we must override the default register settings... + */ + if (max_dma_rate(hwif->pci_dev) == 4) { + u8 mode = speed & 0x07; + + switch (speed) { + case XFER_UDMA_6: + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + set_indexed_reg(hwif, 0x10 + adj, + udma_timings[mode].reg10); + set_indexed_reg(hwif, 0x11 + adj, + udma_timings[mode].reg11); + set_indexed_reg(hwif, 0x12 + adj, + udma_timings[mode].reg12); + break; + + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_MW_DMA_0: + set_indexed_reg(hwif, 0x0e + adj, + mwdma_timings[mode].reg0e); + set_indexed_reg(hwif, 0x0f + adj, + mwdma_timings[mode].reg0f); + break; + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_1: + case XFER_PIO_0: + set_indexed_reg(hwif, 0x0c + adj, + pio_timings[mode].reg0c); + set_indexed_reg(hwif, 0x0d + adj, + pio_timings[mode].reg0d); + set_indexed_reg(hwif, 0x13 + adj, + pio_timings[mode].reg13); + break; + default: + printk(KERN_ERR "pdc202xx_new: " + "Unknown speed %d ignored\n", speed); + } + } else if (speed == XFER_UDMA_2) { + /* Set tHOLD bit to 0 if using UDMA mode 2 */ + u8 tmp = get_indexed_reg(hwif, 0x10 + adj); - return (ide_config_drive_speed(drive, speed)); + set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f); + } + + return err; } /* 0 1 2 3 4 5 6 7 8 @@ -170,36 +259,42 @@ static int pdcnew_new_tune_chipset (ide_drive_t *drive, u8 xferspeed) static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio) { pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - (void)pdcnew_new_tune_chipset(drive, XFER_PIO_0 + pio); + (void)pdcnew_tune_chipset(drive, XFER_PIO_0 + pio); } -static u8 pdcnew_new_cable_detect (ide_hwif_t *hwif) +static u8 pdcnew_cable_detect(ide_hwif_t *hwif) { - hwif->OUTB(0x0b, hwif->dma_vendor1); - return ((u8)((hwif->INB(hwif->dma_vendor3) & 0x04))); + return get_indexed_reg(hwif, 0x0b) & 0x04; } -static int config_chipset_for_dma (ide_drive_t *drive) + +static int config_chipset_for_dma(ide_drive_t *drive) { struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); - u8 speed = -1; - u8 cable; - - u8 ultra_66 = ((id->dma_ultra & 0x0010) || - (id->dma_ultra & 0x0008)) ? 1 : 0; - - cable = pdcnew_new_cable_detect(hwif); + u8 ultra_66 = (id->dma_ultra & 0x0078) ? 1 : 0; + u8 cable = pdcnew_cable_detect(hwif); + u8 speed; if (ultra_66 && cable) { - printk(KERN_WARNING "Warning: %s channel requires an 80-pin cable for operation.\n", hwif->channel ? "Secondary":"Primary"); + printk(KERN_WARNING "Warning: %s channel " + "requires an 80-pin cable for operation.\n", + hwif->channel ? "Secondary" : "Primary"); printk(KERN_WARNING "%s reduced to Ultra33 mode.\n", drive->name); } if (drive->media != ide_disk) return 0; - if (id->capability & 4) { /* IORDY_EN & PREFETCH_EN */ - hwif->OUTB((0x13 + ((drive->dn%2) ? 0x08 : 0x00)), hwif->dma_vendor1); - hwif->OUTB((hwif->INB(hwif->dma_vendor3)|0x03), hwif->dma_vendor3); + + if (id->capability & 4) { + /* + * Set IORDY_EN & PREFETCH_EN (this seems to have + * NO real effect since this register is reloaded + * by hardware when the transfer mode is selected) + */ + u8 tmp, adj = (drive->dn & 1) ? 0x08 : 0x00; + + tmp = get_indexed_reg(hwif, 0x13 + adj); + set_indexed_reg(hwif, 0x13 + adj, tmp | 0x03); } speed = ide_dma_speed(drive, pdcnew_ratemask(drive)); @@ -211,7 +306,7 @@ static int config_chipset_for_dma (ide_drive_t *drive) return ide_dma_enable(drive); } -static int pdcnew_config_drive_xfer_rate (ide_drive_t *drive) +static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); struct hd_driveid *id = drive->id; @@ -236,9 +331,9 @@ fast_ata_pio: return 0; } -static int pdcnew_quirkproc (ide_drive_t *drive) +static int pdcnew_quirkproc(ide_drive_t *drive) { - return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); + return check_in_drive_lists(drive, pdc_quirk_drives); } static int pdcnew_ide_dma_lostirq(ide_drive_t *drive) @@ -255,21 +350,100 @@ static int pdcnew_ide_dma_timeout(ide_drive_t *drive) return __ide_dma_timeout(drive); } -static void pdcnew_new_reset (ide_drive_t *drive) +static void pdcnew_reset(ide_drive_t *drive) { /* * Deleted this because it is redundant from the caller. */ - printk(KERN_WARNING "PDC202XX: %s channel reset.\n", + printk(KERN_WARNING "pdc202xx_new: %s channel reset.\n", HWIF(drive)->channel ? "Secondary" : "Primary"); } +/** + * read_counter - Read the byte count registers + * @dma_base: for the port address + */ +static long __devinit read_counter(u32 dma_base) +{ + u32 pri_dma_base = dma_base, sec_dma_base = dma_base + 0x08; + u8 cnt0, cnt1, cnt2, cnt3; + long count = 0, last; + int retry = 3; + + do { + last = count; + + /* Read the current count */ + outb(0x20, pri_dma_base + 0x01); + cnt0 = inb(pri_dma_base + 0x03); + outb(0x21, pri_dma_base + 0x01); + cnt1 = inb(pri_dma_base + 0x03); + outb(0x20, sec_dma_base + 0x01); + cnt2 = inb(sec_dma_base + 0x03); + outb(0x21, sec_dma_base + 0x01); + cnt3 = inb(sec_dma_base + 0x03); + + count = (cnt3 << 23) | (cnt2 << 15) | (cnt1 << 8) | cnt0; + + /* + * The 30-bit decrementing counter is read in 4 pieces. + * Incorrect value may be read when the most significant bytes + * are changing... + */ + } while (retry-- && (((last ^ count) & 0x3fff8000) || last < count)); + + DBG("cnt0[%02X] cnt1[%02X] cnt2[%02X] cnt3[%02X]\n", + cnt0, cnt1, cnt2, cnt3); + + return count; +} + +/** + * detect_pll_input_clock - Detect the PLL input clock in Hz. + * @dma_base: for the port address + * E.g. 16949000 on 33 MHz PCI bus, i.e. half of the PCI clock. + */ +static long __devinit detect_pll_input_clock(unsigned long dma_base) +{ + long start_count, end_count; + long pll_input; + u8 scr1; + + start_count = read_counter(dma_base); + + /* Start the test mode */ + outb(0x01, dma_base + 0x01); + scr1 = inb(dma_base + 0x03); + DBG("scr1[%02X]\n", scr1); + outb(scr1 | 0x40, dma_base + 0x03); + + /* Let the counter run for 10 ms. */ + mdelay(10); + + end_count = read_counter(dma_base); + + /* Stop the test mode */ + outb(0x01, dma_base + 0x01); + scr1 = inb(dma_base + 0x03); + DBG("scr1[%02X]\n", scr1); + outb(scr1 & ~0x40, dma_base + 0x03); + + /* + * Calculate the input clock in Hz + * (the clock counter is 30 bit wide and counts down) + */ + pll_input = ((start_count - end_count) & 0x3ffffff) * 100; + + DBG("start[%ld] end[%ld]\n", start_count, end_count); + + return pll_input; +} + #ifdef CONFIG_PPC_PMAC static void __devinit apple_kiwi_init(struct pci_dev *pdev) { struct device_node *np = pci_device_to_OF_node(pdev); unsigned int class_rev = 0; - void __iomem *mmio; u8 conf; if (np == NULL || !device_is_compatible(np, "kiwi-root")) @@ -280,30 +454,20 @@ static void __devinit apple_kiwi_init(struct pci_dev *pdev) if (class_rev >= 0x03) { /* Setup chip magic config stuff (from darwin) */ - pci_read_config_byte(pdev, 0x40, &conf); - pci_write_config_byte(pdev, 0x40, conf | 0x01); - } - mmio = ioremap(pci_resource_start(pdev, 5), - pci_resource_len(pdev, 5)); - - /* Setup some PLL stuffs */ - switch (pdev->device) { - case PCI_DEVICE_ID_PROMISE_20270: - writew(0x0d2b, mmio + 0x1202); - mdelay(30); - break; - case PCI_DEVICE_ID_PROMISE_20271: - writew(0x0826, mmio + 0x1202); - mdelay(30); - break; + pci_read_config_byte (pdev, 0x40, &conf); + pci_write_config_byte(pdev, 0x40, (conf | 0x01)); } - - iounmap(mmio); } #endif /* CONFIG_PPC_PMAC */ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const char *name) { + unsigned long dma_base = pci_resource_start(dev, 4); + unsigned long sec_dma_base = dma_base + 0x08; + long pll_input, pll_output, ratio; + int f, r; + u8 pll_ctl0, pll_ctl1; + 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); @@ -315,6 +479,106 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha apple_kiwi_init(dev); #endif + /* Calculate the required PLL output frequency */ + switch(max_dma_rate(dev)) { + case 4: /* it's 133 MHz for Ultra133 chips */ + pll_output = 133333333; + break; + case 3: /* and 100 MHz for Ultra100 chips */ + default: + pll_output = 100000000; + break; + } + + /* + * Detect PLL input clock. + * On some systems, where PCI bus is running at non-standard clock rate + * (e.g. 25 or 40 MHz), we have to adjust the cycle time. + * PDC20268 and newer chips employ PLL circuit to help correct timing + * registers setting. + */ + pll_input = detect_pll_input_clock(dma_base); + printk("%s: PLL input clock is %ld kHz\n", name, pll_input / 1000); + + /* Sanity check */ + if (unlikely(pll_input < 5000000L || pll_input > 70000000L)) { + printk(KERN_ERR "%s: Bad PLL input clock %ld Hz, giving up!\n", + name, pll_input); + goto out; + } + +#ifdef DEBUG + DBG("pll_output is %ld Hz\n", pll_output); + + /* Show the current clock value of PLL control register + * (maybe already configured by the BIOS) + */ + outb(0x02, sec_dma_base + 0x01); + pll_ctl0 = inb(sec_dma_base + 0x03); + outb(0x03, sec_dma_base + 0x01); + pll_ctl1 = inb(sec_dma_base + 0x03); + + DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); +#endif + + /* + * Calculate the ratio of F, R and NO + * POUT = (F + 2) / (( R + 2) * NO) + */ + ratio = pll_output / (pll_input / 1000); + if (ratio < 8600L) { /* 8.6x */ + /* Using NO = 0x01, R = 0x0d */ + r = 0x0d; + } else if (ratio < 12900L) { /* 12.9x */ + /* Using NO = 0x01, R = 0x08 */ + r = 0x08; + } else if (ratio < 16100L) { /* 16.1x */ + /* Using NO = 0x01, R = 0x06 */ + r = 0x06; + } else if (ratio < 64000L) { /* 64x */ + r = 0x00; + } else { + /* Invalid ratio */ + printk(KERN_ERR "%s: Bad ratio %ld, giving up!\n", name, ratio); + goto out; + } + + f = (ratio * (r + 2)) / 1000 - 2; + + DBG("F[%d] R[%d] ratio*1000[%ld]\n", f, r, ratio); + + if (unlikely(f < 0 || f > 127)) { + /* Invalid F */ + printk(KERN_ERR "%s: F[%d] invalid!\n", name, f); + goto out; + } + + pll_ctl0 = (u8) f; + pll_ctl1 = (u8) r; + + DBG("Writing pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); + + outb(0x02, sec_dma_base + 0x01); + outb(pll_ctl0, sec_dma_base + 0x03); + outb(0x03, sec_dma_base + 0x01); + outb(pll_ctl1, sec_dma_base + 0x03); + + /* Wait the PLL circuit to be stable */ + mdelay(30); + +#ifdef DEBUG + /* + * Show the current clock value of PLL control register + */ + outb(0x02, sec_dma_base + 0x01); + pll_ctl0 = inb(sec_dma_base + 0x03); + outb(0x03, sec_dma_base + 0x01); + pll_ctl1 = inb(sec_dma_base + 0x03); + + DBG("pll_ctl[%02X][%02X]\n", pll_ctl0, pll_ctl1); +#endif + + out: return dev->irq; } @@ -324,8 +588,8 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) hwif->tuneproc = &pdcnew_tune_drive; hwif->quirkproc = &pdcnew_quirkproc; - hwif->speedproc = &pdcnew_new_tune_chipset; - hwif->resetproc = &pdcnew_new_reset; + hwif->speedproc = &pdcnew_tune_chipset; + hwif->resetproc = &pdcnew_reset; hwif->drives[0].autotune = hwif->drives[1].autotune = 1; @@ -337,11 +601,14 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate; hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq; hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout; - if (!(hwif->udma_four)) - hwif->udma_four = (pdcnew_new_cable_detect(hwif)) ? 0 : 1; + + if (!hwif->udma_four) + hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1; + if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; + #if PDC202_DEBUG_CABLE printk(KERN_DEBUG "%s: %s-pin cable\n", hwif->name, hwif->udma_four ? "80" : "40"); -- cgit v1.2.3 From ee2f344b33b507af23610c8fdfdde38d7c10fb33 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 10 Dec 2006 02:20:39 -0800 Subject: [PATCH] ide-cd: Handle strange interrupt on the Intel ESB2 The ESB2 appears to emit spurious DMA interrupts when configured for native mode and handling ATAPI devices. Stratus were able to pin this bug down and produce a patch. This is a rework which applies the fixup only to the ESB2 (for now). We can apply it to other chips later if the same problem is found. This code has been tested and confirmed to fix the problem on the tested systems. Signed-off-by: Alan Cox (Most of the hard work done by Stratus however) Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-cd.c | 7 +++++++ drivers/ide/pci/piix.c | 4 ++++ 2 files changed, 11 insertions(+) (limited to 'drivers/ide') diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 88214943d00..5969cec58dc 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -687,8 +687,15 @@ static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 sta static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) { struct request *rq = HWGROUP(drive)->rq; + ide_hwif_t *hwif = HWIF(drive); int stat, err, sense_key; + /* We may have bogus DMA interrupts in PIO state here */ + if (HWIF(drive)->dma_status && hwif->atapi_irq_bogon) { + stat = hwif->INB(hwif->dma_status); + /* Should we force the bit as well ? */ + hwif->OUTB(stat, hwif->dma_status); + } /* Check for errors. */ stat = HWIF(drive)->INB(IDE_STATUS_REG); if (stat_ret) diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index cdc3aab9ebc..b1e9a8eba6b 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -505,6 +505,10 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif) /* This is a painful system best to let it self tune for now */ return; } + /* ESB2 appears to generate spurious DMA interrupts in PIO mode + when in native mode */ + if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_ESB2_18) + hwif->atapi_irq_bogon = 1; hwif->autodma = 0; hwif->tuneproc = &piix_tune_drive; -- cgit v1.2.3 From 2b02a1792000900ead4638f4d42fcdd742062cfa Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Tue, 5 Dec 2006 10:19:14 +0100 Subject: [PATCH] remove blk_queue_activity_fn While working on bidi support at struct request level I have found that blk_queue_activity_fn is actually never used. The only user is in ide-probe.c with this code: /* enable led activity for disk drives only */ if (drive->media == ide_disk && hwif->led_act) blk_queue_activity_fn(q, hwif->led_act, drive); And led_act is never initialized anywhere. (Looking back at older kernels it was used in the PPC arch, but was removed around 2.6.18) Unless it is all for future use off course. (this patch is against linux-2.6-block.git as off 2006/12/4) Signed-off-by: Boaz Harrosh Signed-off-by: Jens Axboe --- drivers/ide/ide-probe.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index dad9c47ebb6..5a5c565a32a 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1000,10 +1000,6 @@ static int ide_init_queue(ide_drive_t *drive) /* needs drive->queue to be set */ ide_toggle_bounce(drive, 1); - /* enable led activity for disk drives only */ - if (drive->media == ide_disk && hwif->led_act) - blk_queue_activity_fn(q, hwif->led_act, drive); - return 0; } -- cgit v1.2.3 From bef1f40261c8bc5ad2ca70a5a1760b0eb79b6812 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Tue, 12 Dec 2006 20:04:19 +0100 Subject: kconfig: Standardize "depends" -> "depends on" in Kconfig files Standardize the miniscule percentage of occurrences of "depends" in Kconfig files to "depends on", and update kconfig-language.txt to reflect that. Signed-off-by: Robert P. J. Day Signed-off-by: Adrian Bunk --- drivers/ide/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ide') diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index e23bc0d6215..3f828052f8d 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -796,7 +796,7 @@ endchoice config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ int "Maximum transfer size (KB) per request (up to 128)" default "128" - depends BLK_DEV_IDE_AU1XXX + depends on BLK_DEV_IDE_AU1XXX config IDE_ARM def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) -- cgit v1.2.3 From 836c0063c74cc088ffe370d007e1c6cac95e7caa Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 13 Dec 2006 00:35:47 -0800 Subject: [PATCH] ide: HPT3xxN clocking fixes Fix serious problems with the HPT372N clock turnaround code: - the wrong ports were written to when called for the secondary channel; - it didn't serialize access to the channels; - turnaround shou;dn't be done on 66 MHz PCI; - caching the clock mode per-channel caused it to get out of sync with the actual register value. Additionally, avoid calibrating PLL twice (for each channel) as the second try results in a wrong PCI frequency and thus in the wrong timings. Make the driver deal with HPT302N and HPT371N correctly -- the clocking and (seemingly) a need for clock tunaround is the same as for HPT372N. HPT371/N chips have only one, secondary channel, so avoid touching their "pure virtual" primary channel, and disable it if the BIOS haven't done this already. Also, while at it, disable UltraATA/133 for HPT372 by default -- 50 MHz DPLL clock don't allow for this speed anyway. And remove the traces of the former bad patch that wasn't even applicable to this version of driver. Has been tested on HPT370/371N, unfortunately I don't have an instant access to the other chips... Signed-off-by: Sergei Shtylyov Cc: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/hpt366.c | 223 +++++++++++++++++++++++++++++------------------ 1 file changed, 139 insertions(+), 84 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index e993a51f250..7534171c2c6 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -4,6 +4,7 @@ * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. * Portions Copyright (C) 2003 Red Hat Inc + * Portions Copyright (C) 2005-2006 MontaVista Software, Inc. * * Thanks to HighPoint Technologies for their assistance, and hardware. * Special Thanks to Jon Burchmore in SanDiego for the deep pockets, his @@ -11,9 +12,11 @@ * development and support. * * - * Highpoint have their own driver (source except for the raid part) - * available from http://www.highpoint-tech.com/hpt3xx-opensource-v131.tgz - * This may be useful to anyone wanting to work on the mainstream hpt IDE. + * HighPoint has its own drivers (open source except for the RAID part) + * available from http://www.highpoint-tech.com/BIOS%20+%20Driver/. + * This may be useful to anyone wanting to work on this driver, however do not + * trust them too much since the code tends to become less and less meaningful + * as the time passes... :-/ * * Note that final HPT370 support was done by force extraction of GPL. * @@ -52,6 +55,20 @@ * keeping me sane. * Alan Cox * + * - fix the clock turnaround code: it was writing to the wrong ports when + * called for the secondary channel, caching the current clock mode per- + * channel caused the cached register value to get out of sync with the + * actual one, the channels weren't serialized, the turnaround shouldn't + * be done on 66 MHz PCI bus + * - avoid calibrating PLL twice as the second time results in a wrong PCI + * frequency and thus in the wrong timings for the secondary channel + * - disable UltraATA/133 for HPT372 by default (50 MHz DPLL clock do not + * allow for this speed anyway) + * - add support for HPT302N and HPT371N clocking (the same as for HPT372N) + * - HPT371/N are single channel chips, so avoid touching the primary channel + * which exists only virtually (there's no pins for it) + * + * */ @@ -76,8 +93,8 @@ /* various tuning parameters */ #define HPT_RESET_STATE_ENGINE -#undef HPT_DELAY_INTERRUPT -#undef HPT_SERIALIZE_IO +#undef HPT_DELAY_INTERRUPT +#define HPT_SERIALIZE_IO 0 static const char *quirk_drives[] = { "QUANTUM FIREBALLlct08 08", @@ -439,7 +456,7 @@ static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = { #define HPT374_ALLOW_ATA133_6 0 #define HPT371_ALLOW_ATA133_6 0 #define HPT302_ALLOW_ATA133_6 0 -#define HPT372_ALLOW_ATA133_6 1 +#define HPT372_ALLOW_ATA133_6 0 #define HPT370_ALLOW_ATA100_5 1 #define HPT366_ALLOW_ATA66_4 1 #define HPT366_ALLOW_ATA66_3 1 @@ -461,7 +478,8 @@ struct hpt_info int revision; /* Chipset revision */ int flags; /* Chipset properties */ #define PLL_MODE 1 -#define IS_372N 2 +#define IS_3xxN 2 +#define PCI_66MHZ 4 /* Speed table */ struct chipset_bus_clock_list_entry *speed; }; @@ -956,59 +974,63 @@ static int hpt374_ide_dma_end (ide_drive_t *drive) } /** - * hpt372n_set_clock - perform clock switching dance - * @drive: Drive to switch - * @mode: Switching mode (0x21 for write, 0x23 otherwise) + * hpt3xxn_set_clock - perform clock switching dance + * @hwif: hwif to switch + * @mode: clocking mode (0x21 for write, 0x23 otherwise) * - * Switch the DPLL clock on the HPT372N devices. This is a - * right mess. + * Switch the DPLL clock on the HPT3xxN devices. This is a right mess. + * NOTE: avoid touching the disabled primary channel on HPT371N -- it + * doesn't physically exist anyway... */ - -static void hpt372n_set_clock(ide_drive_t *drive, int mode) + +static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) { - ide_hwif_t *hwif = HWIF(drive); - - /* FIXME: should we check for DMA active and BUG() */ + u8 mcr1, scr2 = hwif->INB(hwif->dma_master + 0x7b); + + if ((scr2 & 0x7f) == mode) + return; + + /* MISC. control register 1 has the channel enable bit... */ + mcr1 = hwif->INB(hwif->dma_master + 0x70); + /* Tristate the bus */ - outb(0x80, hwif->dma_base+0x73); - outb(0x80, hwif->dma_base+0x77); - + if (mcr1 & 0x04) + hwif->OUTB(0x80, hwif->dma_master + 0x73); + hwif->OUTB(0x80, hwif->dma_master + 0x77); + /* Switch clock and reset channels */ - outb(mode, hwif->dma_base+0x7B); - outb(0xC0, hwif->dma_base+0x79); - + hwif->OUTB(mode, hwif->dma_master + 0x7b); + hwif->OUTB(0xc0, hwif->dma_master + 0x79); + /* Reset state machines */ - outb(0x37, hwif->dma_base+0x70); - outb(0x37, hwif->dma_base+0x74); - + if (mcr1 & 0x04) + hwif->OUTB(0x37, hwif->dma_master + 0x70); + hwif->OUTB(0x37, hwif->dma_master + 0x74); + /* Complete reset */ - outb(0x00, hwif->dma_base+0x79); - + hwif->OUTB(0x00, hwif->dma_master + 0x79); + /* Reconnect channels to bus */ - outb(0x00, hwif->dma_base+0x73); - outb(0x00, hwif->dma_base+0x77); + if (mcr1 & 0x04) + hwif->OUTB(0x00, hwif->dma_master + 0x73); + hwif->OUTB(0x00, hwif->dma_master + 0x77); } /** - * hpt372n_rw_disk - prepare for I/O + * hpt3xxn_rw_disk - prepare for I/O * @drive: drive for command * @rq: block request structure * - * This is called when a disk I/O is issued to the 372N. + * This is called when a disk I/O is issued to HPT3xxN. * We need it because of the clock switching. */ -static void hpt372n_rw_disk(ide_drive_t *drive, struct request *rq) +static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) { - ide_hwif_t *hwif = drive->hwif; - int wantclock; - - wantclock = rq_data_dir(rq) ? 0x23 : 0x21; + ide_hwif_t *hwif = HWIF(drive); + u8 wantclock = rq_data_dir(rq) ? 0x23 : 0x21; - if (hwif->config_data != wantclock) { - hpt372n_set_clock(drive, wantclock); - hwif->config_data = wantclock; - } + hpt3xxn_set_clock(hwif, wantclock); } /* @@ -1138,7 +1160,7 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) int adjust, i; u16 freq; u32 pll; - u8 reg5bh; + u8 reg5bh = 0, mcr1 = 0; /* * default to pci clock. make sure MA15/16 are set to output @@ -1161,17 +1183,11 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) freq &= 0x1FF; /* - * The 372N uses different PCI clock information and has - * some other complications - * On PCI33 timing we must clock switch - * On PCI66 timing we must NOT use the PCI clock - * - * Currently we always set up the PLL for the 372N + * HPT3xxN chips use different PCI clock information. + * Currently we always set up the PLL for them. */ - - if(info->flags & IS_372N) - { - printk(KERN_INFO "hpt: HPT372N detected, using 372N timing.\n"); + + if (info->flags & IS_3xxN) { if(freq < 0x55) pll = F_LOW_PCI_33; else if(freq < 0x70) @@ -1180,10 +1196,8 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pll = F_LOW_PCI_50; else pll = F_LOW_PCI_66; - - printk(KERN_INFO "FREQ: %d PLL: %d\n", freq, pll); - - /* We always use the pll not the PCI clock on 372N */ + + printk(KERN_INFO "HPT3xxN detected, FREQ: %d, PLL: %d\n", freq, pll); } else { @@ -1231,7 +1245,10 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n"); } } - + + if (pll == F_LOW_PCI_66) + info->flags |= PCI_66MHZ; + /* * only try the pll if we don't have a table for the clock * speed that we're running at. NOTE: the internal PLL will @@ -1287,10 +1304,6 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) goto init_hpt37X_done; } } - if (!pci_get_drvdata(dev)) { - printk("No Clock Stabilization!!!\n"); - return; - } pll_recal: if (adjust & 1) pll -= (adjust >> 1); @@ -1300,11 +1313,16 @@ pll_recal: init_hpt37X_done: if (!info->speed) - printk(KERN_ERR "HPT37X%s: unknown bus timing [%d %d].\n", - (info->flags & IS_372N)?"N":"", pll, freq); - /* reset state engine */ - pci_write_config_byte(dev, 0x50, 0x37); - pci_write_config_byte(dev, 0x54, 0x37); + printk(KERN_ERR "HPT37x%s: unknown bus timing [%d %d].\n", + (info->flags & IS_3xxN) ? "N" : "", pll, freq); + /* + * Reset the state engines. + * NOTE: avoid accidentally enabling the primary channel on HPT371N. + */ + pci_read_config_byte(dev, 0x50, &mcr1); + if (mcr1 & 0x04) + pci_write_config_byte(dev, 0x50, 0x37); + pci_write_config_byte(dev, 0x54, 0x37); udelay(100); } @@ -1367,6 +1385,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = ide_get_hwifdata(hwif); u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02; + int serialize = HPT_SERIALIZE_IO; hwif->tuneproc = &hpt3xx_tune_drive; hwif->speedproc = &hpt3xx_tune_chipset; @@ -1374,8 +1393,20 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->intrproc = &hpt3xx_intrproc; hwif->maskproc = &hpt3xx_maskproc; - if(info->flags & IS_372N) - hwif->rw_disk = &hpt372n_rw_disk; + /* + * HPT3xxN chips have some complications: + * + * - on 33 MHz PCI we must clock switch + * - on 66 MHz PCI we must NOT use the PCI clock + */ + if ((info->flags & (IS_3xxN | PCI_66MHZ)) == IS_3xxN) { + /* + * Clock is shared between the channels, + * so we'll have to serialize them... :-( + */ + serialize = 1; + hwif->rw_disk = &hpt3xxn_rw_disk; + } /* * The HPT37x uses the CBLID pins as outputs for MA15/MA16 @@ -1418,11 +1449,9 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) PCI_FUNC(hwif->pci_dev->devfn)); #endif /* DEBUG */ -#ifdef HPT_SERIALIZE_IO - /* serialize access to this device */ - if (hwif->mate) + /* Serialize access to this device */ + if (serialize && hwif->mate) hwif->serialized = hwif->mate->serialized = 1; -#endif if (info->revision >= 3) { u8 reg5ah = 0; @@ -1490,7 +1519,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) return; if(info->speed == NULL) { - printk(KERN_WARNING "hpt: no known IDE timings, disabling DMA.\n"); + printk(KERN_WARNING "hpt366: no known IDE timings, disabling DMA.\n"); return; } @@ -1519,9 +1548,10 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) static void __devinit init_iops_hpt366(ide_hwif_t *hwif) { - struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL); - unsigned long dmabase = pci_resource_start(hwif->pci_dev, 4); - u8 did, rid; + struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL); + struct pci_dev *dev = hwif->pci_dev; + u16 did = dev->device; + u8 rid = 0; if(info == NULL) { printk(KERN_WARNING "hpt366: out of memory.\n"); @@ -1529,15 +1559,22 @@ static void __devinit init_iops_hpt366(ide_hwif_t *hwif) } ide_set_hwifdata(hwif, info); - if(dmabase) { - did = inb(dmabase + 0x22); - rid = inb(dmabase + 0x28); - - if((did == 4 && rid == 6) || (did == 5 && rid > 1)) - info->flags |= IS_372N; + /* Avoid doing the same thing twice. */ + if (hwif->channel && hwif->mate) { + memcpy(info, ide_get_hwifdata(hwif->mate), sizeof(struct hpt_info)); + return; } - info->revision = hpt_revision(hwif->pci_dev); + pci_read_config_byte(dev, PCI_CLASS_REVISION, &rid); + + if (( did == PCI_DEVICE_ID_TTI_HPT366 && rid == 6) || + ((did == PCI_DEVICE_ID_TTI_HPT372 || + did == PCI_DEVICE_ID_TTI_HPT302 || + did == PCI_DEVICE_ID_TTI_HPT371) && rid > 1) || + did == PCI_DEVICE_ID_TTI_HPT372N) + info->flags |= IS_3xxN; + + info->revision = hpt_revision(dev); if (info->revision >= 3) hpt37x_clocking(hwif); @@ -1574,6 +1611,23 @@ static int __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d) return ide_setup_pci_device(dev, d); } +static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) +{ + u8 mcr1 = 0; + + /* + * HPT371 chips physically have only one channel, the secondary one, + * but the primary channel registers do exist! Go figure... + * So, we manually disable the non-existing channel here + * (if the BIOS hasn't done this already). + */ + pci_read_config_byte(dev, 0x50, &mcr1); + if (mcr1 & 0x04) + pci_write_config_byte(dev, 0x50, (mcr1 & ~0x04)); + + return ide_setup_pci_device(dev, d); +} + static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) { struct pci_dev *findev = NULL; @@ -1661,13 +1715,14 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .bootable = OFF_BOARD, },{ /* 3 */ .name = "HPT371", - .init_setup = init_setup_hpt37x, + .init_setup = init_setup_hpt371, .init_chipset = init_chipset_hpt366, .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, + .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, },{ /* 4 */ .name = "HPT374", -- cgit v1.2.3 From 9448732f6c9ef4932b226056338d1084f3669752 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 13 Dec 2006 00:35:49 -0800 Subject: [PATCH] ide: fix HPT37x timing tables Fix/remove bad/unused timing tables: HPT370/A 66 MHz tables weren't really needed (the chips are not UltraATA/133 capable and shouldn't support 66 MHz PCI) and had many modes over- and underclocked, HPT372 33 MHz table was in fact for 66 MHz and 50 MHz table missed UltraDMA mode 6, HPT374 33 MHz table was really for 50 MHz... (Actually, HPT370/A 33 MHz tables also have issues. e.g. HPT370 has PIO modes 0/1 overlocked.) There's also no need in the separate HPT374 tables because HPT372 timings should be the same (and those tables has UltraDMA mode 6 which HPT374 supports depending on HPT374_ALLOW_ATA133_6 #define)... Signed-off-by: Sergei Shtylyov Cc: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/hpt366.c | 149 +++++++++-------------------------------------- 1 file changed, 29 insertions(+), 120 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 7534171c2c6..51f40f2db77 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -67,6 +67,10 @@ * - add support for HPT302N and HPT371N clocking (the same as for HPT372N) * - HPT371/N are single channel chips, so avoid touching the primary channel * which exists only virtually (there's no pins for it) + * - fix/remove bad/unused timing tables: HPT370/A 66 MHz tables weren't really + * needed and had many modes over- and underclocked, HPT372 33 MHz table was + * for 66 MHz and 50 MHz table missed UltraDMA mode 6, HPT374 33 MHz table was + * really for 50 MHz; switch to using HPT372 tables for HPT374... * * */ @@ -264,26 +268,6 @@ static struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { { 0, 0x06514e57 } }; -static struct chipset_bus_clock_list_entry sixty_six_base_hpt370[] = { - { XFER_UDMA_5, 0x14846231 }, - { XFER_UDMA_4, 0x14886231 }, - { XFER_UDMA_3, 0x148c6231 }, - { XFER_UDMA_2, 0x148c6231 }, - { XFER_UDMA_1, 0x14906231 }, - { XFER_UDMA_0, 0x14986231 }, - - { XFER_MW_DMA_2, 0x26514e21 }, - { XFER_MW_DMA_1, 0x26514e33 }, - { XFER_MW_DMA_0, 0x26514e97 }, - - { XFER_PIO_4, 0x06514e21 }, - { XFER_PIO_3, 0x06514e22 }, - { XFER_PIO_2, 0x06514e33 }, - { XFER_PIO_1, 0x06914e43 }, - { XFER_PIO_0, 0x06914e57 }, - { 0, 0x06514e57 } -}; - /* these are the current (4 sep 2001) timings from highpoint */ static struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = { { XFER_UDMA_5, 0x12446231 }, @@ -305,27 +289,6 @@ static struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = { { 0, 0x06814ea7 } }; -/* 2x 33MHz timings */ -static struct chipset_bus_clock_list_entry sixty_six_base_hpt370a[] = { - { XFER_UDMA_5, 0x1488e673 }, - { XFER_UDMA_4, 0x1488e673 }, - { XFER_UDMA_3, 0x1498e673 }, - { XFER_UDMA_2, 0x1490e673 }, - { XFER_UDMA_1, 0x1498e677 }, - { XFER_UDMA_0, 0x14a0e73f }, - - { XFER_MW_DMA_2, 0x2480fa73 }, - { XFER_MW_DMA_1, 0x2480fa77 }, - { XFER_MW_DMA_0, 0x2480fb3f }, - - { XFER_PIO_4, 0x0c82be73 }, - { XFER_PIO_3, 0x0c82be95 }, - { XFER_PIO_2, 0x0c82beb7 }, - { XFER_PIO_1, 0x0d02bf37 }, - { XFER_PIO_0, 0x0d02bf5f }, - { 0, 0x0d02bf5f } -}; - static struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = { { XFER_UDMA_5, 0x12848242 }, { XFER_UDMA_4, 0x12ac8242 }, @@ -347,27 +310,28 @@ static struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = { }; static struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = { - { XFER_UDMA_6, 0x1c81dc62 }, - { XFER_UDMA_5, 0x1c6ddc62 }, - { XFER_UDMA_4, 0x1c8ddc62 }, - { XFER_UDMA_3, 0x1c8edc62 }, /* checkme */ - { XFER_UDMA_2, 0x1c91dc62 }, - { XFER_UDMA_1, 0x1c9adc62 }, /* checkme */ - { XFER_UDMA_0, 0x1c82dc62 }, /* checkme */ - - { XFER_MW_DMA_2, 0x2c829262 }, - { XFER_MW_DMA_1, 0x2c829266 }, /* checkme */ - { XFER_MW_DMA_0, 0x2c82922e }, /* checkme */ + { XFER_UDMA_6, 0x12446231 }, /* 0x12646231 ?? */ + { XFER_UDMA_5, 0x12446231 }, + { XFER_UDMA_4, 0x12446231 }, + { XFER_UDMA_3, 0x126c6231 }, + { XFER_UDMA_2, 0x12486231 }, + { XFER_UDMA_1, 0x124c6233 }, + { XFER_UDMA_0, 0x12506297 }, - { XFER_PIO_4, 0x0c829c62 }, - { XFER_PIO_3, 0x0c829c84 }, - { XFER_PIO_2, 0x0c829ca6 }, - { XFER_PIO_1, 0x0d029d26 }, - { XFER_PIO_0, 0x0d029d5e }, - { 0, 0x0d029d5e } + { XFER_MW_DMA_2, 0x22406c31 }, + { XFER_MW_DMA_1, 0x22406c33 }, + { XFER_MW_DMA_0, 0x22406c97 }, + + { XFER_PIO_4, 0x06414e31 }, + { XFER_PIO_3, 0x06414e42 }, + { XFER_PIO_2, 0x06414e53 }, + { XFER_PIO_1, 0x06814e93 }, + { XFER_PIO_0, 0x06814ea7 }, + { 0, 0x06814ea7 } }; static struct chipset_bus_clock_list_entry fifty_base_hpt372[] = { + { XFER_UDMA_6, 0x12848242 }, { XFER_UDMA_5, 0x12848242 }, { XFER_UDMA_4, 0x12ac8242 }, { XFER_UDMA_3, 0x128c8242 }, @@ -389,7 +353,7 @@ static struct chipset_bus_clock_list_entry fifty_base_hpt372[] = { static struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = { { XFER_UDMA_6, 0x1c869c62 }, - { XFER_UDMA_5, 0x1cae9c62 }, + { XFER_UDMA_5, 0x1cae9c62 }, /* 0x1c8a9c62 */ { XFER_UDMA_4, 0x1c8a9c62 }, { XFER_UDMA_3, 0x1c8e9c62 }, { XFER_UDMA_2, 0x1c929c62 }, @@ -408,50 +372,6 @@ static struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = { { 0, 0x0d029d26 } }; -static struct chipset_bus_clock_list_entry thirty_three_base_hpt374[] = { - { XFER_UDMA_6, 0x12808242 }, - { XFER_UDMA_5, 0x12848242 }, - { XFER_UDMA_4, 0x12ac8242 }, - { XFER_UDMA_3, 0x128c8242 }, - { XFER_UDMA_2, 0x120c8242 }, - { XFER_UDMA_1, 0x12148254 }, - { XFER_UDMA_0, 0x121882ea }, - - { XFER_MW_DMA_2, 0x22808242 }, - { XFER_MW_DMA_1, 0x22808254 }, - { XFER_MW_DMA_0, 0x228082ea }, - - { XFER_PIO_4, 0x0a81f442 }, - { XFER_PIO_3, 0x0a81f443 }, - { XFER_PIO_2, 0x0a81f454 }, - { XFER_PIO_1, 0x0ac1f465 }, - { XFER_PIO_0, 0x0ac1f48a }, - { 0, 0x06814e93 } -}; - -/* FIXME: 50MHz timings for HPT374 */ - -#if 0 -static struct chipset_bus_clock_list_entry sixty_six_base_hpt374[] = { - { XFER_UDMA_6, 0x12406231 }, /* checkme */ - { XFER_UDMA_5, 0x12446231 }, /* 0x14846231 */ - { XFER_UDMA_4, 0x16814ea7 }, /* 0x14886231 */ - { XFER_UDMA_3, 0x16814ea7 }, /* 0x148c6231 */ - { XFER_UDMA_2, 0x16814ea7 }, /* 0x148c6231 */ - { XFER_UDMA_1, 0x16814ea7 }, /* 0x14906231 */ - { XFER_UDMA_0, 0x16814ea7 }, /* 0x14986231 */ - { XFER_MW_DMA_2, 0x16814ea7 }, /* 0x26514e21 */ - { XFER_MW_DMA_1, 0x16814ea7 }, /* 0x26514e97 */ - { XFER_MW_DMA_0, 0x16814ea7 }, /* 0x26514e97 */ - { XFER_PIO_4, 0x06814ea7 }, /* 0x06514e21 */ - { XFER_PIO_3, 0x06814ea7 }, /* 0x06514e22 */ - { XFER_PIO_2, 0x06814ea7 }, /* 0x06514e33 */ - { XFER_PIO_1, 0x06814ea7 }, /* 0x06914e43 */ - { XFER_PIO_0, 0x06814ea7 }, /* 0x06914e57 */ - { 0, 0x06814ea7 } -}; -#endif - #define HPT366_DEBUG_DRIVE_INFO 0 #define HPT374_ALLOW_ATA133_6 0 #define HPT371_ALLOW_ATA133_6 0 @@ -1211,9 +1131,7 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pll = F_LOW_PCI_66; if (pll == F_LOW_PCI_33) { - if (info->revision >= 8) - info->speed = thirty_three_base_hpt374; - else if (info->revision >= 5) + if (info->revision >= 5) info->speed = thirty_three_base_hpt372; else if (info->revision >= 4) info->speed = thirty_three_base_hpt370a; @@ -1223,26 +1141,17 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) } else if (pll == F_LOW_PCI_40) { /* Unsupported */ } else if (pll == F_LOW_PCI_50) { - if (info->revision >= 8) - info->speed = fifty_base_hpt370a; - else if (info->revision >= 5) + if (info->revision >= 5) info->speed = fifty_base_hpt372; - else if (info->revision >= 4) - info->speed = fifty_base_hpt370a; else info->speed = fifty_base_hpt370a; printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n"); } else { - if (info->revision >= 8) { - printk(KERN_ERR "HPT37x: 66MHz timings are not supported.\n"); - } - else if (info->revision >= 5) + if (info->revision >= 5) { info->speed = sixty_six_base_hpt372; - else if (info->revision >= 4) - info->speed = sixty_six_base_hpt370a; - else - info->speed = sixty_six_base_hpt370; - printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n"); + printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n"); + } else + printk(KERN_ERR "HPT37x: 66MHz timings not supported.\n"); } } -- cgit v1.2.3 From 471a0bda5a2de5b0fd3b58255791eb831517a52c Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 13 Dec 2006 00:35:49 -0800 Subject: [PATCH] ide: optimize HPT37x timing tables Save some space on the timing tables by introducing the separate transfer mode table in which the mode lookup is done to get the index into the timing table itself. Get rid of the rest of the obsolete/duplicate tables and use one set of tables for the whole HPT37x chip family like the HighPoint open-source drivers do. Documnent the different timing register layout for the HPT36x chip family (this is my guesswork based on the timing values). Have been tested and works fine on HPT370/302/371N. Signed-off-by: Sergei Shtylyov Cc: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/hpt366.c | 404 ++++++++++++++++++++--------------------------- 1 file changed, 174 insertions(+), 230 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 51f40f2db77..787efd35db2 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -67,10 +67,9 @@ * - add support for HPT302N and HPT371N clocking (the same as for HPT372N) * - HPT371/N are single channel chips, so avoid touching the primary channel * which exists only virtually (there's no pins for it) - * - fix/remove bad/unused timing tables: HPT370/A 66 MHz tables weren't really - * needed and had many modes over- and underclocked, HPT372 33 MHz table was - * for 66 MHz and 50 MHz table missed UltraDMA mode 6, HPT374 33 MHz table was - * really for 50 MHz; switch to using HPT372 tables for HPT374... + * - fix/remove bad/unused timing tables and use one set of tables for the whole + * HPT37x chip family; save space by introducing the separate transfer mode + * table in which the mode lookup is done * * */ @@ -162,214 +161,168 @@ static const char *bad_ata33[] = { NULL }; -struct chipset_bus_clock_list_entry { - u8 xfer_speed; - unsigned int chipset_settings; +static u8 xfer_speeds[] = { + XFER_UDMA_6, + XFER_UDMA_5, + XFER_UDMA_4, + XFER_UDMA_3, + XFER_UDMA_2, + XFER_UDMA_1, + XFER_UDMA_0, + + XFER_MW_DMA_2, + XFER_MW_DMA_1, + XFER_MW_DMA_0, + + XFER_PIO_4, + XFER_PIO_3, + XFER_PIO_2, + XFER_PIO_1, + XFER_PIO_0 }; -/* key for bus clock timings - * bit - * 0:3 data_high_time. inactive time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 4:8 data_low_time. active time of DIOW_/DIOR_ for PIO and MW - * DMA. cycles = value + 1 - * 9:12 cmd_high_time. inactive time of DIOW_/DIOR_ during task file - * register access. - * 13:17 cmd_low_time. active time of DIOW_/DIOR_ during task file - * register access. - * 18:21 udma_cycle_time. clock freq and clock cycles for UDMA xfer. - * during task file register access. - * 22:24 pre_high_time. time to initialize 1st cycle for PIO and MW DMA - * xfer. - * 25:27 cmd_pre_high_time. time to initialize 1st PIO cycle for task - * register access. - * 28 UDMA enable - * 29 DMA enable - * 30 PIO_MST enable. if set, the chip is in bus master mode during - * PIO. - * 31 FIFO enable. +/* Key for bus clock timings + * 36x 37x + * bits bits + * 0:3 0:3 data_high_time. Inactive time of DIOW_/DIOR_ for PIO and MW DMA. + * cycles = value + 1 + * 4:7 4:8 data_low_time. Active time of DIOW_/DIOR_ for PIO and MW DMA. + * cycles = value + 1 + * 8:11 9:12 cmd_high_time. Inactive time of DIOW_/DIOR_ during task file + * register access. + * 12:15 13:17 cmd_low_time. Active time of DIOW_/DIOR_ during task file + * register access. + * 16:18 18:20 udma_cycle_time. Clock cycles for UDMA xfer. + * - 21 CLK frequency: 0=ATA clock, 1=dual ATA clock. + * 19:21 22:24 pre_high_time. Time to initialize the 1st cycle for PIO and + * MW DMA xfer. + * 22:24 25:27 cmd_pre_high_time. Time to initialize the 1st PIO cycle for + * task file register access. + * 28 28 UDMA enable. + * 29 29 DMA enable. + * 30 30 PIO MST enable. If set, the chip is in bus master mode during + * PIO xfer. + * 31 31 FIFO enable. */ -static struct chipset_bus_clock_list_entry forty_base_hpt366[] = { - { XFER_UDMA_4, 0x900fd943 }, - { XFER_UDMA_3, 0x900ad943 }, - { XFER_UDMA_2, 0x900bd943 }, - { XFER_UDMA_1, 0x9008d943 }, - { XFER_UDMA_0, 0x9008d943 }, - - { XFER_MW_DMA_2, 0xa008d943 }, - { XFER_MW_DMA_1, 0xa010d955 }, - { XFER_MW_DMA_0, 0xa010d9fc }, - - { XFER_PIO_4, 0xc008d963 }, - { XFER_PIO_3, 0xc010d974 }, - { XFER_PIO_2, 0xc010d997 }, - { XFER_PIO_1, 0xc010d9c7 }, - { XFER_PIO_0, 0xc018d9d9 }, - { 0, 0x0120d9d9 } -}; - -static struct chipset_bus_clock_list_entry thirty_three_base_hpt366[] = { - { XFER_UDMA_4, 0x90c9a731 }, - { XFER_UDMA_3, 0x90cfa731 }, - { XFER_UDMA_2, 0x90caa731 }, - { XFER_UDMA_1, 0x90cba731 }, - { XFER_UDMA_0, 0x90c8a731 }, - - { XFER_MW_DMA_2, 0xa0c8a731 }, - { XFER_MW_DMA_1, 0xa0c8a732 }, /* 0xa0c8a733 */ - { XFER_MW_DMA_0, 0xa0c8a797 }, - - { XFER_PIO_4, 0xc0c8a731 }, - { XFER_PIO_3, 0xc0c8a742 }, - { XFER_PIO_2, 0xc0d0a753 }, - { XFER_PIO_1, 0xc0d0a7a3 }, /* 0xc0d0a793 */ - { XFER_PIO_0, 0xc0d0a7aa }, /* 0xc0d0a7a7 */ - { 0, 0x0120a7a7 } -}; -static struct chipset_bus_clock_list_entry twenty_five_base_hpt366[] = { - { XFER_UDMA_4, 0x90c98521 }, - { XFER_UDMA_3, 0x90cf8521 }, - { XFER_UDMA_2, 0x90cf8521 }, - { XFER_UDMA_1, 0x90cb8521 }, - { XFER_UDMA_0, 0x90cb8521 }, - - { XFER_MW_DMA_2, 0xa0ca8521 }, - { XFER_MW_DMA_1, 0xa0ca8532 }, - { XFER_MW_DMA_0, 0xa0ca8575 }, - - { XFER_PIO_4, 0xc0ca8521 }, - { XFER_PIO_3, 0xc0ca8532 }, - { XFER_PIO_2, 0xc0ca8542 }, - { XFER_PIO_1, 0xc0d08572 }, - { XFER_PIO_0, 0xc0d08585 }, - { 0, 0x01208585 } +static u32 forty_base_hpt36x[] = { + /* XFER_UDMA_6 */ 0x900fd943, + /* XFER_UDMA_5 */ 0x900fd943, + /* XFER_UDMA_4 */ 0x900fd943, + /* XFER_UDMA_3 */ 0x900ad943, + /* XFER_UDMA_2 */ 0x900bd943, + /* XFER_UDMA_1 */ 0x9008d943, + /* XFER_UDMA_0 */ 0x9008d943, + + /* XFER_MW_DMA_2 */ 0xa008d943, + /* XFER_MW_DMA_1 */ 0xa010d955, + /* XFER_MW_DMA_0 */ 0xa010d9fc, + + /* XFER_PIO_4 */ 0xc008d963, + /* XFER_PIO_3 */ 0xc010d974, + /* XFER_PIO_2 */ 0xc010d997, + /* XFER_PIO_1 */ 0xc010d9c7, + /* XFER_PIO_0 */ 0xc018d9d9 }; -/* from highpoint documentation. these are old values */ -static struct chipset_bus_clock_list_entry thirty_three_base_hpt370[] = { -/* { XFER_UDMA_5, 0x1A85F442, 0x16454e31 }, */ - { XFER_UDMA_5, 0x16454e31 }, - { XFER_UDMA_4, 0x16454e31 }, - { XFER_UDMA_3, 0x166d4e31 }, - { XFER_UDMA_2, 0x16494e31 }, - { XFER_UDMA_1, 0x164d4e31 }, - { XFER_UDMA_0, 0x16514e31 }, - - { XFER_MW_DMA_2, 0x26514e21 }, - { XFER_MW_DMA_1, 0x26514e33 }, - { XFER_MW_DMA_0, 0x26514e97 }, - - { XFER_PIO_4, 0x06514e21 }, - { XFER_PIO_3, 0x06514e22 }, - { XFER_PIO_2, 0x06514e33 }, - { XFER_PIO_1, 0x06914e43 }, - { XFER_PIO_0, 0x06914e57 }, - { 0, 0x06514e57 } +static u32 thirty_three_base_hpt36x[] = { + /* XFER_UDMA_6 */ 0x90c9a731, + /* XFER_UDMA_5 */ 0x90c9a731, + /* XFER_UDMA_4 */ 0x90c9a731, + /* XFER_UDMA_3 */ 0x90cfa731, + /* XFER_UDMA_2 */ 0x90caa731, + /* XFER_UDMA_1 */ 0x90cba731, + /* XFER_UDMA_0 */ 0x90c8a731, + + /* XFER_MW_DMA_2 */ 0xa0c8a731, + /* XFER_MW_DMA_1 */ 0xa0c8a732, /* 0xa0c8a733 */ + /* XFER_MW_DMA_0 */ 0xa0c8a797, + + /* XFER_PIO_4 */ 0xc0c8a731, + /* XFER_PIO_3 */ 0xc0c8a742, + /* XFER_PIO_2 */ 0xc0d0a753, + /* XFER_PIO_1 */ 0xc0d0a7a3, /* 0xc0d0a793 */ + /* XFER_PIO_0 */ 0xc0d0a7aa /* 0xc0d0a7a7 */ }; -/* these are the current (4 sep 2001) timings from highpoint */ -static struct chipset_bus_clock_list_entry thirty_three_base_hpt370a[] = { - { XFER_UDMA_5, 0x12446231 }, - { XFER_UDMA_4, 0x12446231 }, - { XFER_UDMA_3, 0x126c6231 }, - { XFER_UDMA_2, 0x12486231 }, - { XFER_UDMA_1, 0x124c6233 }, - { XFER_UDMA_0, 0x12506297 }, - - { XFER_MW_DMA_2, 0x22406c31 }, - { XFER_MW_DMA_1, 0x22406c33 }, - { XFER_MW_DMA_0, 0x22406c97 }, - - { XFER_PIO_4, 0x06414e31 }, - { XFER_PIO_3, 0x06414e42 }, - { XFER_PIO_2, 0x06414e53 }, - { XFER_PIO_1, 0x06814e93 }, - { XFER_PIO_0, 0x06814ea7 }, - { 0, 0x06814ea7 } +static u32 twenty_five_base_hpt36x[] = { + /* XFER_UDMA_6 */ 0x90c98521, + /* XFER_UDMA_5 */ 0x90c98521, + /* XFER_UDMA_4 */ 0x90c98521, + /* XFER_UDMA_3 */ 0x90cf8521, + /* XFER_UDMA_2 */ 0x90cf8521, + /* XFER_UDMA_1 */ 0x90cb8521, + /* XFER_UDMA_0 */ 0x90cb8521, + + /* XFER_MW_DMA_2 */ 0xa0ca8521, + /* XFER_MW_DMA_1 */ 0xa0ca8532, + /* XFER_MW_DMA_0 */ 0xa0ca8575, + + /* XFER_PIO_4 */ 0xc0ca8521, + /* XFER_PIO_3 */ 0xc0ca8532, + /* XFER_PIO_2 */ 0xc0ca8542, + /* XFER_PIO_1 */ 0xc0d08572, + /* XFER_PIO_0 */ 0xc0d08585 }; -static struct chipset_bus_clock_list_entry fifty_base_hpt370a[] = { - { XFER_UDMA_5, 0x12848242 }, - { XFER_UDMA_4, 0x12ac8242 }, - { XFER_UDMA_3, 0x128c8242 }, - { XFER_UDMA_2, 0x120c8242 }, - { XFER_UDMA_1, 0x12148254 }, - { XFER_UDMA_0, 0x121882ea }, - - { XFER_MW_DMA_2, 0x22808242 }, - { XFER_MW_DMA_1, 0x22808254 }, - { XFER_MW_DMA_0, 0x228082ea }, - - { XFER_PIO_4, 0x0a81f442 }, - { XFER_PIO_3, 0x0a81f443 }, - { XFER_PIO_2, 0x0a81f454 }, - { XFER_PIO_1, 0x0ac1f465 }, - { XFER_PIO_0, 0x0ac1f48a }, - { 0, 0x0ac1f48a } +static u32 thirty_three_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x12446231, /* 0x12646231 ?? */ + /* XFER_UDMA_5 */ 0x12446231, + /* XFER_UDMA_4 */ 0x12446231, + /* XFER_UDMA_3 */ 0x126c6231, + /* XFER_UDMA_2 */ 0x12486231, + /* XFER_UDMA_1 */ 0x124c6233, + /* XFER_UDMA_0 */ 0x12506297, + + /* XFER_MW_DMA_2 */ 0x22406c31, + /* XFER_MW_DMA_1 */ 0x22406c33, + /* XFER_MW_DMA_0 */ 0x22406c97, + + /* XFER_PIO_4 */ 0x06414e31, + /* XFER_PIO_3 */ 0x06414e42, + /* XFER_PIO_2 */ 0x06414e53, + /* XFER_PIO_1 */ 0x06814e93, + /* XFER_PIO_0 */ 0x06814ea7 }; -static struct chipset_bus_clock_list_entry thirty_three_base_hpt372[] = { - { XFER_UDMA_6, 0x12446231 }, /* 0x12646231 ?? */ - { XFER_UDMA_5, 0x12446231 }, - { XFER_UDMA_4, 0x12446231 }, - { XFER_UDMA_3, 0x126c6231 }, - { XFER_UDMA_2, 0x12486231 }, - { XFER_UDMA_1, 0x124c6233 }, - { XFER_UDMA_0, 0x12506297 }, - - { XFER_MW_DMA_2, 0x22406c31 }, - { XFER_MW_DMA_1, 0x22406c33 }, - { XFER_MW_DMA_0, 0x22406c97 }, - - { XFER_PIO_4, 0x06414e31 }, - { XFER_PIO_3, 0x06414e42 }, - { XFER_PIO_2, 0x06414e53 }, - { XFER_PIO_1, 0x06814e93 }, - { XFER_PIO_0, 0x06814ea7 }, - { 0, 0x06814ea7 } +static u32 fifty_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x12848242, + /* XFER_UDMA_5 */ 0x12848242, + /* XFER_UDMA_4 */ 0x12ac8242, + /* XFER_UDMA_3 */ 0x128c8242, + /* XFER_UDMA_2 */ 0x120c8242, + /* XFER_UDMA_1 */ 0x12148254, + /* XFER_UDMA_0 */ 0x121882ea, + + /* XFER_MW_DMA_2 */ 0x22808242, + /* XFER_MW_DMA_1 */ 0x22808254, + /* XFER_MW_DMA_0 */ 0x228082ea, + + /* XFER_PIO_4 */ 0x0a81f442, + /* XFER_PIO_3 */ 0x0a81f443, + /* XFER_PIO_2 */ 0x0a81f454, + /* XFER_PIO_1 */ 0x0ac1f465, + /* XFER_PIO_0 */ 0x0ac1f48a }; -static struct chipset_bus_clock_list_entry fifty_base_hpt372[] = { - { XFER_UDMA_6, 0x12848242 }, - { XFER_UDMA_5, 0x12848242 }, - { XFER_UDMA_4, 0x12ac8242 }, - { XFER_UDMA_3, 0x128c8242 }, - { XFER_UDMA_2, 0x120c8242 }, - { XFER_UDMA_1, 0x12148254 }, - { XFER_UDMA_0, 0x121882ea }, - - { XFER_MW_DMA_2, 0x22808242 }, - { XFER_MW_DMA_1, 0x22808254 }, - { XFER_MW_DMA_0, 0x228082ea }, - - { XFER_PIO_4, 0x0a81f442 }, - { XFER_PIO_3, 0x0a81f443 }, - { XFER_PIO_2, 0x0a81f454 }, - { XFER_PIO_1, 0x0ac1f465 }, - { XFER_PIO_0, 0x0ac1f48a }, - { 0, 0x0a81f443 } -}; - -static struct chipset_bus_clock_list_entry sixty_six_base_hpt372[] = { - { XFER_UDMA_6, 0x1c869c62 }, - { XFER_UDMA_5, 0x1cae9c62 }, /* 0x1c8a9c62 */ - { XFER_UDMA_4, 0x1c8a9c62 }, - { XFER_UDMA_3, 0x1c8e9c62 }, - { XFER_UDMA_2, 0x1c929c62 }, - { XFER_UDMA_1, 0x1c9a9c62 }, - { XFER_UDMA_0, 0x1c829c62 }, - - { XFER_MW_DMA_2, 0x2c829c62 }, - { XFER_MW_DMA_1, 0x2c829c66 }, - { XFER_MW_DMA_0, 0x2c829d2e }, - - { XFER_PIO_4, 0x0c829c62 }, - { XFER_PIO_3, 0x0c829c84 }, - { XFER_PIO_2, 0x0c829ca6 }, - { XFER_PIO_1, 0x0d029d26 }, - { XFER_PIO_0, 0x0d029d5e }, - { 0, 0x0d029d26 } +static u32 sixty_six_base_hpt37x[] = { + /* XFER_UDMA_6 */ 0x1c869c62, + /* XFER_UDMA_5 */ 0x1cae9c62, /* 0x1c8a9c62 */ + /* XFER_UDMA_4 */ 0x1c8a9c62, + /* XFER_UDMA_3 */ 0x1c8e9c62, + /* XFER_UDMA_2 */ 0x1c929c62, + /* XFER_UDMA_1 */ 0x1c9a9c62, + /* XFER_UDMA_0 */ 0x1c829c62, + + /* XFER_MW_DMA_2 */ 0x2c829c62, + /* XFER_MW_DMA_1 */ 0x2c829c66, + /* XFER_MW_DMA_0 */ 0x2c829d2e, + + /* XFER_PIO_4 */ 0x0c829c62, + /* XFER_PIO_3 */ 0x0c829c84, + /* XFER_PIO_2 */ 0x0c829ca6, + /* XFER_PIO_1 */ 0x0d029d26, + /* XFER_PIO_0 */ 0x0d029d5e }; #define HPT366_DEBUG_DRIVE_INFO 0 @@ -401,7 +354,7 @@ struct hpt_info #define IS_3xxN 2 #define PCI_66MHZ 4 /* Speed table */ - struct chipset_bus_clock_list_entry *speed; + u32 *speed; }; /* @@ -538,12 +491,20 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) return 0; } -static unsigned int pci_bus_clock_list (u8 speed, struct chipset_bus_clock_list_entry * chipset_table) +static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table) { - for ( ; chipset_table->xfer_speed ; chipset_table++) - if (chipset_table->xfer_speed == speed) - return chipset_table->chipset_settings; - return chipset_table->chipset_settings; + int i; + + /* + * Lookup the transfer mode table to get the index into + * the timing table. + * + * NOTE: For XFER_PIO_SLOW, PIO mode 0 timings will be used. + */ + for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++) + if (xfer_speeds[i] == speed) + break; + return chipset_table[i]; } static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) @@ -1061,14 +1022,14 @@ static void __devinit hpt366_clocking(ide_hwif_t *hwif) /* detect bus speed by looking at control reg timing: */ switch((reg1 >> 8) & 7) { case 5: - info->speed = forty_base_hpt366; + info->speed = forty_base_hpt36x; break; case 9: - info->speed = twenty_five_base_hpt366; + info->speed = twenty_five_base_hpt36x; break; case 7: default: - info->speed = thirty_three_base_hpt366; + info->speed = thirty_three_base_hpt36x; break; } } @@ -1131,27 +1092,16 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pll = F_LOW_PCI_66; if (pll == F_LOW_PCI_33) { - if (info->revision >= 5) - info->speed = thirty_three_base_hpt372; - else if (info->revision >= 4) - info->speed = thirty_three_base_hpt370a; - else - info->speed = thirty_three_base_hpt370; + info->speed = thirty_three_base_hpt37x; printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n"); } else if (pll == F_LOW_PCI_40) { /* Unsupported */ } else if (pll == F_LOW_PCI_50) { - if (info->revision >= 5) - info->speed = fifty_base_hpt372; - else - info->speed = fifty_base_hpt370a; + info->speed = fifty_base_hpt37x; printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n"); } else { - if (info->revision >= 5) { - info->speed = sixty_six_base_hpt372; - printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n"); - } else - printk(KERN_ERR "HPT37x: 66MHz timings not supported.\n"); + info->speed = sixty_six_base_hpt37x; + printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n"); } } @@ -1201,14 +1151,8 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pci_write_config_dword(dev, 0x5c, pll & ~0x100); pci_write_config_byte(dev, 0x5b, 0x21); - if (info->revision >= 8) - info->speed = fifty_base_hpt370a; - else if (info->revision >= 5) - info->speed = fifty_base_hpt372; - else if (info->revision >= 4) - info->speed = fifty_base_hpt370a; - else - info->speed = fifty_base_hpt370a; + + info->speed = fifty_base_hpt37x; printk("HPT37X: using 50MHz internal PLL\n"); goto init_hpt37X_done; } -- cgit v1.2.3 From 33b18a602525198ab8892789dab6839f325407f8 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 13 Dec 2006 00:35:50 -0800 Subject: [PATCH] ide: fix HPT3xx hotswap support Fix the broken hotswap code: on HPT37x it caused RESET- to glitch when tristating the bus (the MISC control 3/6 and soft control 2 need to be written to in the certain order), and for HPT36x the obsolete HDIO_TRISTATE_HWIF ioctl() handler was called instead which treated the state argument wrong. Also, get rid of the soft control reg. 1 wtite to enable IDE interrupt -- this is done in init_hpt37x() already... Have been tested on HPT370 and 371N. Signed-off-by: Sergei Shtylyov Cc: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/hpt366.c | 115 +++++++++++++++-------------------------------- 1 file changed, 36 insertions(+), 79 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 787efd35db2..29a37704432 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -70,6 +70,8 @@ * - fix/remove bad/unused timing tables and use one set of tables for the whole * HPT37x chip family; save space by introducing the separate transfer mode * table in which the mode lookup is done + * - fix the hotswap code: it caused RESET- to glitch when tristating the bus, + * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead * * */ @@ -914,101 +916,68 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) hpt3xxn_set_clock(hwif, wantclock); } -/* - * Since SUN Cobalt is attempting to do this operation, I should disclose - * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date - * HOTSWAP ATA Infrastructure. - */ - -static void hpt3xx_reset (ide_drive_t *drive) -{ -} - -static int hpt3xx_tristate (ide_drive_t * drive, int state) -{ - ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - u8 reg59h = 0, reset = (hwif->channel) ? 0x80 : 0x40; - u8 regXXh = 0, state_reg= (hwif->channel) ? 0x57 : 0x53; - - pci_read_config_byte(dev, 0x59, ®59h); - pci_read_config_byte(dev, state_reg, ®XXh); - - if (state) { - (void) ide_do_reset(drive); - pci_write_config_byte(dev, state_reg, regXXh|0x80); - pci_write_config_byte(dev, 0x59, reg59h|reset); - } else { - pci_write_config_byte(dev, 0x59, reg59h & ~(reset)); - pci_write_config_byte(dev, state_reg, regXXh & ~(0x80)); - (void) ide_do_reset(drive); - } - return 0; -} - /* - * set/get power state for a drive. - * turning the power off does the following things: - * 1) soft-reset the drive - * 2) tri-states the ide bus + * Set/get power state for a drive. * - * when we turn things back on, we need to re-initialize things. + * When we turn the power back on, we need to re-initialize things. */ #define TRISTATE_BIT 0x8000 -static int hpt370_busproc(ide_drive_t * drive, int state) + +static int hpt3xx_busproc(ide_drive_t *drive, int state) { ide_hwif_t *hwif = drive->hwif; struct pci_dev *dev = hwif->pci_dev; - u8 tristate = 0, resetmask = 0, bus_reg = 0; - u16 tri_reg; + u8 tristate, resetmask, bus_reg = 0; + u16 tri_reg = 0; hwif->bus_state = state; if (hwif->channel) { /* secondary channel */ - tristate = 0x56; - resetmask = 0x80; + tristate = 0x56; + resetmask = 0x80; } else { /* primary channel */ - tristate = 0x52; + tristate = 0x52; resetmask = 0x40; } - /* grab status */ + /* Grab the status. */ pci_read_config_word(dev, tristate, &tri_reg); pci_read_config_byte(dev, 0x59, &bus_reg); - /* set the state. we don't set it if we don't need to do so. - * make sure that the drive knows that it has failed if it's off */ + /* + * Set the state. We don't set it if we don't need to do so. + * Make sure that the drive knows that it has failed if it's off. + */ switch (state) { case BUSSTATE_ON: - hwif->drives[0].failures = 0; - hwif->drives[1].failures = 0; - if ((bus_reg & resetmask) == 0) + if (!(bus_reg & resetmask)) return 0; - tri_reg &= ~TRISTATE_BIT; - bus_reg &= ~resetmask; - break; + hwif->drives[0].failures = hwif->drives[1].failures = 0; + + pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask); + pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT); + return 0; case BUSSTATE_OFF: - hwif->drives[0].failures = hwif->drives[0].max_failures + 1; - hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - if ((tri_reg & TRISTATE_BIT) == 0 && (bus_reg & resetmask)) + if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT)) return 0; tri_reg &= ~TRISTATE_BIT; - bus_reg |= resetmask; break; case BUSSTATE_TRISTATE: - hwif->drives[0].failures = hwif->drives[0].max_failures + 1; - hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - if ((tri_reg & TRISTATE_BIT) && (bus_reg & resetmask)) + if ((bus_reg & resetmask) && (tri_reg & TRISTATE_BIT)) return 0; tri_reg |= TRISTATE_BIT; - bus_reg |= resetmask; break; + default: + return -EINVAL; } - pci_write_config_byte(dev, 0x59, bus_reg); - pci_write_config_word(dev, tristate, tri_reg); + hwif->drives[0].failures = hwif->drives[0].max_failures + 1; + hwif->drives[1].failures = hwif->drives[1].max_failures + 1; + + pci_write_config_word(dev, tristate, tri_reg); + pci_write_config_byte(dev, 0x59, bus_reg | resetmask); return 0; } @@ -1306,23 +1275,11 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) if (serialize && hwif->mate) hwif->serialized = hwif->mate->serialized = 1; - if (info->revision >= 3) { - u8 reg5ah = 0; - pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); - /* - * set up ioctl for power status. - * note: power affects both - * drives on each channel - */ - hwif->resetproc = &hpt3xx_reset; - hwif->busproc = &hpt370_busproc; - } else if (info->revision >= 2) { - hwif->resetproc = &hpt3xx_reset; - hwif->busproc = &hpt3xx_tristate; - } else { - hwif->resetproc = &hpt3xx_reset; - hwif->busproc = &hpt3xx_tristate; - } + /* + * Set up ioctl for power status. + * NOTE: power affects both drives on each channel. + */ + hwif->busproc = &hpt3xx_busproc; if (!hwif->dma_base) { hwif->drives[0].autotune = 1; -- cgit v1.2.3 From 73d1dd93c462b52512685fe118159eafc7eb9f7e Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 13 Dec 2006 00:35:51 -0800 Subject: [PATCH] ide: fix the case of multiple HPT3xx chips present init_chipset_hpt366() modifies some fields of the ide_pci_device_t structure depending on the chip's revision, so pass it a copy of the structure to avoid issues when multiple different chips are present. Signed-off-by: Sergei Shtylyov Cc: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/hpt366.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 29a37704432..4968b16fa30 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -72,6 +72,8 @@ * table in which the mode lookup is done * - fix the hotswap code: it caused RESET- to glitch when tristating the bus, * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead + * - pass to init_chipset() handlers a copy of the IDE PCI device structure as + * they tamper with its fields * * */ @@ -1564,13 +1566,16 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { * * Called when the PCI registration layer (or the IDE initialization) * finds a device matching our IDE device tables. + * + * NOTE: since we'll have to modify some fields of the ide_pci_device_t + * structure depending on the chip's revision, we'd better pass a local + * copy down the call chain... */ - static int __devinit hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_pci_device_t *d = &hpt366_chipsets[id->driver_data]; + ide_pci_device_t d = hpt366_chipsets[id->driver_data]; - return d->init_setup(dev, d); + return d.init_setup(dev, &d); } static struct pci_device_id hpt366_pci_tbl[] = { -- cgit v1.2.3 From 26c068daf089aa21844236c97d05049b9497cc0a Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 13 Dec 2006 00:35:52 -0800 Subject: [PATCH] ide: HPT3xx: fix PCI clock detection Use the f_CNT value saved by the HighPoint BIOS if available as reading it directly would give us a wrong PCI frequency after DPLL has already been calibrated by BIOS. Signed-off-by: Sergei Shtylyov Cc: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/hpt366.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 4968b16fa30..9fd50801d38 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -70,6 +70,8 @@ * - fix/remove bad/unused timing tables and use one set of tables for the whole * HPT37x chip family; save space by introducing the separate transfer mode * table in which the mode lookup is done + * - use f_CNT value saved by the HighPoint BIOS as reading it directly gives + * the wrong PCI frequency since DPLL has already been calibrated by BIOS * - fix the hotswap code: it caused RESET- to glitch when tristating the bus, * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead * - pass to init_chipset() handlers a copy of the IDE PCI device structure as @@ -1010,8 +1012,8 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) struct hpt_info *info = ide_get_hwifdata(hwif); struct pci_dev *dev = hwif->pci_dev; int adjust, i; - u16 freq; - u32 pll; + u16 freq = 0; + u32 pll, temp = 0; u8 reg5bh = 0, mcr1 = 0; /* @@ -1025,15 +1027,34 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pci_write_config_byte(dev, 0x5b, 0x23); /* - * set up the PLL. we need to adjust it so that it's stable. - * freq = Tpll * 192 / Tpci + * We'll have to read f_CNT value in order to determine + * the PCI clock frequency according to the following ratio: * - * Todo. For non x86 should probably check the dword is - * set to 0xABCDExxx indicating the BIOS saved f_CNT + * f_CNT = Fpci * 192 / Fdpll + * + * First try reading the register in which the HighPoint BIOS + * saves f_CNT value before reprogramming the DPLL from its + * default setting (which differs for the various chips). + * In case the signature check fails, we'll have to resort to + * reading the f_CNT register itself in hopes that nobody has + * touched the DPLL yet... */ - pci_read_config_word(dev, 0x78, &freq); - freq &= 0x1FF; - + pci_read_config_dword(dev, 0x70, &temp); + if ((temp & 0xFFFFF000) != 0xABCDE000) { + int i; + + printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n"); + + /* Calculate the average value of f_CNT */ + for (temp = i = 0; i < 128; i++) { + pci_read_config_word(dev, 0x78, &freq); + temp += freq & 0x1ff; + mdelay(1); + } + freq = temp / 128; + } else + freq = temp & 0x1ff; + /* * HPT3xxN chips use different PCI clock information. * Currently we always set up the PLL for them. @@ -1095,11 +1116,8 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) info->flags |= PLL_MODE; /* - * FIXME: make this work correctly, esp with 372N as per - * reference driver code. - * - * adjust PLL based upon PCI clock, enable it, and wait for - * stabilization. + * Adjust the PLL based upon the PCI clock, enable it, and + * wait for stabilization... */ adjust = 0; freq = (pll < F_LOW_PCI_50) ? 2 : 4; -- cgit v1.2.3 From f13c152684a7f99ead26525270ed3e28a1d2467f Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 13 Dec 2006 00:35:53 -0800 Subject: [PATCH] HPT37x: read f_CNT saved by BIOS from port The undocumented register BIOS uses for saving f_CNT seems to only be mapped to I/O space while all the other HPT3xx regs are dual-mapped. Looks like another HighPoint's dirty trick. With this patch, the deadly kernel oops on the cards having the modern HighPoint BIOSes is now at last gone! Signed-off-by: Sergei Shtylyov Cc: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/hpt366.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 9fd50801d38..08119da06d5 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1035,14 +1035,14 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) * First try reading the register in which the HighPoint BIOS * saves f_CNT value before reprogramming the DPLL from its * default setting (which differs for the various chips). + * NOTE: This register is only accessible via I/O space. + * * In case the signature check fails, we'll have to resort to * reading the f_CNT register itself in hopes that nobody has * touched the DPLL yet... */ - pci_read_config_dword(dev, 0x70, &temp); + temp = inl(pci_resource_start(dev, 4) + 0x90); if ((temp & 0xFFFFF000) != 0xABCDE000) { - int i; - printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n"); /* Calculate the average value of f_CNT */ -- cgit v1.2.3 From 5cbded585d129d0226cb48ac4202b253c781be26 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Wed, 13 Dec 2006 00:35:56 -0800 Subject: [PATCH] getting rid of all casts of k[cmz]alloc() calls Run this: #!/bin/sh for f in $(grep -Erl "\([^\)]*\) *k[cmz]alloc" *) ; do echo "De-casting $f..." perl -pi -e "s/ ?= ?\([^\)]*\) *(k[cmz]alloc) *\(/ = \1\(/" $f done And then go through and reinstate those cases where code is casting pointers to non-pointers. And then drop a few hunks which conflicted with outstanding work. Cc: Russell King , Ian Molton Cc: Mikael Starvik Cc: Yoshinori Sato Cc: Roman Zippel Cc: Geert Uytterhoeven Cc: Ralf Baechle Cc: Paul Mackerras Cc: Kyle McMartin Cc: Benjamin Herrenschmidt Cc: Martin Schwidefsky Cc: "David S. Miller" Cc: Jeff Dike Cc: Greg KH Cc: Jens Axboe Cc: Paul Fulghum Cc: Alan Cox Cc: Karsten Keil Cc: Mauro Carvalho Chehab Cc: Jeff Garzik Cc: James Bottomley Cc: Ian Kent Cc: Steven French Cc: David Woodhouse Cc: Neil Brown Cc: Jaroslav Kysela Cc: Takashi Iwai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ide-floppy.c | 2 +- drivers/ide/ide-tape.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index e3a267622bb..d33717c8afd 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -2147,7 +2147,7 @@ static int ide_floppy_probe(ide_drive_t *drive) printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name); goto failed; } - if ((floppy = (idefloppy_floppy_t *) kzalloc (sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { + if ((floppy = kzalloc(sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) { printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name); goto failed; } diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index e2f4bb54906..b3bcd1d7315 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2573,11 +2573,11 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full, int pages = tape->pages_per_stage; char *b_data = NULL; - if ((stage = (idetape_stage_t *) kmalloc (sizeof (idetape_stage_t),GFP_KERNEL)) == NULL) + if ((stage = kmalloc(sizeof (idetape_stage_t),GFP_KERNEL)) == NULL) return NULL; stage->next = NULL; - bh = stage->bh = (struct idetape_bh *)kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); + bh = stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); if (bh == NULL) goto abort; bh->b_reqnext = NULL; @@ -2607,7 +2607,7 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full, continue; } prev_bh = bh; - if ((bh = (struct idetape_bh *)kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) { + if ((bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) { free_page((unsigned long) b_data); goto abort; } @@ -4860,7 +4860,7 @@ static int ide_tape_probe(ide_drive_t *drive) printk(KERN_WARNING "ide-tape: Use drive %s with ide-scsi emulation and osst.\n", drive->name); printk(KERN_WARNING "ide-tape: OnStream support will be removed soon from ide-tape!\n"); } - tape = (idetape_tape_t *) kzalloc (sizeof (idetape_tape_t), GFP_KERNEL); + tape = kzalloc(sizeof (idetape_tape_t), GFP_KERNEL); if (tape == NULL) { printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); goto failed; -- cgit v1.2.3 From ab17443a3df35abe4b7529e83511a591aa7384f3 Mon Sep 17 00:00:00 2001 From: Conke Hu Date: Tue, 19 Dec 2006 13:11:37 -0800 Subject: PCI: ATI sb600 sata quirk Acked-by: Jeff Garzik Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/ide/pci/atiixp.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index d55b938b1ae..ffdffb6379e 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -368,7 +368,6 @@ static struct pci_device_id atiixp_pci_tbl[] = { { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, PCI_ANY_ID, PCI_ANY_ID, (PCI_CLASS_STORAGE_IDE<<8)|0x8a, 0xffff05, 1}, { 0, }, }; MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl); -- cgit v1.2.3 From 242ce41fc92214c3430495edd43783c3ba3dcd2b Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 29 Dec 2006 16:49:18 -0800 Subject: [PATCH] PIIX: remove check for broken MW DMA mode 0 There's no need to check in piix_config_drive_for_dma() for broken MW DMA mode 0 as this mode is not supported by the driver (it sets hwif->mwdma_mask to 0x6), and hence can't be selected by ide_dma_speed(). (Alan sayeth "Probably right but if not you've got a subtle corruptor. Should at least stick a BUG_ON mode 0 setting right close when the mode is set.") Signed-off-by: Sergei Shtylyov Cc: Alan Cox Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/piix.c | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index b1e9a8eba6b..8ecd2d668db 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -352,33 +352,6 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed) return (ide_config_drive_speed(drive, speed)); } -/** - * piix_faulty_dma0 - check for DMA0 errata - * @hwif: IDE interface to check - * - * If an ICH/ICH0/ICH2 interface is is operating in multi-word - * DMA mode with 600nS cycle time the IDE PIO prefetch buffer will - * inadvertently provide an extra piece of secondary data to the primary - * device resulting in data corruption. - * - * With such a device this test function returns true. This allows - * our tuning code to follow Intel recommendations and use PIO on - * such devices. - */ - -static int piix_faulty_dma0(ide_hwif_t *hwif) -{ - switch(hwif->pci_dev->device) - { - case PCI_DEVICE_ID_INTEL_82801AA_1: /* ICH */ - case PCI_DEVICE_ID_INTEL_82801AB_1: /* ICH0 */ - case PCI_DEVICE_ID_INTEL_82801BA_8: /* ICH2 */ - case PCI_DEVICE_ID_INTEL_82801BA_9: /* ICH2 */ - return 1; - } - return 0; -} - /** * piix_config_drive_for_dma - configure drive for DMA * @drive: IDE drive to configure @@ -391,10 +364,6 @@ static int piix_faulty_dma0(ide_hwif_t *hwif) static int piix_config_drive_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, piix_ratemask(drive)); - - /* Some ICH devices cannot support DMA mode 0 */ - if(speed == XFER_MW_DMA_0 && piix_faulty_dma0(HWIF(drive))) - speed = 0; /* If no DMA speed was available or the chipset has DMA bugs then disable DMA and use PIO */ -- cgit v1.2.3 From 44854add66811124a5667466245b6824f751143a Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 29 Dec 2006 16:49:26 -0800 Subject: [PATCH] PIIX/SLC90E66: PIO mode fallback fix The fallback to PIO mode in the hwif->dma_check() handler doesn't work in the Intel PIIX and SMsC SLC90E66 IDE drivers because: - config_drive_for_dma() calls the hwif->speedproc() handler with a wrong mode number (unbiased by XFER_PIO_0) in case of the PIO fallback; - hwif->tuneproc() handler doesn't really set the drive's own speed (this is not fixed as yet). Signed-off-by: Sergei Shtylyov Cc: Alan Cox Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/piix.c | 33 ++++++++++++++++----------------- drivers/ide/pci/slc90e66.c | 20 +++++++++----------- 2 files changed, 25 insertions(+), 28 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 8ecd2d668db..edb37f3d558 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -1,13 +1,14 @@ /* - * linux/drivers/ide/pci/piix.c Version 0.44 March 20, 2003 + * linux/drivers/ide/pci/piix.c Version 0.45 May 12, 2006 * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick * Copyright (C) 2003 Red Hat Inc + * Copyright (C) 2006 MontaVista Software, Inc. * * May be copied or modified under the terms of the GNU General Public License * - * PIO mode setting function for Intel chipsets. + * PIO mode setting function for Intel chipsets. * For use instead of BIOS settings. * * 40-41 @@ -25,7 +26,7 @@ * sitre = word42 & 0x4000; secondary * * 44 8421|8421 hdd|hdb - * + * * 48 8421 hdd|hdc|hdb|hda udma enabled * * 0001 hda @@ -357,21 +358,20 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed) * @drive: IDE drive to configure * * Set up a PIIX interface channel for the best available speed. - * We prefer UDMA if it is available and then MWDMA. If DMA is - * not available we switch to PIO and return 0. + * We prefer UDMA if it is available and then MWDMA. If DMA is + * not available we switch to PIO and return 0. */ static int piix_config_drive_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, piix_ratemask(drive)); - /* If no DMA speed was available or the chipset has DMA bugs - then disable DMA and use PIO */ - - if (!speed || no_piix_dma) { - u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); - speed = piix_dma_2_pio(XFER_PIO_0 + tspeed); - } + /* + * If no DMA speed was available or the chipset has DMA bugs + * then disable DMA and use PIO + */ + if (!speed || no_piix_dma) + return 0; (void) piix_tune_chipset(drive, speed); return ide_dma_enable(drive); @@ -394,17 +394,16 @@ static int piix_config_drive_xfer_rate (ide_drive_t *drive) if ((id->capability & 1) && drive->autodma) { - if (ide_use_dma(drive)) { - if (piix_config_drive_for_dma(drive)) - return hwif->ide_dma_on(drive); - } + if (ide_use_dma(drive) && piix_config_drive_for_dma(drive)) + return hwif->ide_dma_on(drive); goto fast_ata_pio; } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: /* Find best PIO mode. */ - hwif->tuneproc(drive, 255); + (void) hwif->speedproc(drive, XFER_PIO_0 + + ide_get_best_pio_mode(drive, 255, 4, NULL)); return hwif->ide_dma_off_quietly(drive); } /* IORDY not supported */ diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index 4a1853af3bb..9be7e49cba0 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -1,9 +1,10 @@ /* - * linux/drivers/ide/pci/slc90e66.c Version 0.11 September 11, 2002 + * linux/drivers/ide/pci/slc90e66.c Version 0.12 May 12, 2006 * * Copyright (C) 2000-2002 Andre Hedrick + * Copyright (C) 2006 MontaVista Software, Inc. * - * This a look-a-like variation of the ICH0 PIIX4 Ultra-66, + * This is a look-alike variation of the ICH0 PIIX4 Ultra-66, * but this keeps the ISA-Bridge and slots alive. * */ @@ -158,10 +159,8 @@ static int slc90e66_config_drive_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, slc90e66_ratemask(drive)); - if (!(speed)) { - u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); - speed = slc90e66_dma_2_pio(XFER_PIO_0 + tspeed); - } + if (!speed) + return 0; (void) slc90e66_tune_chipset(drive, speed); return ide_dma_enable(drive); @@ -176,16 +175,15 @@ static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive) if (id && (id->capability & 1) && drive->autodma) { - if (ide_use_dma(drive)) { - if (slc90e66_config_drive_for_dma(drive)) - return hwif->ide_dma_on(drive); - } + if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive)) + return hwif->ide_dma_on(drive); goto fast_ata_pio; } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: - hwif->tuneproc(drive, 5); + (void) hwif->speedproc(drive, XFER_PIO_0 + + ide_get_best_pio_mode(drive, 255, 4, NULL)); return hwif->ide_dma_off_quietly(drive); } /* IORDY not supported */ -- cgit v1.2.3 From cd36beec0b83d28dceb85696a23542bf1b97cc8c Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 5 Jan 2007 16:36:21 -0800 Subject: [PATCH] via82cxxx: fix cable detection This patch fixes 2.6.15 regression, is straightforward and tested. Cable detection got broken probably while converting the driver to support multiple controllers. Cable detection is done by examining how BIOS configured the attached devices. The current code is broken in that it examines the status *after* modifying Clk66 configuration ending up detecting 40c cables as 80c. This patch fixes it. Signed-off-by: Tejun Heo Signed-off-by: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/via82cxxx.c | 138 +++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 73 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index 61f1a9665a7..381cc6f101c 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -123,7 +123,7 @@ struct via82cxxx_dev static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing) { struct pci_dev *dev = hwif->pci_dev; - struct via82cxxx_dev *vdev = ide_get_hwifdata(hwif); + struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev); u8 t; if (~vdev->via_config->flags & VIA_BAD_AST) { @@ -162,7 +162,7 @@ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing) static int via_set_drive(ide_drive_t *drive, u8 speed) { ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1); - struct via82cxxx_dev *vdev = ide_get_hwifdata(drive->hwif); + struct via82cxxx_dev *vdev = pci_get_drvdata(drive->hwif->pci_dev); struct ide_timing t, p; unsigned int T, UT; @@ -225,7 +225,7 @@ static void via82cxxx_tune_drive(ide_drive_t *drive, u8 pio) static int via82cxxx_ide_dma_check (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - struct via82cxxx_dev *vdev = ide_get_hwifdata(hwif); + struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev); u16 w80 = hwif->udma_four; u16 speed = ide_find_best_mode(drive, @@ -262,6 +262,53 @@ static struct via_isa_bridge *via_config_find(struct pci_dev **isa) return via_config; } +/* + * Check and handle 80-wire cable presence + */ +static void __devinit via_cable_detect(struct via82cxxx_dev *vdev, u32 u) +{ + int i; + + switch (vdev->via_config->flags & VIA_UDMA) { + case VIA_UDMA_66: + for (i = 24; i >= 0; i -= 8) + if (((u >> (i & 16)) & 8) && + ((u >> i) & 0x20) && + (((u >> i) & 7) < 2)) { + /* + * 2x PCI clock and + * UDMA w/ < 3T/cycle + */ + vdev->via_80w |= (1 << (1 - (i >> 4))); + } + break; + + case VIA_UDMA_100: + for (i = 24; i >= 0; i -= 8) + if (((u >> i) & 0x10) || + (((u >> i) & 0x20) && + (((u >> i) & 7) < 4))) { + /* BIOS 80-wire bit or + * UDMA w/ < 60ns/cycle + */ + vdev->via_80w |= (1 << (1 - (i >> 4))); + } + break; + + case VIA_UDMA_133: + for (i = 24; i >= 0; i -= 8) + if (((u >> i) & 0x10) || + (((u >> i) & 0x20) && + (((u >> i) & 7) < 6))) { + /* BIOS 80-wire bit or + * UDMA w/ < 60ns/cycle + */ + vdev->via_80w |= (1 << (1 - (i >> 4))); + } + break; + } +} + /** * init_chipset_via82cxxx - initialization handler * @dev: PCI device @@ -274,14 +321,22 @@ static struct via_isa_bridge *via_config_find(struct pci_dev **isa) static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const char *name) { struct pci_dev *isa = NULL; + struct via82cxxx_dev *vdev; struct via_isa_bridge *via_config; u8 t, v; - unsigned int u; + u32 u; + + vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); + if (!vdev) { + printk(KERN_ERR "VP_IDE: out of memory :(\n"); + return -ENOMEM; + } + pci_set_drvdata(dev, vdev); /* * Find the ISA bridge to see how good the IDE is. */ - via_config = via_config_find(&isa); + vdev->via_config = via_config = via_config_find(&isa); /* We checked this earlier so if it fails here deeep badness is involved */ @@ -289,16 +344,17 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const BUG_ON(!via_config->id); /* - * Setup or disable Clk66 if appropriate + * Detect cable and configure Clk66 */ + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); + + via_cable_detect(vdev, u); if ((via_config->flags & VIA_UDMA) == VIA_UDMA_66) { /* Enable Clk66 */ - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); pci_write_config_dword(dev, VIA_UDMA_TIMING, u|0x80008); } else if (via_config->flags & VIA_BAD_CLK66) { /* Would cause trouble on 596a and 686 */ - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008); } @@ -367,75 +423,11 @@ static unsigned int __devinit init_chipset_via82cxxx(struct pci_dev *dev, const return 0; } -/* - * Check and handle 80-wire cable presence - */ -static void __devinit via_cable_detect(struct pci_dev *dev, struct via82cxxx_dev *vdev) -{ - unsigned int u; - int i; - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); - - switch (vdev->via_config->flags & VIA_UDMA) { - - case VIA_UDMA_66: - for (i = 24; i >= 0; i -= 8) - if (((u >> (i & 16)) & 8) && - ((u >> i) & 0x20) && - (((u >> i) & 7) < 2)) { - /* - * 2x PCI clock and - * UDMA w/ < 3T/cycle - */ - vdev->via_80w |= (1 << (1 - (i >> 4))); - } - break; - - case VIA_UDMA_100: - for (i = 24; i >= 0; i -= 8) - if (((u >> i) & 0x10) || - (((u >> i) & 0x20) && - (((u >> i) & 7) < 4))) { - /* BIOS 80-wire bit or - * UDMA w/ < 60ns/cycle - */ - vdev->via_80w |= (1 << (1 - (i >> 4))); - } - break; - - case VIA_UDMA_133: - for (i = 24; i >= 0; i -= 8) - if (((u >> i) & 0x10) || - (((u >> i) & 0x20) && - (((u >> i) & 7) < 6))) { - /* BIOS 80-wire bit or - * UDMA w/ < 60ns/cycle - */ - vdev->via_80w |= (1 << (1 - (i >> 4))); - } - break; - - } -} - static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif) { - struct via82cxxx_dev *vdev = kmalloc(sizeof(struct via82cxxx_dev), - GFP_KERNEL); - struct pci_dev *isa = NULL; + struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev); int i; - if (vdev == NULL) { - printk(KERN_ERR "VP_IDE: out of memory :(\n"); - return; - } - - memset(vdev, 0, sizeof(struct via82cxxx_dev)); - ide_set_hwifdata(hwif, vdev); - - vdev->via_config = via_config_find(&isa); - via_cable_detect(hwif->pci_dev, vdev); - hwif->autodma = 0; hwif->tuneproc = &via82cxxx_tune_drive; -- cgit v1.2.3 From 6c5f8cc33eb2e10b6ab788bbe259fc142a068627 Mon Sep 17 00:00:00 2001 From: Alan Date: Fri, 5 Jan 2007 16:36:27 -0800 Subject: [PATCH] atiixp: Old drivers/ide layer driver for the ATIIXP hang fix When the old IDE layer calls into methods in the driver during error handling it is essentially random whether ide_lock is already held. This causes a deadlock in the atiixp driver which also uses ide_lock internally for locking. Switch to a private lock instead. [akpm@osl.org: cleanup] Signed-off-by: Alan Cox Acked-by: Bartlomiej Zolnierkiewicz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/atiixp.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index ffdffb6379e..524e65de439 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -46,6 +46,8 @@ static atiixp_ide_timing mdma_timing[] = { static int save_mdma_mode[4]; +static DEFINE_SPINLOCK(atiixp_lock); + /** * atiixp_ratemask - compute rate mask for ATIIXP IDE * @drive: IDE drive to compute for @@ -105,7 +107,7 @@ static int atiixp_ide_dma_host_on(ide_drive_t *drive) unsigned long flags; u16 tmp16; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&atiixp_lock, flags); pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16); if (save_mdma_mode[drive->dn]) @@ -114,7 +116,7 @@ static int atiixp_ide_dma_host_on(ide_drive_t *drive) tmp16 |= (1 << drive->dn); pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&atiixp_lock, flags); return __ide_dma_host_on(drive); } @@ -125,13 +127,13 @@ static int atiixp_ide_dma_host_off(ide_drive_t *drive) unsigned long flags; u16 tmp16; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&atiixp_lock, flags); pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16); tmp16 &= ~(1 << drive->dn); pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&atiixp_lock, flags); return __ide_dma_host_off(drive); } @@ -152,7 +154,7 @@ static void atiixp_tuneproc(ide_drive_t *drive, u8 pio) u32 pio_timing_data; u16 pio_mode_data; - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&atiixp_lock, flags); pci_read_config_word(dev, ATIIXP_IDE_PIO_MODE, &pio_mode_data); pio_mode_data &= ~(0x07 << (drive->dn * 4)); @@ -165,7 +167,7 @@ static void atiixp_tuneproc(ide_drive_t *drive, u8 pio) (pio_timing[pio].command_width << (timing_shift + 4)); pci_write_config_dword(dev, ATIIXP_IDE_PIO_TIMING, pio_timing_data); - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&atiixp_lock, flags); } /** @@ -189,7 +191,7 @@ static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed) speed = ide_rate_filter(atiixp_ratemask(drive), xferspeed); - spin_lock_irqsave(&ide_lock, flags); + spin_lock_irqsave(&atiixp_lock, flags); save_mdma_mode[drive->dn] = 0; if (speed >= XFER_UDMA_0) { @@ -208,7 +210,7 @@ static int atiixp_speedproc(ide_drive_t *drive, u8 xferspeed) } } - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irqrestore(&atiixp_lock, flags); if (speed >= XFER_SW_DMA_0) pio = atiixp_dma_2_pio(speed); -- cgit v1.2.3 From a51545ab2523b9cfd426737495f877821006371a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 27 Jan 2007 13:46:21 +0100 Subject: jmicron: fix warning Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/jmicron.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index c1cec236ecf..35dda8fcd0a 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -93,8 +93,9 @@ static int __devinit ata66_jmicron(ide_hwif_t *hwif) return 0; return 1; case PORT_SATA: - return 1; + break; } + return 1; /* Avoid bogus "control reaches end of non-void function" */ } static void jmicron_tuneproc (ide_drive_t *drive, byte mode_wanted) -- cgit v1.2.3 From 737153298023342073ccaa006144dd254b298e2b Mon Sep 17 00:00:00 2001 From: Conke Hu Date: Sat, 27 Jan 2007 13:46:28 +0100 Subject: atiixp.c: remove unused code A previous patch to atiixp.c was removed but some code has not been cleaned. Now we remove these code sine they are no use any longer. Signed-off-by: Conke Hu Cc: Alan Cox Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/atiixp.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index 524e65de439..148af8ab518 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -320,19 +320,6 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif) hwif->drives[0].autodma = hwif->autodma; } -static void __devinit init_hwif_sb600_legacy(ide_hwif_t *hwif) -{ - - hwif->atapi_dma = 1; - hwif->ultra_mask = 0x7f; - hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x07; - - if (!noautodma) - hwif->autodma = 1; - hwif->drives[0].autodma = hwif->autodma; - hwif->drives[1].autodma = hwif->autodma; -} static ide_pci_device_t atiixp_pci_info[] __devinitdata = { { /* 0 */ @@ -342,13 +329,7 @@ static ide_pci_device_t atiixp_pci_info[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}}, .bootable = ON_BOARD, - },{ /* 1 */ - .name = "ATI SB600 SATA Legacy IDE", - .init_hwif = init_hwif_sb600_legacy, - .channels = 2, - .autodma = AUTODMA, - .bootable = ON_BOARD, - } + }, }; /** -- cgit v1.2.3 From b25168dfdc162b4198fa6395cd191a20dddc6d34 Mon Sep 17 00:00:00 2001 From: Conke Hu Date: Sat, 27 Jan 2007 13:46:30 +0100 Subject: atiixp.c: sb600 ide only has one channel AMD/ATI SB600 IDE/PATA controller only has one channel. Signed-off-by: Conke Hu Cc: Alan Cox Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/atiixp.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index 148af8ab518..5b7e000ac2f 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -329,7 +329,14 @@ static ide_pci_device_t atiixp_pci_info[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}}, .bootable = ON_BOARD, - }, + },{ /* 1 */ + .name = "SB600_PATA", + .init_hwif = init_hwif_atiixp, + .channels = 1, + .autodma = AUTODMA, + .enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}}, + .bootable = ON_BOARD, + }, }; /** @@ -350,7 +357,7 @@ static struct pci_device_id atiixp_pci_tbl[] = { { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { 0, }, }; MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl); -- cgit v1.2.3 From e5c073ff24604d4dbb2fbcedb17da6df768468d3 Mon Sep 17 00:00:00 2001 From: Conke Hu Date: Sat, 27 Jan 2007 13:46:40 +0100 Subject: atiixp.c: add cable detection support for ATI IDE IDE HDD does not work if it uses a 40-pin PATA cable on ATI chipset. This patch fixes the bug. Signed-off-by: Conke Hu Cc: Alan Cox Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/atiixp.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index 5b7e000ac2f..7e1d07031d3 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -291,8 +291,12 @@ fast_ata_pio: static void __devinit init_hwif_atiixp(ide_hwif_t *hwif) { + u8 udma_mode = 0; + u8 ch = hwif->channel; + struct pci_dev *pdev = hwif->pci_dev; + if (!hwif->irq) - hwif->irq = hwif->channel ? 15 : 14; + hwif->irq = ch ? 15 : 14; hwif->autodma = 0; hwif->tuneproc = &atiixp_tuneproc; @@ -308,8 +312,12 @@ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif) hwif->mwdma_mask = 0x06; hwif->swdma_mask = 0x04; - /* FIXME: proper cable detection needed */ - hwif->udma_four = 1; + pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode); + if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40) + hwif->udma_four = 1; + else + hwif->udma_four = 0; + hwif->ide_dma_host_on = &atiixp_ide_dma_host_on; hwif->ide_dma_host_off = &atiixp_ide_dma_host_off; hwif->ide_dma_check = &atiixp_dma_check; -- cgit v1.2.3 From 3e9e4c8606127592cda22159cc2440ea48963ae4 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 27 Jan 2007 13:46:45 +0100 Subject: ide/generic: Jmicron has its own drivers now Drop ide-generic support for Jmicron identifiers as we now trust Jmicron.c for this with drivers/ide. The code check remains for the all-generic-ide case. Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/generic.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index 9f306880491..3143cb03fe3 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -185,36 +185,6 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - },{ /* 15 */ - .name = "JMB361", - .init_hwif = init_hwif_generic, - .channels = 2, - .autodma = AUTODMA, - .bootable = OFF_BOARD, - },{ /* 16 */ - .name = "JMB363", - .init_hwif = init_hwif_generic, - .channels = 2, - .autodma = AUTODMA, - .bootable = OFF_BOARD, - },{ /* 17 */ - .name = "JMB365", - .init_hwif = init_hwif_generic, - .channels = 2, - .autodma = AUTODMA, - .bootable = OFF_BOARD, - },{ /* 18 */ - .name = "JMB366", - .init_hwif = init_hwif_generic, - .channels = 2, - .autodma = AUTODMA, - .bootable = OFF_BOARD, - },{ /* 19 */ - .name = "JMB368", - .init_hwif = init_hwif_generic, - .channels = 2, - .autodma = AUTODMA, - .bootable = OFF_BOARD, } }; @@ -281,11 +251,6 @@ static struct pci_device_id generic_pci_tbl[] = { { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13}, { PCI_VENDOR_ID_NETCELL,PCI_DEVICE_ID_REVOLUTION, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14}, - { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15}, - { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16}, - { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17}, - { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18}, - { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19}, /* Must come last. If you add entries adjust this table appropriately and the init_one code */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0}, { 0, }, -- cgit v1.2.3 From 82ab1eeceba6705cd5a8815c48eb03af1dada744 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sat, 27 Jan 2007 13:46:56 +0100 Subject: ide: add missing __init tags to IDE PCI host drivers also change __devinit tag for sgiioc4.c:ioc4_ide_init() to __init Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/aec62xx.c | 2 +- drivers/ide/pci/alim15x3.c | 2 +- drivers/ide/pci/amd74xx.c | 2 +- drivers/ide/pci/atiixp.c | 2 +- drivers/ide/pci/cmd64x.c | 2 +- drivers/ide/pci/cs5520.c | 2 +- drivers/ide/pci/cs5530.c | 2 +- drivers/ide/pci/cy82c693.c | 2 +- drivers/ide/pci/generic.c | 2 +- drivers/ide/pci/hpt34x.c | 2 +- drivers/ide/pci/hpt366.c | 2 +- drivers/ide/pci/ns87415.c | 2 +- drivers/ide/pci/opti621.c | 2 +- drivers/ide/pci/pdc202xx_new.c | 2 +- drivers/ide/pci/pdc202xx_old.c | 2 +- drivers/ide/pci/rz1000.c | 2 +- drivers/ide/pci/sc1200.c | 2 +- drivers/ide/pci/serverworks.c | 2 +- drivers/ide/pci/sgiioc4.c | 3 +-- drivers/ide/pci/siimage.c | 2 +- drivers/ide/pci/sis5513.c | 2 +- drivers/ide/pci/sl82c105.c | 2 +- drivers/ide/pci/slc90e66.c | 2 +- drivers/ide/pci/triflex.c | 2 +- drivers/ide/pci/trm290.c | 2 +- drivers/ide/pci/via82cxxx.c | 2 +- 26 files changed, 26 insertions(+), 27 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index f286079d233..d261bfbad22 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -441,7 +441,7 @@ static struct pci_driver driver = { .probe = aec62xx_init_one, }; -static int aec62xx_ide_init(void) +static int __init aec62xx_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 89109be5162..68df77ec502 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -907,7 +907,7 @@ static struct pci_driver driver = { .probe = alim15x3_init_one, }; -static int ali15x3_ide_init(void) +static int __init ali15x3_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 753fe0e2145..a4336995a41 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -544,7 +544,7 @@ static struct pci_driver driver = { .probe = amd74xx_probe, }; -static int amd74xx_ide_init(void) +static int __init amd74xx_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c index 7e1d07031d3..982ac31fa99 100644 --- a/drivers/ide/pci/atiixp.c +++ b/drivers/ide/pci/atiixp.c @@ -376,7 +376,7 @@ static struct pci_driver driver = { .probe = atiixp_init_one, }; -static int atiixp_ide_init(void) +static int __init atiixp_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index 20c32716bbc..aee947e8fc3 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c @@ -793,7 +793,7 @@ static struct pci_driver driver = { .probe = cmd64x_init_one, }; -static int cmd64x_ide_init(void) +static int __init cmd64x_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c index 079f7c86726..ba6786aabf3 100644 --- a/drivers/ide/pci/cs5520.c +++ b/drivers/ide/pci/cs5520.c @@ -260,7 +260,7 @@ static struct pci_driver driver = { .probe = cs5520_init_one, }; -static int cs5520_ide_init(void) +static int __init cs5520_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c index ae405fa3223..9bf5fdfc5b1 100644 --- a/drivers/ide/pci/cs5530.c +++ b/drivers/ide/pci/cs5530.c @@ -374,7 +374,7 @@ static struct pci_driver driver = { .probe = cs5530_init_one, }; -static int cs5530_ide_init(void) +static int __init cs5530_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c index 64330c459bd..9eafcbf444f 100644 --- a/drivers/ide/pci/cy82c693.c +++ b/drivers/ide/pci/cy82c693.c @@ -519,7 +519,7 @@ static struct pci_driver driver = { .probe = cy82c693_init_one, }; -static int cy82c693_ide_init(void) +static int __init cy82c693_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index 3143cb03fe3..b408c6c517e 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -263,7 +263,7 @@ static struct pci_driver driver = { .probe = generic_init_one, }; -static int generic_ide_init(void) +static int __init generic_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c index b46cb042290..ce7b08f08a0 100644 --- a/drivers/ide/pci/hpt34x.c +++ b/drivers/ide/pci/hpt34x.c @@ -265,7 +265,7 @@ static struct pci_driver driver = { .probe = hpt34x_init_one, }; -static int hpt34x_ide_init(void) +static int __init hpt34x_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 08119da06d5..b486442dd5d 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1613,7 +1613,7 @@ static struct pci_driver driver = { .probe = hpt366_init_one, }; -static int hpt366_ide_init(void) +static int __init hpt366_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index d95714bcee4..8aaea4ea554 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c @@ -302,7 +302,7 @@ static struct pci_driver driver = { .probe = ns87415_init_one, }; -static int ns87415_ide_init(void) +static int __init ns87415_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index 7a7c2ef78ac..22bbf613f94 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -382,7 +382,7 @@ static struct pci_driver driver = { .probe = opti621_init_one, }; -static int opti621_ide_init(void) +static int __init opti621_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 7cb48576e47..77a9aaa7dab 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -756,7 +756,7 @@ static struct pci_driver driver = { .probe = pdc202new_init_one, }; -static int pdc202new_ide_init(void) +static int __init pdc202new_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 184cdacddeb..143239c093d 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -719,7 +719,7 @@ static struct pci_driver driver = { .probe = pdc202xx_init_one, }; -static int pdc202xx_ide_init(void) +static int __init pdc202xx_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c index 5f6950c2d1d..c1855311052 100644 --- a/drivers/ide/pci/rz1000.c +++ b/drivers/ide/pci/rz1000.c @@ -77,7 +77,7 @@ static struct pci_driver driver = { .probe = rz1000_init_one, }; -static int rz1000_ide_init(void) +static int __init rz1000_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c index ff80937d94d..8d762d323f8 100644 --- a/drivers/ide/pci/sc1200.c +++ b/drivers/ide/pci/sc1200.c @@ -507,7 +507,7 @@ static struct pci_driver driver = { #endif }; -static int sc1200_ide_init(void) +static int __init sc1200_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index 057548d0720..ea9a28a4585 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c @@ -666,7 +666,7 @@ static struct pci_driver driver = { .probe = svwks_init_one, }; -static int svwks_ide_init(void) +static int __init svwks_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index cfad09accf5..b0bf0180927 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -762,8 +762,7 @@ static struct ioc4_submodule ioc4_ide_submodule = { /* .is_remove = ioc4_ide_remove_one, */ }; -static int __devinit -ioc4_ide_init(void) +static int __init ioc4_ide_init(void) { return ioc4_register_submodule(&ioc4_ide_submodule); } diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 697f566fb90..4ff89c7d990 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -1096,7 +1096,7 @@ static struct pci_driver driver = { .probe = siimage_init_one, }; -static int siimage_ide_init(void) +static int __init siimage_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index 6b313139b5e..1afff659ab5 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -968,7 +968,7 @@ static struct pci_driver driver = { .probe = sis5513_init_one, }; -static int sis5513_ide_init(void) +static int __init sis5513_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c index 5afefe8692f..170a2619905 100644 --- a/drivers/ide/pci/sl82c105.c +++ b/drivers/ide/pci/sl82c105.c @@ -492,7 +492,7 @@ static struct pci_driver driver = { .probe = sl82c105_init_one, }; -static int sl82c105_ide_init(void) +static int __init sl82c105_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index 9be7e49cba0..90e79c0844d 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -253,7 +253,7 @@ static struct pci_driver driver = { .probe = slc90e66_init_one, }; -static int slc90e66_ide_init(void) +static int __init slc90e66_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c index 56d84931d6d..b13cce1fd1a 100644 --- a/drivers/ide/pci/triflex.c +++ b/drivers/ide/pci/triflex.c @@ -173,7 +173,7 @@ static struct pci_driver driver = { .probe = triflex_init_one, }; -static int triflex_ide_init(void) +static int __init triflex_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c index 2a282529bfc..174b88c4780 100644 --- a/drivers/ide/pci/trm290.c +++ b/drivers/ide/pci/trm290.c @@ -355,7 +355,7 @@ static struct pci_driver driver = { .probe = trm290_init_one, }; -static int trm290_ide_init(void) +static int __init trm290_ide_init(void) { return ide_pci_register_driver(&driver); } diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index 381cc6f101c..6414a545be0 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -514,7 +514,7 @@ static struct pci_driver driver = { .probe = via_init_one, }; -static int via_ide_init(void) +static int __init via_ide_init(void) { return ide_pci_register_driver(&driver); } -- cgit v1.2.3 From 6855036aa035913bc2bfb31c41576a49f42ecd5f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 27 Jan 2007 13:47:02 +0100 Subject: ide: unregister idepnp driver on unload idepnp driver is registered as a pnp driver on ide init but doesn't get unregistered on ide unload causing driver list corruption and eventually oops. Fix it. Signed-off-by: Tejun Heo Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-pnp.c | 5 +++++ drivers/ide/ide.c | 5 +++++ 2 files changed, 10 insertions(+) (limited to 'drivers/ide') diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c index df7d1504f84..98410ca044c 100644 --- a/drivers/ide/ide-pnp.c +++ b/drivers/ide/ide-pnp.c @@ -73,3 +73,8 @@ void __init pnpide_init(void) { pnp_register_driver(&idepnp_driver); } + +void __exit pnpide_exit(void) +{ + pnp_unregister_driver(&idepnp_driver); +} diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 16890769dca..3b334af0c7b 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1782,6 +1782,7 @@ done: } extern void pnpide_init(void); +extern void pnpide_exit(void); extern void h8300_ide_init(void); /* @@ -2094,6 +2095,10 @@ void cleanup_module (void) for (index = 0; index < MAX_HWIFS; ++index) ide_unregister(index); +#ifdef CONFIG_BLK_DEV_IDEPNP + pnpide_exit(); +#endif + #ifdef CONFIG_PROC_FS proc_ide_destroy(); #endif -- cgit v1.2.3 From e0b874df14052489e6408125903dba96b4dd7baa Mon Sep 17 00:00:00 2001 From: Josepch Chan Date: Sat, 27 Jan 2007 13:47:08 +0100 Subject: via82cxxx/pata_via: correct PCI_DEVICE_ID_VIA_SATA_EIDE ID and add support for CX700 and 8237S This patch: * Corrects the wrong device ID of PCI_DEVICE_ID_VIA_SATA_EIDE from 0x0581 to 0x5324. * Adds VIA CX700 and VT8237S support in drivers/ide/pci/via82cxxx.c * Adds VIA VT8237S support in drivers/ata/pata_via.c Signed-off-by: Josepch Chan Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/via82cxxx.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index 6414a545be0..a98b4d38b9d 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -78,6 +78,8 @@ static struct via_isa_bridge { u8 rev_max; u16 flags; } via_isa_bridges[] = { + { "cx7000", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, + { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, @@ -504,6 +506,7 @@ static struct pci_device_id via_pci_tbl[] = { { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_6410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_SATA_EIDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, { 0, }, }; MODULE_DEVICE_TABLE(pci, via_pci_tbl); -- cgit v1.2.3 From 99abaf51e25f7d4ac2081e5cdc1f01baa0543514 Mon Sep 17 00:00:00 2001 From: "ethanhsiao@jmicron.com" Date: Tue, 30 Jan 2007 14:36:13 -0800 Subject: [PATCH] jmicron: 40/80pin primary detection jmicron module detects all JMB36x as JMB361 and PATA0 has wrong pin status of XICBLID. Cc: Jeff Garzik Cc: Alan Cox Cc: Bartlomiej Zolnierkiewicz Cc: Sergei Shtylyov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/jmicron.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c index 35dda8fcd0a..f07bbbed177 100644 --- a/drivers/ide/pci/jmicron.c +++ b/drivers/ide/pci/jmicron.c @@ -86,8 +86,8 @@ static int __devinit ata66_jmicron(ide_hwif_t *hwif) { case PORT_PATA0: if (control & (1 << 3)) /* 40/80 pin primary */ - return 1; - return 0; + return 0; + return 1; case PORT_PATA1: if (control5 & (1 << 19)) /* 40/80 pin secondary */ return 0; @@ -241,11 +241,11 @@ static int __devinit jmicron_init_one(struct pci_dev *dev, const struct pci_devi } static struct pci_device_id jmicron_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361), 0}, - { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363), 1}, - { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365), 2}, - { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366), 3}, - { PCI_DEVICE(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368), 4}, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, + { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, { 0, }, }; -- cgit v1.2.3 From eb7972271720bfc64dc8bacc5b15f874c0bcc859 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 1 Feb 2007 13:52:38 +0000 Subject: [PATCH] ide section fixes a) cleanup_module() should be __exit b) externs should match reality Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/ide/ide.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 3b334af0c7b..6c9bd5165bd 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1781,9 +1781,9 @@ done: return 1; } -extern void pnpide_init(void); -extern void pnpide_exit(void); -extern void h8300_ide_init(void); +extern void __init pnpide_init(void); +extern void __exit pnpide_exit(void); +extern void __init h8300_ide_init(void); /* * probe_for_hwifs() finds/initializes "known" IDE interfaces @@ -2088,7 +2088,7 @@ int __init init_module (void) return ide_init(); } -void cleanup_module (void) +void __exit cleanup_module (void) { int index; -- cgit v1.2.3 From fb594d31aa2d133ea89d4ead964c51262b331407 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 1 Feb 2007 14:12:27 +0100 Subject: [PATCH] via82cxxx: fix typo ("cx7000" should be corrected to "cx700") Noticed by JosephChan@via.com.tw. Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Linus Torvalds --- drivers/ide/pci/via82cxxx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index a98b4d38b9d..6fb6e50b823 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -78,7 +78,7 @@ static struct via_isa_bridge { u8 rev_max; u16 flags; } via_isa_bridges[] = { - { "cx7000", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, + { "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, -- cgit v1.2.3 From e139b0b02fd35a68c4353db34d3380c8a7c9a90d Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:17:37 +0100 Subject: hpt366: rework rate filtering - Rework hpt3xx_ratemask() and hpt3xx_ratefilter() so that the former returns the max. mode computed at the load time and doesn't have to do bad Ultra33 drive list lookups anymore; remove the duplicate code from the latter function. Move the quirky drive list lookup into hpt3xx_quirkproc() where it should have been from the start... - Disable UltraATA/100 for HPT370 by default as the 33 MHz ATA clock being used does not allow for it, and this *greatly* increases the transfer speed. - Save some space by using byte-wide fields in struct hpt_info; switch to reading the 8-bit PCI revision ID reg. only, not the whole 32-bit reg. - Start incrementing the driver version number with each patch (should have been done from the first one posted). Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 179 ++++++++++++++++++++++------------------------- 1 file changed, 85 insertions(+), 94 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index b486442dd5d..49ae9f6d218 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 0.36 April 25, 2003 + * linux/drivers/ide/pci/hpt366.c Version 0.43 May 17, 2006 * * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -62,8 +62,8 @@ * be done on 66 MHz PCI bus * - avoid calibrating PLL twice as the second time results in a wrong PCI * frequency and thus in the wrong timings for the secondary channel - * - disable UltraATA/133 for HPT372 by default (50 MHz DPLL clock do not - * allow for this speed anyway) + * - disable UltraATA/133 for HPT372 and UltraATA/100 for HPT370 by default + * as the ATA clock being used does not allow for this speed anyway * - add support for HPT302N and HPT371N clocking (the same as for HPT372N) * - HPT371/N are single channel chips, so avoid touching the primary channel * which exists only virtually (there's no pins for it) @@ -76,6 +76,7 @@ * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead * - pass to init_chipset() handlers a copy of the IDE PCI device structure as * they tamper with its fields + * - optimize the rate masking/filtering and the drive list lookup code * * */ @@ -336,7 +337,7 @@ static u32 sixty_six_base_hpt37x[] = { #define HPT371_ALLOW_ATA133_6 0 #define HPT302_ALLOW_ATA133_6 0 #define HPT372_ALLOW_ATA133_6 0 -#define HPT370_ALLOW_ATA100_5 1 +#define HPT370_ALLOW_ATA100_5 0 #define HPT366_ALLOW_ATA66_4 1 #define HPT366_ALLOW_ATA66_3 1 #define HPT366_MAX_DEVS 8 @@ -354,8 +355,8 @@ static u32 sixty_six_base_hpt37x[] = { struct hpt_info { u8 max_mode; /* Speeds allowed */ - int revision; /* Chipset revision */ - int flags; /* Chipset properties */ + u8 revision; /* Chipset revision */ + u8 flags; /* Chipset properties */ #define PLL_MODE 1 #define IS_3xxN 2 #define PCI_66MHZ 4 @@ -364,61 +365,50 @@ struct hpt_info }; /* - * This wants fixing so that we do everything not by classrev + * This wants fixing so that we do everything not by revision * (which breaks on the newest chips) but by creating an * enumeration of chip variants and using that */ -static __devinit u32 hpt_revision (struct pci_dev *dev) +static __devinit u8 hpt_revision(struct pci_dev *dev) { - u32 class_rev; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; + u8 rev = 0; + + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); switch(dev->device) { /* Remap new 372N onto 372 */ case PCI_DEVICE_ID_TTI_HPT372N: - class_rev = PCI_DEVICE_ID_TTI_HPT372; break; + rev = PCI_DEVICE_ID_TTI_HPT372; break; case PCI_DEVICE_ID_TTI_HPT374: - class_rev = PCI_DEVICE_ID_TTI_HPT374; break; + rev = PCI_DEVICE_ID_TTI_HPT374; break; case PCI_DEVICE_ID_TTI_HPT371: - class_rev = PCI_DEVICE_ID_TTI_HPT371; break; + rev = PCI_DEVICE_ID_TTI_HPT371; break; case PCI_DEVICE_ID_TTI_HPT302: - class_rev = PCI_DEVICE_ID_TTI_HPT302; break; + rev = PCI_DEVICE_ID_TTI_HPT302; break; case PCI_DEVICE_ID_TTI_HPT372: - class_rev = PCI_DEVICE_ID_TTI_HPT372; break; + rev = PCI_DEVICE_ID_TTI_HPT372; break; default: break; } - return class_rev; + return rev; } -static int check_in_drive_lists(ide_drive_t *drive, const char **list); +static int check_in_drive_list(ide_drive_t *drive, const char **list) +{ + struct hd_driveid *id = drive->id; + + while (*list) + if (!strcmp(*list++,id->model)) + return 1; + return 0; +} -static u8 hpt3xx_ratemask (ide_drive_t *drive) +static u8 hpt3xx_ratemask(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); - u8 mode = 0; - - /* FIXME: TODO - move this to set info->mode once at boot */ - - if (info->revision >= 8) { /* HPT374 */ - mode = (HPT374_ALLOW_ATA133_6) ? 4 : 3; - } else if (info->revision >= 7) { /* HPT371 */ - mode = (HPT371_ALLOW_ATA133_6) ? 4 : 3; - } else if (info->revision >= 6) { /* HPT302 */ - mode = (HPT302_ALLOW_ATA133_6) ? 4 : 3; - } else if (info->revision >= 5) { /* HPT372 */ - mode = (HPT372_ALLOW_ATA133_6) ? 4 : 3; - } else if (info->revision >= 4) { /* HPT370A */ - mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; - } else if (info->revision >= 3) { /* HPT370 */ - mode = (HPT370_ALLOW_ATA100_5) ? 3 : 2; - mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : mode; - } else { /* HPT366 and HPT368 */ - mode = (check_in_drive_lists(drive, bad_ata33)) ? 0 : 2; - } + struct hpt_info *info = ide_get_hwifdata(HWIF(drive)); + u8 mode = info->max_mode; + if (!eighty_ninty_three(drive) && mode) mode = min(mode, (u8)1); return mode; @@ -429,16 +419,15 @@ static u8 hpt3xx_ratemask (ide_drive_t *drive) * either PIO or UDMA modes 0,4,5 */ -static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) +static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) { - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); + struct hpt_info *info = ide_get_hwifdata(HWIF(drive)); u8 mode = hpt3xx_ratemask(drive); if (drive->media != ide_disk) return min(speed, (u8)XFER_PIO_4); - switch(mode) { + switch (mode) { case 0x04: speed = min(speed, (u8)XFER_UDMA_6); break; @@ -446,33 +435,34 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) speed = min(speed, (u8)XFER_UDMA_5); if (info->revision >= 5) break; - if (check_in_drive_lists(drive, bad_ata100_5)) - speed = min(speed, (u8)XFER_UDMA_4); - break; + if (!check_in_drive_list(drive, bad_ata100_5)) + goto check_bad_ata33; + /* fall thru */ case 0x02: speed = min(speed, (u8)XFER_UDMA_4); /* * CHECK ME, Does this need to be set to 5 ?? */ if (info->revision >= 3) - break; - if ((check_in_drive_lists(drive, bad_ata66_4)) || - (!(HPT366_ALLOW_ATA66_4))) - speed = min(speed, (u8)XFER_UDMA_3); - if ((check_in_drive_lists(drive, bad_ata66_3)) || - (!(HPT366_ALLOW_ATA66_3))) - speed = min(speed, (u8)XFER_UDMA_2); - break; + goto check_bad_ata33; + if (HPT366_ALLOW_ATA66_4 && + !check_in_drive_list(drive, bad_ata66_4)) + goto check_bad_ata33; + + speed = min(speed, (u8)XFER_UDMA_3); + if (HPT366_ALLOW_ATA66_3 && + !check_in_drive_list(drive, bad_ata66_3)) + goto check_bad_ata33; + /* fall thru */ case 0x01: speed = min(speed, (u8)XFER_UDMA_2); - /* - * CHECK ME, Does this need to be set to 5 ?? - */ - if (info->revision >= 3) + + check_bad_ata33: + if (info->revision >= 4) break; - if (check_in_drive_lists(drive, bad_ata33)) - speed = min(speed, (u8)XFER_MW_DMA_2); - break; + if (!check_in_drive_list(drive, bad_ata33)) + break; + /* fall thru */ case 0x00: default: speed = min(speed, (u8)XFER_MW_DMA_2); @@ -481,22 +471,6 @@ static u8 hpt3xx_ratefilter (ide_drive_t *drive, u8 speed) return speed; } -static int check_in_drive_lists (ide_drive_t *drive, const char **list) -{ - struct hd_driveid *id = drive->id; - - if (quirk_drives == list) { - while (*list) - if (strstr(id->model, *list++)) - return 1; - } else { - while (*list) - if (!strcmp(*list++,id->model)) - return 1; - } - return 0; -} - static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table) { int i; @@ -671,9 +645,15 @@ static int config_chipset_for_dma (ide_drive_t *drive) return ide_dma_enable(drive); } -static int hpt3xx_quirkproc (ide_drive_t *drive) +static int hpt3xx_quirkproc(ide_drive_t *drive) { - return ((int) check_in_drive_lists(drive, quirk_drives)); + struct hd_driveid *id = drive->id; + const char **list = quirk_drives; + + while (*list) + if (strstr(id->model, *list++)) + return 1; + return 0; } static void hpt3xx_intrproc (ide_drive_t *drive) @@ -1381,7 +1361,7 @@ static void __devinit init_iops_hpt366(ide_hwif_t *hwif) struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL); struct pci_dev *dev = hwif->pci_dev; u16 did = dev->device; - u8 rid = 0; + u8 mode, rid = 0; if(info == NULL) { printk(KERN_WARNING "hpt366: out of memory.\n"); @@ -1395,7 +1375,7 @@ static void __devinit init_iops_hpt366(ide_hwif_t *hwif) return; } - pci_read_config_byte(dev, PCI_CLASS_REVISION, &rid); + pci_read_config_byte(dev, PCI_REVISION_ID, &rid); if (( did == PCI_DEVICE_ID_TTI_HPT366 && rid == 6) || ((did == PCI_DEVICE_ID_TTI_HPT372 || @@ -1404,9 +1384,22 @@ static void __devinit init_iops_hpt366(ide_hwif_t *hwif) did == PCI_DEVICE_ID_TTI_HPT372N) info->flags |= IS_3xxN; - info->revision = hpt_revision(dev); - - if (info->revision >= 3) + rid = info->revision = hpt_revision(dev); + if (rid >= 8) /* HPT374 */ + mode = HPT374_ALLOW_ATA133_6 ? 4 : 3; + else if (rid >= 7) /* HPT371 and HPT371N */ + mode = HPT371_ALLOW_ATA133_6 ? 4 : 3; + else if (rid >= 6) /* HPT302 and HPT302N */ + mode = HPT302_ALLOW_ATA133_6 ? 4 : 3; + else if (rid >= 5) /* HPT372, HPT372A, and HPT372N */ + mode = HPT372_ALLOW_ATA133_6 ? 4 : 3; + else if (rid >= 3) /* HPT370 and HPT370A */ + mode = HPT370_ALLOW_ATA100_5 ? 3 : 2; + else /* HPT366 and HPT368 */ + mode = (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1; + info->max_mode = mode; + + if (rid >= 3) hpt37x_clocking(hwif); else hpt366_clocking(hwif); @@ -1461,8 +1454,7 @@ static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) { struct pci_dev *findev = NULL; - u8 pin1 = 0, pin2 = 0; - unsigned int class_rev; + u8 rev = 0, pin1 = 0, pin2 = 0; char *chipset_names[] = {"HPT366", "HPT366", "HPT368", "HPT370", "HPT370A", "HPT372", "HPT372N" }; @@ -1470,16 +1462,15 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) if (PCI_FUNC(dev->devfn) & 1) return -ENODEV; - pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); - class_rev &= 0xff; + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); if(dev->device == PCI_DEVICE_ID_TTI_HPT372N) - class_rev = 6; + rev = 6; - if(class_rev <= 6) - d->name = chipset_names[class_rev]; + if(rev <= 6) + d->name = chipset_names[rev]; - switch(class_rev) { + switch(rev) { case 6: case 5: case 4: -- cgit v1.2.3 From f36702b4de1f7ea57927c8eb88d624504d33fc34 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 7 Feb 2007 18:17:37 +0100 Subject: hpt366: rework rate filtering tidy Cc: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 49ae9f6d218..28bf2bad154 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -379,15 +379,20 @@ static __devinit u8 hpt_revision(struct pci_dev *dev) switch(dev->device) { /* Remap new 372N onto 372 */ case PCI_DEVICE_ID_TTI_HPT372N: - rev = PCI_DEVICE_ID_TTI_HPT372; break; + rev = PCI_DEVICE_ID_TTI_HPT372; + break; case PCI_DEVICE_ID_TTI_HPT374: - rev = PCI_DEVICE_ID_TTI_HPT374; break; + rev = PCI_DEVICE_ID_TTI_HPT374; + break; case PCI_DEVICE_ID_TTI_HPT371: - rev = PCI_DEVICE_ID_TTI_HPT371; break; + rev = PCI_DEVICE_ID_TTI_HPT371; + break; case PCI_DEVICE_ID_TTI_HPT302: - rev = PCI_DEVICE_ID_TTI_HPT302; break; + rev = PCI_DEVICE_ID_TTI_HPT302; + break; case PCI_DEVICE_ID_TTI_HPT372: - rev = PCI_DEVICE_ID_TTI_HPT372; break; + rev = PCI_DEVICE_ID_TTI_HPT372; + break; default: break; } @@ -439,7 +444,7 @@ static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) goto check_bad_ata33; /* fall thru */ case 0x02: - speed = min(speed, (u8)XFER_UDMA_4); + speed = min_t(u8, speed, XFER_UDMA_4); /* * CHECK ME, Does this need to be set to 5 ?? */ @@ -449,13 +454,13 @@ static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) !check_in_drive_list(drive, bad_ata66_4)) goto check_bad_ata33; - speed = min(speed, (u8)XFER_UDMA_3); + speed = min_t(u8, speed, XFER_UDMA_3); if (HPT366_ALLOW_ATA66_3 && !check_in_drive_list(drive, bad_ata66_3)) goto check_bad_ata33; /* fall thru */ case 0x01: - speed = min(speed, (u8)XFER_UDMA_2); + speed = min_t(u8, speed, XFER_UDMA_2); check_bad_ata33: if (info->revision >= 4) @@ -465,7 +470,7 @@ static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) /* fall thru */ case 0x00: default: - speed = min(speed, (u8)XFER_MW_DMA_2); + speed = min_t(u8, speed, XFER_MW_DMA_2); break; } return speed; -- cgit v1.2.3 From 90778574c9257ea2d11c433626e1b12ac4135e0a Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:17:51 +0100 Subject: hpt366: print the real chip name at startup - Rework the driver setup code so that it prefixes the driver startup messages with the real chip name. - Print the measured f_CNT value and the DPLL setting for non-HPT3xx chips as well. - Claim the extra 240 bytes of I/O space for all chips, not only for those having PCI device ID of 0x0004. Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 104 ++++++++++++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 37 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 28bf2bad154..32a40710e73 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 0.43 May 17, 2006 + * linux/drivers/ide/pci/hpt366.c Version 0.44 May 20, 2006 * * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -76,6 +76,8 @@ * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead * - pass to init_chipset() handlers a copy of the IDE PCI device structure as * they tamper with its fields + * - prefix the driver startup messages with the real chip name + * - claim the extra 240 bytes of I/O space for all chips * - optimize the rate masking/filtering and the drive list lookup code * * @@ -994,8 +996,9 @@ static void __devinit hpt366_clocking(ide_hwif_t *hwif) static void __devinit hpt37x_clocking(ide_hwif_t *hwif) { - struct hpt_info *info = ide_get_hwifdata(hwif); - struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = ide_get_hwifdata(hwif); + struct pci_dev *dev = hwif->pci_dev; + char *name = hwif->cds->name; int adjust, i; u16 freq = 0; u32 pll, temp = 0; @@ -1028,7 +1031,7 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) */ temp = inl(pci_resource_start(dev, 4) + 0x90); if ((temp & 0xFFFFF000) != 0xABCDE000) { - printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n"); + printk(KERN_WARNING "%s: no clock data saved by BIOS\n", name); /* Calculate the average value of f_CNT */ for (temp = i = 0; i < 128; i++) { @@ -1055,10 +1058,7 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) else pll = F_LOW_PCI_66; - printk(KERN_INFO "HPT3xxN detected, FREQ: %d, PLL: %d\n", freq, pll); - } - else - { + } else { if(freq < 0x9C) pll = F_LOW_PCI_33; else if(freq < 0xb0) @@ -1067,18 +1067,21 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pll = F_LOW_PCI_50; else pll = F_LOW_PCI_66; + } + printk(KERN_INFO "%s: FREQ: %d, PLL: %d\n", name, freq, pll); + if (!(info->flags & IS_3xxN)) { if (pll == F_LOW_PCI_33) { info->speed = thirty_three_base_hpt37x; - printk(KERN_DEBUG "HPT37X: using 33MHz PCI clock\n"); + printk(KERN_DEBUG "%s: using 33MHz PCI clock\n", name); } else if (pll == F_LOW_PCI_40) { /* Unsupported */ } else if (pll == F_LOW_PCI_50) { info->speed = fifty_base_hpt37x; - printk(KERN_DEBUG "HPT37X: using 50MHz PCI clock\n"); + printk(KERN_DEBUG "%s: using 50MHz PCI clock\n", name); } else { info->speed = sixty_six_base_hpt37x; - printk(KERN_DEBUG "HPT37X: using 66MHz PCI clock\n"); + printk(KERN_DEBUG "%s: using 66MHz PCI clock\n", name); } } @@ -1127,7 +1130,7 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) pci_write_config_byte(dev, 0x5b, 0x21); info->speed = fifty_base_hpt37x; - printk("HPT37X: using 50MHz internal PLL\n"); + printk("%s: using 50MHz internal PLL\n", name); goto init_hpt37X_done; } } @@ -1140,8 +1143,8 @@ pll_recal: init_hpt37X_done: if (!info->speed) - printk(KERN_ERR "HPT37x%s: unknown bus timing [%d %d].\n", - (info->flags & IS_3xxN) ? "N" : "", pll, freq); + printk(KERN_ERR "%s: unknown bus timing [%d %d].\n", + name, pll, freq); /* * Reset the state engines. * NOTE: avoid accidentally enabling the primary channel on HPT371N. @@ -1334,7 +1337,8 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) return; if(info->speed == NULL) { - printk(KERN_WARNING "hpt366: no known IDE timings, disabling DMA.\n"); + printk(KERN_WARNING "%s: no known IDE timings, disabling DMA.\n", + hwif->cds->name); return; } @@ -1369,7 +1373,7 @@ static void __devinit init_iops_hpt366(ide_hwif_t *hwif) u8 mode, rid = 0; if(info == NULL) { - printk(KERN_WARNING "hpt366: out of memory.\n"); + printk(KERN_WARNING "%s: out of memory.\n", hwif->cds->name); return; } ide_set_hwifdata(hwif, info); @@ -1434,14 +1438,19 @@ static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d) return ide_setup_pci_device(dev, d); } -static int __devinit init_setup_hpt37x(struct pci_dev *dev, ide_pci_device_t *d) +static int __devinit init_setup_hpt372n(struct pci_dev *dev, ide_pci_device_t *d) { return ide_setup_pci_device(dev, d); } static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) { - u8 mcr1 = 0; + u8 rev = 0, mcr1 = 0; + + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); + + if (rev > 1) + d->name = "HPT371N"; /* * HPT371 chips physically have only one channel, the secondary one, @@ -1451,7 +1460,31 @@ static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) */ pci_read_config_byte(dev, 0x50, &mcr1); if (mcr1 & 0x04) - pci_write_config_byte(dev, 0x50, (mcr1 & ~0x04)); + pci_write_config_byte(dev, 0x50, mcr1 & ~0x04); + + return ide_setup_pci_device(dev, d); +} + +static int __devinit init_setup_hpt372a(struct pci_dev *dev, ide_pci_device_t *d) +{ + u8 rev = 0; + + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); + + if (rev > 1) + d->name = "HPT372N"; + + return ide_setup_pci_device(dev, d); +} + +static int __devinit init_setup_hpt302(struct pci_dev *dev, ide_pci_device_t *d) +{ + u8 rev = 0; + + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); + + if (rev > 1) + d->name = "HPT302N"; return ide_setup_pci_device(dev, d); } @@ -1460,30 +1493,22 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) { struct pci_dev *findev = NULL; u8 rev = 0, pin1 = 0, pin2 = 0; - char *chipset_names[] = {"HPT366", "HPT366", "HPT368", - "HPT370", "HPT370A", "HPT372", - "HPT372N" }; + static char *chipset_names[] = { "HPT366", "HPT366", "HPT368", + "HPT370", "HPT370A", "HPT372", + "HPT372N" }; if (PCI_FUNC(dev->devfn) & 1) return -ENODEV; pci_read_config_byte(dev, PCI_REVISION_ID, &rev); - if(dev->device == PCI_DEVICE_ID_TTI_HPT372N) + if (rev > 6) rev = 6; - if(rev <= 6) - d->name = chipset_names[rev]; + d->name = chipset_names[rev]; - switch(rev) { - case 6: - case 5: - case 4: - case 3: - goto init_single; - default: - break; - } + if (rev > 2) + goto init_single; d->channels = 1; @@ -1521,7 +1546,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .extra = 240 },{ /* 1 */ .name = "HPT372A", - .init_setup = init_setup_hpt37x, + .init_setup = init_setup_hpt372a, .init_chipset = init_chipset_hpt366, .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, @@ -1529,9 +1554,10 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, + .extra = 240 },{ /* 2 */ .name = "HPT302", - .init_setup = init_setup_hpt37x, + .init_setup = init_setup_hpt302, .init_chipset = init_chipset_hpt366, .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, @@ -1539,6 +1565,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, + .extra = 240 },{ /* 3 */ .name = "HPT371", .init_setup = init_setup_hpt371, @@ -1550,6 +1577,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .autodma = AUTODMA, .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, + .extra = 240 },{ /* 4 */ .name = "HPT374", .init_setup = init_setup_hpt374, @@ -1560,9 +1588,10 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .channels = 2, /* 4 */ .autodma = AUTODMA, .bootable = OFF_BOARD, + .extra = 240 },{ /* 5 */ .name = "HPT372N", - .init_setup = init_setup_hpt37x, + .init_setup = init_setup_hpt372n, .init_chipset = init_chipset_hpt366, .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, @@ -1570,6 +1599,7 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .channels = 2, /* 4 */ .autodma = AUTODMA, .bootable = OFF_BOARD, + .extra = 240 } }; -- cgit v1.2.3 From b4586715d7944dfbcb2b6b76a0098413cf3222e4 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:17:54 +0100 Subject: hpt366: switch to using pci_get_slot Switch to using pci_get_slot() to get to the function 1 of HPT36x/374 chips -- there's no need for the driver itself to walk the list of the PCI devices, and it also forgets to check the bus number of the device found. Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 61 ++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 30 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 32a40710e73..577aef94d7b 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 0.44 May 20, 2006 + * linux/drivers/ide/pci/hpt366.c Version 0.45 May 27, 2006 * * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -79,6 +79,7 @@ * - prefix the driver startup messages with the real chip name * - claim the extra 240 bytes of I/O space for all chips * - optimize the rate masking/filtering and the drive list lookup code + * - use pci_get_slot() to get to the function 1 of HPT36x/374 * * */ @@ -1416,24 +1417,24 @@ static void __devinit init_iops_hpt366(ide_hwif_t *hwif) static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d) { - struct pci_dev *findev = NULL; + struct pci_dev *dev2; if (PCI_FUNC(dev->devfn) & 1) return -ENODEV; - while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - ((findev->devfn - dev->devfn) == 1) && - (PCI_FUNC(findev->devfn) & 1)) { - if (findev->irq != dev->irq) { - /* FIXME: we need a core pci_set_interrupt() */ - findev->irq = dev->irq; - printk(KERN_WARNING "%s: pci-config space interrupt " - "fixed.\n", d->name); - } - return ide_setup_pci_devices(dev, findev, d); + if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) { + int ret; + + if (dev2->irq != dev->irq) { + /* FIXME: we need a core pci_set_interrupt() */ + dev2->irq = dev->irq; + printk(KERN_WARNING "%s: PCI config space interrupt " + "fixed.\n", d->name); } + ret = ide_setup_pci_devices(dev, dev2, d); + if (ret < 0) + pci_dev_put(dev2); + return ret; } return ide_setup_pci_device(dev, d); } @@ -1491,8 +1492,8 @@ static int __devinit init_setup_hpt302(struct pci_dev *dev, ide_pci_device_t *d) static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) { - struct pci_dev *findev = NULL; - u8 rev = 0, pin1 = 0, pin2 = 0; + struct pci_dev *dev2; + u8 rev = 0; static char *chipset_names[] = { "HPT366", "HPT366", "HPT368", "HPT370", "HPT370A", "HPT372", "HPT372N" }; @@ -1512,21 +1513,21 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) d->channels = 1; - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); - while ((findev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, findev)) != NULL) { - if ((findev->vendor == dev->vendor) && - (findev->device == dev->device) && - ((findev->devfn - dev->devfn) == 1) && - (PCI_FUNC(findev->devfn) & 1)) { - pci_read_config_byte(findev, PCI_INTERRUPT_PIN, &pin2); - if ((pin1 != pin2) && (dev->irq == findev->irq)) { - d->bootable = ON_BOARD; - printk("%s: onboard version of chipset, " - "pin1=%d pin2=%d\n", d->name, - pin1, pin2); - } - return ide_setup_pci_devices(dev, findev, d); + if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) { + u8 pin1 = 0, pin2 = 0; + int ret; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); + pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); + if (pin1 != pin2 && dev->irq == dev2->irq) { + d->bootable = ON_BOARD; + printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", + d->name, pin1, pin2); } + ret = ide_setup_pci_devices(dev, dev2, d); + if (ret < 0) + pci_dev_put(dev2); + return ret; } init_single: return ide_setup_pci_device(dev, d); -- cgit v1.2.3 From abc4ad4c6b3c6a51a0aa633e3d3fbc80b0ecabfe Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:18:05 +0100 Subject: hpt366: cache channel's MCR address Begin the real driver redesign. For the starters: - cache the offset of the IDE channel's MISC. control registers which are used throughout the driver in hwif->select_data; - only touch the relevant MCR when detecting the cable type on HPT374's function 1; - make HPT36x's speedproc handler look the same way as HPT37x ones; fix the PIO timing register mask for HPT37x. - rename all the HPT3xx register related variables consistently; clean up the whitespace. Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 371 +++++++++++++++++++++++------------------------ 1 file changed, 181 insertions(+), 190 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 577aef94d7b..fd15329d953 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 0.45 May 27, 2006 + * linux/drivers/ide/pci/hpt366.c Version 0.50 May 28, 2006 * * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -80,6 +80,11 @@ * - claim the extra 240 bytes of I/O space for all chips * - optimize the rate masking/filtering and the drive list lookup code * - use pci_get_slot() to get to the function 1 of HPT36x/374 + * - cache the channel's MCRs' offset; only touch the relevant MCR when detecting + * the cable type on HPT374's function 1 + * - rename all the register related variables consistently + * - make HPT36x's speedproc handler look the same way as HPT37x ones; fix the + * PIO timing register mask for HPT37x * * */ @@ -497,109 +502,106 @@ static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table) static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) { - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); - u8 speed = hpt3xx_ratefilter(drive, xferspeed); - u8 regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; - u8 regfast = (hwif->channel) ? 0x55 : 0x51; - u8 drive_fast = 0; - u32 reg1 = 0, reg2 = 0; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = ide_get_hwifdata (hwif); + u8 speed = hpt3xx_ratefilter(drive, xferspeed); + u8 itr_addr = drive->dn ? 0x44 : 0x40; + u8 mcr_addr = hwif->select_data + 1; + u8 mcr = 0; + u32 new_itr, old_itr = 0; + u32 itr_mask = (speed < XFER_MW_DMA_0) ? 0x30070000 : 0xc0000000; /* * Disable the "fast interrupt" prediction. */ - pci_read_config_byte(dev, regfast, &drive_fast); - if (drive_fast & 0x80) - pci_write_config_byte(dev, regfast, drive_fast & ~0x80); + pci_read_config_byte(dev, mcr_addr, &mcr); + if (mcr & 0x80) + pci_write_config_byte(dev, mcr_addr, mcr & ~0x80); - reg2 = pci_bus_clock_list(speed, info->speed); + new_itr = pci_bus_clock_list(speed, info->speed); /* - * Disable on-chip PIO FIFO/buffer - * (to avoid problems handling I/O errors later) + * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well) + * to avoid problems handling I/O errors later */ - pci_read_config_dword(dev, regtime, ®1); - if (speed >= XFER_MW_DMA_0) { - reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000); - } else { - reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000); - } - reg2 &= ~0x80000000; + pci_read_config_dword(dev, itr_addr, &old_itr); + new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); + new_itr &= ~0xc0000000; - pci_write_config_dword(dev, regtime, reg2); + pci_write_config_dword(dev, itr_addr, new_itr); return ide_config_drive_speed(drive, speed); } static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) { - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); - u8 speed = hpt3xx_ratefilter(drive, xferspeed); - u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51; - u8 drive_pci = 0x40 + (drive->dn * 4); - u8 new_fast = 0, drive_fast = 0; - u32 list_conf = 0, drive_conf = 0; - u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = ide_get_hwifdata (hwif); + u8 speed = hpt3xx_ratefilter(drive, xferspeed); + u8 mcr_addr = hwif->select_data + 1; + u8 itr_addr = 0x40 + (drive->dn * 4); + u8 new_mcr = 0, old_mcr = 0; + u32 new_itr, old_itr = 0; + u32 itr_mask = (speed < XFER_MW_DMA_0) ? 0x303c0000 : 0xc0000000; /* * Disable the "fast interrupt" prediction. * don't holdoff on interrupts. (== 0x01 despite what the docs say) */ - pci_read_config_byte(dev, regfast, &drive_fast); - new_fast = drive_fast; - if (new_fast & 0x02) - new_fast &= ~0x02; + pci_read_config_byte(dev, mcr_addr, &old_mcr); + new_mcr = old_mcr; + if (new_mcr & 0x02) + new_mcr &= ~0x02; #ifdef HPT_DELAY_INTERRUPT - if (new_fast & 0x01) - new_fast &= ~0x01; + if (new_mcr & 0x01) + new_mcr &= ~0x01; #else - if ((new_fast & 0x01) == 0) - new_fast |= 0x01; + if ((new_mcr & 0x01) == 0) + new_mcr |= 0x01; #endif - if (new_fast != drive_fast) - pci_write_config_byte(dev, regfast, new_fast); + if (new_mcr != old_mcr) + pci_write_config_byte(dev, mcr_addr, new_mcr); - list_conf = pci_bus_clock_list(speed, info->speed); + new_itr = pci_bus_clock_list(speed, info->speed); - pci_read_config_dword(dev, drive_pci, &drive_conf); - list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); + pci_read_config_dword(dev, itr_addr, &old_itr); + new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); if (speed < XFER_MW_DMA_0) - list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ - pci_write_config_dword(dev, drive_pci, list_conf); + new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ + pci_write_config_dword(dev, itr_addr, new_itr); return ide_config_drive_speed(drive, speed); } static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed) { - ide_hwif_t *hwif = drive->hwif; - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); - u8 speed = hpt3xx_ratefilter(drive, xferspeed); - u8 regfast = (drive->hwif->channel) ? 0x55 : 0x51; - u8 drive_fast = 0, drive_pci = 0x40 + (drive->dn * 4); - u32 list_conf = 0, drive_conf = 0; - u32 conf_mask = (speed >= XFER_MW_DMA_0) ? 0xc0000000 : 0x30070000; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = ide_get_hwifdata (hwif); + u8 speed = hpt3xx_ratefilter(drive, xferspeed); + u8 mcr_addr = hwif->select_data + 1; + u8 itr_addr = 0x40 + (drive->dn * 4); + u8 mcr = 0; + u32 new_itr, old_itr = 0; + u32 itr_mask = (speed < XFER_MW_DMA_0) ? 0x303c0000 : 0xc0000000; /* * Disable the "fast interrupt" prediction. * don't holdoff on interrupts. (== 0x01 despite what the docs say) */ - pci_read_config_byte(dev, regfast, &drive_fast); - drive_fast &= ~0x07; - pci_write_config_byte(dev, regfast, drive_fast); + pci_read_config_byte (dev, mcr_addr, &mcr); + pci_write_config_byte(dev, mcr_addr, (mcr & ~0x07)); - list_conf = pci_bus_clock_list(speed, info->speed); - pci_read_config_dword(dev, drive_pci, &drive_conf); - list_conf = (list_conf & ~conf_mask) | (drive_conf & conf_mask); + new_itr = pci_bus_clock_list(speed, info->speed); + pci_read_config_dword(dev, itr_addr, &old_itr); + new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); if (speed < XFER_MW_DMA_0) - list_conf &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ - pci_write_config_dword(dev, drive_pci, list_conf); + new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ + pci_write_config_dword(dev, itr_addr, new_itr); return ide_config_drive_speed(drive, speed); } @@ -666,39 +668,41 @@ static int hpt3xx_quirkproc(ide_drive_t *drive) static void hpt3xx_intrproc (ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = HWIF(drive); if (drive->quirk_list) return; /* drives in the quirk_list may not like intr setups/cleanups */ - hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG); + hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG); } static void hpt3xx_maskproc (ide_drive_t *drive, int mask) { - ide_hwif_t *hwif = drive->hwif; - struct hpt_info *info = ide_get_hwifdata(hwif); - struct pci_dev *dev = hwif->pci_dev; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = ide_get_hwifdata(hwif); if (drive->quirk_list) { if (info->revision >= 3) { - u8 reg5a = 0; - pci_read_config_byte(dev, 0x5a, ®5a); - if (((reg5a & 0x10) >> 4) != mask) - pci_write_config_byte(dev, 0x5a, mask ? (reg5a | 0x10) : (reg5a & ~0x10)); + u8 scr1 = 0; + + pci_read_config_byte(dev, 0x5a, &scr1); + if (((scr1 & 0x10) >> 4) != mask) { + if (mask) + scr1 |= 0x10; + else + scr1 &= ~0x10; + pci_write_config_byte(dev, 0x5a, scr1); + } } else { - if (mask) { + if (mask) disable_irq(hwif->irq); - } else { - enable_irq(hwif->irq); - } + else + enable_irq (hwif->irq); } - } else { - if (IDE_CONTROL_REG) - hwif->OUTB(mask ? (drive->ctl | 2) : - (drive->ctl & ~2), - IDE_CONTROL_REG); - } + } else + hwif->OUTB(mask ? (drive->ctl | 2) : (drive->ctl & ~2), + IDE_CONTROL_REG); } static int hpt366_config_drive_xfer_rate (ide_drive_t *drive) @@ -727,28 +731,29 @@ fast_ata_pio: } /* - * This is specific to the HPT366 UDMA bios chipset + * This is specific to the HPT366 UDMA chipset * by HighPoint|Triones Technologies, Inc. */ -static int hpt366_ide_dma_lostirq (ide_drive_t *drive) +static int hpt366_ide_dma_lostirq(ide_drive_t *drive) { - struct pci_dev *dev = HWIF(drive)->pci_dev; - u8 reg50h = 0, reg52h = 0, reg5ah = 0; - - pci_read_config_byte(dev, 0x50, ®50h); - pci_read_config_byte(dev, 0x52, ®52h); - pci_read_config_byte(dev, 0x5a, ®5ah); - printk("%s: (%s) reg50h=0x%02x, reg52h=0x%02x, reg5ah=0x%02x\n", - drive->name, __FUNCTION__, reg50h, reg52h, reg5ah); - if (reg5ah & 0x10) - pci_write_config_byte(dev, 0x5a, reg5ah & ~0x10); + struct pci_dev *dev = HWIF(drive)->pci_dev; + u8 mcr1 = 0, mcr3 = 0, scr1 = 0; + + pci_read_config_byte(dev, 0x50, &mcr1); + pci_read_config_byte(dev, 0x52, &mcr3); + pci_read_config_byte(dev, 0x5a, &scr1); + printk("%s: (%s) mcr1=0x%02x, mcr3=0x%02x, scr1=0x%02x\n", + drive->name, __FUNCTION__, mcr1, mcr3, scr1); + if (scr1 & 0x10) + pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); return __ide_dma_lostirq(drive); } static void hpt370_clear_engine (ide_drive_t *drive) { - u8 regstate = HWIF(drive)->channel ? 0x54 : 0x50; - pci_write_config_byte(HWIF(drive)->pci_dev, regstate, 0x37); + ide_hwif_t *hwif = HWIF(drive); + + pci_write_config_byte(hwif->pci_dev, hwif->select_data, 0x37); udelay(10); } @@ -780,10 +785,10 @@ static int hpt370_ide_dma_end (ide_drive_t *drive) static void hpt370_lostirq_timeout (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - u8 bfifo = 0, reginfo = hwif->channel ? 0x56 : 0x52; + u8 bfifo = 0; u8 dma_stat = 0, dma_cmd = 0; - pci_read_config_byte(HWIF(drive)->pci_dev, reginfo, &bfifo); + pci_read_config_byte(HWIF(drive)->pci_dev, hwif->select_data + 2, &bfifo); printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo); hpt370_clear_engine(drive); /* get dma command mode */ @@ -814,10 +819,9 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); u16 bfifo = 0; - u8 reginfo = hwif->channel ? 0x56 : 0x52; - u8 dma_stat; + u8 dma_stat; - pci_read_config_word(hwif->pci_dev, reginfo, &bfifo); + pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo); if (bfifo & 0x1FF) { // printk("%s: %d bytes in FIFO\n", drive->name, bfifo); return 0; @@ -825,7 +829,7 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) dma_stat = hwif->INB(hwif->dma_status); /* return 1 if INTR asserted */ - if ((dma_stat & 4) == 4) + if (dma_stat & 4) return 1; if (!drive->waiting_for_dma) @@ -834,17 +838,17 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) return 0; } -static int hpt374_ide_dma_end (ide_drive_t *drive) +static int hpt374_ide_dma_end(ide_drive_t *drive) { - struct pci_dev *dev = HWIF(drive)->pci_dev; ide_hwif_t *hwif = HWIF(drive); - u8 msc_stat = 0, mscreg = hwif->channel ? 0x54 : 0x50; - u8 bwsr_stat = 0, bwsr_mask = hwif->channel ? 0x02 : 0x01; - - pci_read_config_byte(dev, 0x6a, &bwsr_stat); - pci_read_config_byte(dev, mscreg, &msc_stat); - if ((bwsr_stat & bwsr_mask) == bwsr_mask) - pci_write_config_byte(dev, mscreg, msc_stat|0x30); + struct pci_dev *dev = hwif->pci_dev; + u8 mcr = 0, mcr_addr = hwif->select_data; + u8 bwsr = 0, mask = hwif->channel ? 0x02 : 0x01; + + pci_read_config_byte(dev, 0x6a, &bwsr); + pci_read_config_byte(dev, mcr_addr, &mcr); + if (bwsr & mask) + pci_write_config_byte(dev, mcr_addr, mcr | 0x30); return __ide_dma_end(drive); } @@ -910,6 +914,7 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) /* * Set/get power state for a drive. + * NOTE: affects both drives on each channel. * * When we turn the power back on, we need to re-initialize things. */ @@ -917,26 +922,18 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) static int hpt3xx_busproc(ide_drive_t *drive, int state) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - u8 tristate, resetmask, bus_reg = 0; - u16 tri_reg = 0; + u8 mcr_addr = hwif->select_data + 2; + u8 resetmask = hwif->channel ? 0x80 : 0x40; + u8 bsr2 = 0; + u16 mcr = 0; hwif->bus_state = state; - if (hwif->channel) { - /* secondary channel */ - tristate = 0x56; - resetmask = 0x80; - } else { - /* primary channel */ - tristate = 0x52; - resetmask = 0x40; - } - /* Grab the status. */ - pci_read_config_word(dev, tristate, &tri_reg); - pci_read_config_byte(dev, 0x59, &bus_reg); + pci_read_config_word(dev, mcr_addr, &mcr); + pci_read_config_byte(dev, 0x59, &bsr2); /* * Set the state. We don't set it if we don't need to do so. @@ -944,22 +941,22 @@ static int hpt3xx_busproc(ide_drive_t *drive, int state) */ switch (state) { case BUSSTATE_ON: - if (!(bus_reg & resetmask)) + if (!(bsr2 & resetmask)) return 0; hwif->drives[0].failures = hwif->drives[1].failures = 0; - pci_write_config_byte(dev, 0x59, bus_reg & ~resetmask); - pci_write_config_word(dev, tristate, tri_reg & ~TRISTATE_BIT); + pci_write_config_byte(dev, 0x59, bsr2 & ~resetmask); + pci_write_config_word(dev, mcr_addr, mcr & ~TRISTATE_BIT); return 0; case BUSSTATE_OFF: - if ((bus_reg & resetmask) && !(tri_reg & TRISTATE_BIT)) + if ((bsr2 & resetmask) && !(mcr & TRISTATE_BIT)) return 0; - tri_reg &= ~TRISTATE_BIT; + mcr &= ~TRISTATE_BIT; break; case BUSSTATE_TRISTATE: - if ((bus_reg & resetmask) && (tri_reg & TRISTATE_BIT)) + if ((bsr2 & resetmask) && (mcr & TRISTATE_BIT)) return 0; - tri_reg |= TRISTATE_BIT; + mcr |= TRISTATE_BIT; break; default: return -EINVAL; @@ -968,20 +965,20 @@ static int hpt3xx_busproc(ide_drive_t *drive, int state) hwif->drives[0].failures = hwif->drives[0].max_failures + 1; hwif->drives[1].failures = hwif->drives[1].max_failures + 1; - pci_write_config_word(dev, tristate, tri_reg); - pci_write_config_byte(dev, 0x59, bus_reg | resetmask); + pci_write_config_word(dev, mcr_addr, mcr); + pci_write_config_byte(dev, 0x59, bsr2 | resetmask); return 0; } static void __devinit hpt366_clocking(ide_hwif_t *hwif) { - u32 reg1 = 0; + u32 itr1 = 0; struct hpt_info *info = ide_get_hwifdata(hwif); - pci_read_config_dword(hwif->pci_dev, 0x40, ®1); + pci_read_config_dword(hwif->pci_dev, 0x40, &itr1); /* detect bus speed by looking at control reg timing: */ - switch((reg1 >> 8) & 7) { + switch((itr1 >> 8) & 7) { case 5: info->speed = forty_base_hpt36x; break; @@ -1003,7 +1000,7 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) int adjust, i; u16 freq = 0; u32 pll, temp = 0; - u8 reg5bh = 0, mcr1 = 0; + u8 scr2 = 0, mcr1 = 0; /* * default to pci clock. make sure MA15/16 are set to output @@ -1116,13 +1113,13 @@ static void __devinit hpt37x_clocking(ide_hwif_t *hwif) /* wait for clock stabilization */ for (i = 0; i < 0x50000; i++) { - pci_read_config_byte(dev, 0x5b, ®5bh); - if (reg5bh & 0x80) { + pci_read_config_byte(dev, 0x5b, &scr2); + if (scr2 & 0x80) { /* spin looking for the clock to destabilize */ for (i = 0; i < 0x1000; ++i) { pci_read_config_byte(dev, 0x5b, - ®5bh); - if ((reg5bh & 0x80) == 0) + &scr2); + if ((scr2 & 0x80) == 0) goto pll_recal; } pci_read_config_dword(dev, 0x5c, &pll); @@ -1159,26 +1156,24 @@ init_hpt37X_done: static int __devinit init_hpt37x(struct pci_dev *dev) { - u8 reg5ah; + u8 scr1; - pci_read_config_byte(dev, 0x5a, ®5ah); + pci_read_config_byte (dev, 0x5a, &scr1); /* interrupt force enable */ - pci_write_config_byte(dev, 0x5a, (reg5ah & ~0x10)); + pci_write_config_byte(dev, 0x5a, (scr1 & ~0x10)); return 0; } static int __devinit init_hpt366(struct pci_dev *dev) { - u32 reg1 = 0; - u8 drive_fast = 0; + u8 mcr = 0; /* * Disable the "fast interrupt" prediction. */ - pci_read_config_byte(dev, 0x51, &drive_fast); - if (drive_fast & 0x80) - pci_write_config_byte(dev, 0x51, drive_fast & ~0x80); - pci_read_config_dword(dev, 0x40, ®1); + pci_read_config_byte(dev, 0x51, &mcr); + if (mcr & 0x80) + pci_write_config_byte(dev, 0x51, mcr & ~0x80); return 0; } @@ -1213,17 +1208,21 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = ide_get_hwifdata(hwif); - u8 ata66 = 0, regmask = (hwif->channel) ? 0x01 : 0x02; int serialize = HPT_SERIALIZE_IO; - + u8 scr1 = 0, ata66 = (hwif->channel) ? 0x01 : 0x02; + + /* Cache the channel's MISC. control registers' offset */ + hwif->select_data = hwif->channel ? 0x54 : 0x50; + hwif->tuneproc = &hpt3xx_tune_drive; hwif->speedproc = &hpt3xx_tune_chipset; hwif->quirkproc = &hpt3xx_quirkproc; hwif->intrproc = &hpt3xx_intrproc; hwif->maskproc = &hpt3xx_maskproc; - + hwif->busproc = &hpt3xx_busproc; + /* * HPT3xxN chips have some complications: * @@ -1241,7 +1240,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) /* * The HPT37x uses the CBLID pins as outputs for MA15/MA16 - * address lines to access an external eeprom. To read valid + * address lines to access an external EEPROM. To read valid * cable detect state the pins must be enabled as inputs. */ if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) { @@ -1250,35 +1249,28 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) * - set bit 15 of reg 0x52 to enable TCBLID as input * - set bit 15 of reg 0x56 to enable FCBLID as input */ - u16 mcr3, mcr6; - pci_read_config_word(dev, 0x52, &mcr3); - pci_read_config_word(dev, 0x56, &mcr6); - pci_write_config_word(dev, 0x52, mcr3 | 0x8000); - pci_write_config_word(dev, 0x56, mcr6 | 0x8000); + u8 mcr_addr = hwif->select_data + 2; + u16 mcr; + + pci_read_config_word (dev, mcr_addr, &mcr); + pci_write_config_word(dev, mcr_addr, (mcr | 0x8000)); /* now read cable id register */ - pci_read_config_byte(dev, 0x5a, &ata66); - pci_write_config_word(dev, 0x52, mcr3); - pci_write_config_word(dev, 0x56, mcr6); + pci_read_config_byte (dev, 0x5a, &scr1); + pci_write_config_word(dev, mcr_addr, mcr); } else if (info->revision >= 3) { /* * HPT370/372 and 374 pcifn 0 - * - clear bit 0 of 0x5b to enable P/SCBLID as inputs + * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs */ - u8 scr2; - pci_read_config_byte(dev, 0x5b, &scr2); - pci_write_config_byte(dev, 0x5b, scr2 & ~1); - /* now read cable id register */ - pci_read_config_byte(dev, 0x5a, &ata66); - pci_write_config_byte(dev, 0x5b, scr2); - } else { - pci_read_config_byte(dev, 0x5a, &ata66); - } + u8 scr2 = 0; -#ifdef DEBUG - printk("HPT366: reg5ah=0x%02x ATA-%s Cable Port%d\n", - ata66, (ata66 & regmask) ? "33" : "66", - PCI_FUNC(hwif->pci_dev->devfn)); -#endif /* DEBUG */ + pci_read_config_byte (dev, 0x5b, &scr2); + pci_write_config_byte(dev, 0x5b, (scr2 & ~1)); + /* now read cable id register */ + pci_read_config_byte (dev, 0x5a, &scr1); + pci_write_config_byte(dev, 0x5b, scr2); + } else + pci_read_config_byte (dev, 0x5a, &scr1); /* Serialize access to this device */ if (serialize && hwif->mate) @@ -1300,7 +1292,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->mwdma_mask = 0x07; if (!(hwif->udma_four)) - hwif->udma_four = ((ata66 & regmask) ? 0 : 1); + hwif->udma_four = ((scr1 & ata66) ? 0 : 1); hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; if (info->revision >= 8) { @@ -1327,11 +1319,10 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) { - struct hpt_info *info = ide_get_hwifdata(hwif); - u8 masterdma = 0, slavedma = 0; - u8 dma_new = 0, dma_old = 0; - u8 primary = hwif->channel ? 0x4b : 0x43; - u8 secondary = hwif->channel ? 0x4f : 0x47; + struct pci_dev *dev = hwif->pci_dev; + struct hpt_info *info = ide_get_hwifdata(hwif); + u8 masterdma = 0, slavedma = 0; + u8 dma_new = 0, dma_old = 0; unsigned long flags; if (!dmabase) @@ -1348,13 +1339,13 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) local_irq_save(flags); dma_new = dma_old; - pci_read_config_byte(hwif->pci_dev, primary, &masterdma); - pci_read_config_byte(hwif->pci_dev, secondary, &slavedma); + pci_read_config_byte(dev, hwif->channel ? 0x4b : 0x43, &masterdma); + pci_read_config_byte(dev, hwif->channel ? 0x4f : 0x47, &slavedma); if (masterdma & 0x30) dma_new |= 0x20; - if (slavedma & 0x30) dma_new |= 0x40; + if ( slavedma & 0x30) dma_new |= 0x40; if (dma_new != dma_old) - hwif->OUTB(dma_new, dmabase+2); + hwif->OUTB(dma_new, dmabase + 2); local_irq_restore(flags); -- cgit v1.2.3 From 26ccb802ee3f9a1f1fd5bc6abf38f124bfbd9cb2 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:18:11 +0100 Subject: hpt366: merge HPT37x speedproc handlers Continue with the driver rewrite: - move the interrupt twiddling code from the speedproc handlers into the init_hwif_hpt366 which allows to merge the two HPT37x speedproc handlers into one; - get rid of in init_hpt366 which solely consists of the duplicate code, then fold init_hpt37x() into init_chipset_hpt366(); - fix hpt3xx_tune_drive() to always set the PIO mode requested, not the best possible one, change hpt366_config_drive_xfer_rate() accordingly, simplify it a bit; - group all the DMA related code together init_hwif_hpt366(), and generally clean up and beautify it. Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 258 ++++++++++++++++------------------------------- 1 file changed, 88 insertions(+), 170 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index fd15329d953..7317defd821 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 0.50 May 28, 2006 + * linux/drivers/ide/pci/hpt366.c Version 0.51 Jun 04, 2006 * * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -83,13 +83,16 @@ * - cache the channel's MCRs' offset; only touch the relevant MCR when detecting * the cable type on HPT374's function 1 * - rename all the register related variables consistently - * - make HPT36x's speedproc handler look the same way as HPT37x ones; fix the - * PIO timing register mask for HPT37x + * - move the interrupt twiddling code from the speedproc handlers into the + * init_hwif handler, also grouping all the DMA related code together there; + * simplify the init_chipset handler + * - merge two HPT37x speedproc handlers and fix the PIO timing register mask + * there; make HPT36x speedproc handler look the same way as the HPT37x one + * - fix the tuneproc handler to always set the PIO mode requested, not the + * best possible one * - * */ - #include #include #include @@ -507,19 +510,9 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) struct hpt_info *info = ide_get_hwifdata (hwif); u8 speed = hpt3xx_ratefilter(drive, xferspeed); u8 itr_addr = drive->dn ? 0x44 : 0x40; - u8 mcr_addr = hwif->select_data + 1; - u8 mcr = 0; - u32 new_itr, old_itr = 0; u32 itr_mask = (speed < XFER_MW_DMA_0) ? 0x30070000 : 0xc0000000; - - /* - * Disable the "fast interrupt" prediction. - */ - pci_read_config_byte(dev, mcr_addr, &mcr); - if (mcr & 0x80) - pci_write_config_byte(dev, mcr_addr, mcr & ~0x80); - - new_itr = pci_bus_clock_list(speed, info->speed); + u32 new_itr = pci_bus_clock_list(speed, info->speed); + u32 old_itr = 0; /* * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well) @@ -534,38 +527,16 @@ static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } -static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) +static int hpt37x_tune_chipset(ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = ide_get_hwifdata (hwif); u8 speed = hpt3xx_ratefilter(drive, xferspeed); - u8 mcr_addr = hwif->select_data + 1; u8 itr_addr = 0x40 + (drive->dn * 4); - u8 new_mcr = 0, old_mcr = 0; - u32 new_itr, old_itr = 0; u32 itr_mask = (speed < XFER_MW_DMA_0) ? 0x303c0000 : 0xc0000000; - - /* - * Disable the "fast interrupt" prediction. - * don't holdoff on interrupts. (== 0x01 despite what the docs say) - */ - pci_read_config_byte(dev, mcr_addr, &old_mcr); - new_mcr = old_mcr; - if (new_mcr & 0x02) - new_mcr &= ~0x02; - -#ifdef HPT_DELAY_INTERRUPT - if (new_mcr & 0x01) - new_mcr &= ~0x01; -#else - if ((new_mcr & 0x01) == 0) - new_mcr |= 0x01; -#endif - if (new_mcr != old_mcr) - pci_write_config_byte(dev, mcr_addr, new_mcr); - - new_itr = pci_bus_clock_list(speed, info->speed); + u32 new_itr = pci_bus_clock_list(speed, info->speed); + u32 old_itr = 0; pci_read_config_dword(dev, itr_addr, &old_itr); new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); @@ -577,71 +548,34 @@ static int hpt370_tune_chipset(ide_drive_t *drive, u8 xferspeed) return ide_config_drive_speed(drive, speed); } -static int hpt372_tune_chipset(ide_drive_t *drive, u8 xferspeed) +static int hpt3xx_tune_chipset(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = HWIF(drive); - struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata (hwif); - u8 speed = hpt3xx_ratefilter(drive, xferspeed); - u8 mcr_addr = hwif->select_data + 1; - u8 itr_addr = 0x40 + (drive->dn * 4); - u8 mcr = 0; - u32 new_itr, old_itr = 0; - u32 itr_mask = (speed < XFER_MW_DMA_0) ? 0x303c0000 : 0xc0000000; - - /* - * Disable the "fast interrupt" prediction. - * don't holdoff on interrupts. (== 0x01 despite what the docs say) - */ - pci_read_config_byte (dev, mcr_addr, &mcr); - pci_write_config_byte(dev, mcr_addr, (mcr & ~0x07)); - - new_itr = pci_bus_clock_list(speed, info->speed); - pci_read_config_dword(dev, itr_addr, &old_itr); - new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask); - if (speed < XFER_MW_DMA_0) - new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */ - pci_write_config_dword(dev, itr_addr, new_itr); - - return ide_config_drive_speed(drive, speed); -} - -static int hpt3xx_tune_chipset (ide_drive_t *drive, u8 speed) -{ - ide_hwif_t *hwif = drive->hwif; struct hpt_info *info = ide_get_hwifdata(hwif); - if (info->revision >= 8) - return hpt372_tune_chipset(drive, speed); /* not a typo */ - else if (info->revision >= 5) - return hpt372_tune_chipset(drive, speed); - else if (info->revision >= 3) - return hpt370_tune_chipset(drive, speed); + if (info->revision >= 3) + return hpt37x_tune_chipset(drive, speed); else /* hpt368: hpt_minimum_revision(dev, 2) */ return hpt36x_tune_chipset(drive, speed); } -static void hpt3xx_tune_drive (ide_drive_t *drive, u8 pio) +static void hpt3xx_tune_drive(ide_drive_t *drive, u8 pio) { - pio = ide_get_best_pio_mode(drive, 255, pio, NULL); - (void) hpt3xx_tune_chipset(drive, (XFER_PIO_0 + pio)); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + (void) hpt3xx_tune_chipset (drive, XFER_PIO_0 + pio); } /* * This allows the configuration of ide_pci chipset registers * for cards that learn about the drive's UDMA, DMA, PIO capabilities - * after the drive is reported by the OS. Initially for designed for + * after the drive is reported by the OS. Initially designed for * HPT366 UDMA chipset by HighPoint|Triones Technologies, Inc. * - * check_in_drive_lists(drive, bad_ata66_4) - * check_in_drive_lists(drive, bad_ata66_3) - * check_in_drive_lists(drive, bad_ata33) - * */ -static int config_chipset_for_dma (ide_drive_t *drive) +static int config_chipset_for_dma(ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive)); - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = HWIF(drive); struct hpt_info *info = ide_get_hwifdata(hwif); if (!speed) @@ -666,7 +600,7 @@ static int hpt3xx_quirkproc(ide_drive_t *drive) return 0; } -static void hpt3xx_intrproc (ide_drive_t *drive) +static void hpt3xx_intrproc(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -676,7 +610,7 @@ static void hpt3xx_intrproc (ide_drive_t *drive) hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG); } -static void hpt3xx_maskproc (ide_drive_t *drive, int mask) +static void hpt3xx_maskproc(ide_drive_t *drive, int mask) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; @@ -705,25 +639,22 @@ static void hpt3xx_maskproc (ide_drive_t *drive, int mask) IDE_CONTROL_REG); } -static int hpt366_config_drive_xfer_rate (ide_drive_t *drive) +static int hpt366_config_drive_xfer_rate(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; + ide_hwif_t *hwif = HWIF(drive); struct hd_driveid *id = drive->id; drive->init_speed = 0; if ((id->capability & 1) && drive->autodma) { - - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); goto fast_ata_pio; } else if ((id->capability & 8) || (id->field_valid & 2)) { fast_ata_pio: - hpt3xx_tune_drive(drive, 5); + hpt3xx_tune_drive(drive, 255); return hwif->ide_dma_off_quietly(drive); } /* IORDY not supported */ @@ -1154,34 +1085,8 @@ init_hpt37X_done: udelay(100); } -static int __devinit init_hpt37x(struct pci_dev *dev) -{ - u8 scr1; - - pci_read_config_byte (dev, 0x5a, &scr1); - /* interrupt force enable */ - pci_write_config_byte(dev, 0x5a, (scr1 & ~0x10)); - return 0; -} - -static int __devinit init_hpt366(struct pci_dev *dev) -{ - u8 mcr = 0; - - /* - * Disable the "fast interrupt" prediction. - */ - pci_read_config_byte(dev, 0x51, &mcr); - if (mcr & 0x80) - pci_write_config_byte(dev, 0x51, mcr & ~0x80); - - return 0; -} - static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name) { - int ret = 0; - /* * FIXME: Not portable. Also, why do we enable the ROM in the first place? * We don't seem to be using it. @@ -1195,23 +1100,25 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); - if (hpt_revision(dev) >= 3) - ret = init_hpt37x(dev); - else - ret = init_hpt366(dev); + if (hpt_revision(dev) >= 3) { + u8 scr1 = 0; - if (ret) - return ret; + /* Interrupt force enable. */ + pci_read_config_byte(dev, 0x5a, &scr1); + if (scr1 & 0x10) + pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); + } return dev->irq; } static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = ide_get_hwifdata(hwif); int serialize = HPT_SERIALIZE_IO; u8 scr1 = 0, ata66 = (hwif->channel) ? 0x01 : 0x02; + u8 new_mcr, old_mcr = 0; /* Cache the channel's MISC. control registers' offset */ hwif->select_data = hwif->channel ? 0x54 : 0x50; @@ -1238,6 +1145,41 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->rw_disk = &hpt3xxn_rw_disk; } + /* Serialize access to this device if needed */ + if (serialize && hwif->mate) + hwif->serialized = hwif->mate->serialized = 1; + + /* + * Disable the "fast interrupt" prediction. Don't hold off + * on interrupts. (== 0x01 despite what the docs say) + */ + pci_read_config_byte(dev, hwif->select_data + 1, &old_mcr); + + if (info->revision >= 5) /* HPT372 and newer */ + new_mcr = old_mcr & ~0x07; + else if (info->revision >= 3) { /* HPT370 and HPT370A */ + new_mcr = old_mcr; + new_mcr &= ~0x02; + +#ifdef HPT_DELAY_INTERRUPT + new_mcr &= ~0x01; +#else + new_mcr |= 0x01; +#endif + } else /* HPT366 and HPT368 */ + new_mcr = old_mcr & ~0x80; + + if (new_mcr != old_mcr) + pci_write_config_byte(dev, hwif->select_data + 1, new_mcr); + + if (!hwif->dma_base) { + hwif->drives[0].autotune = hwif->drives[1].autotune = 1; + return; + } + + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + /* * The HPT37x uses the CBLID pins as outputs for MA15/MA16 * address lines to access an external EEPROM. To read valid @@ -1272,54 +1214,30 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) } else pci_read_config_byte (dev, 0x5a, &scr1); - /* Serialize access to this device */ - if (serialize && hwif->mate) - hwif->serialized = hwif->mate->serialized = 1; + if (!hwif->udma_four) + hwif->udma_four = (scr1 & ata66) ? 0 : 1; - /* - * Set up ioctl for power status. - * NOTE: power affects both drives on each channel. - */ - hwif->busproc = &hpt3xx_busproc; - - if (!hwif->dma_base) { - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - return; - } + hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; - hwif->ultra_mask = 0x7f; - hwif->mwdma_mask = 0x07; - - if (!(hwif->udma_four)) - hwif->udma_four = ((scr1 & ata66) ? 0 : 1); - hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; - - if (info->revision >= 8) { - hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; - hwif->ide_dma_end = &hpt374_ide_dma_end; - } else if (info->revision >= 5) { - hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; - hwif->ide_dma_end = &hpt374_ide_dma_end; + if (info->revision >= 5) { + hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; + hwif->ide_dma_end = &hpt374_ide_dma_end; } else if (info->revision >= 3) { - hwif->dma_start = &hpt370_ide_dma_start; - hwif->ide_dma_end = &hpt370_ide_dma_end; - hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; - hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq; - } else if (info->revision >= 2) - hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; - else - hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; + hwif->dma_start = &hpt370_ide_dma_start; + hwif->ide_dma_end = &hpt370_ide_dma_end; + hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; + hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq; + } else + hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; if (!noautodma) hwif->autodma = 1; - hwif->drives[0].autodma = hwif->autodma; - hwif->drives[1].autodma = hwif->autodma; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; } static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) { - struct pci_dev *dev = hwif->pci_dev; + struct pci_dev *dev = hwif->pci_dev; struct hpt_info *info = ide_get_hwifdata(hwif); u8 masterdma = 0, slavedma = 0; u8 dma_new = 0, dma_old = 0; @@ -1334,7 +1252,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) return; } - dma_old = hwif->INB(dmabase+2); + dma_old = hwif->INB(dmabase + 2); local_irq_save(flags); -- cgit v1.2.3 From 4bf63de27e9fd9c0926ba3bb773de076b324a955 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:18:13 +0100 Subject: hpt366: clean up DMA timeout handling for HPT370 Clean up DMA timeout handling for HPT370: - hpt370_lostirq_timeout() cleared the DMA status which made __ide_dma_end() called afterwards return the incorrect result, and the DMA engine was reset both before and after stopping DMA while the HighPoint drivers only do it after (which seems logical) -- fix this and also rename the function; - get rid of the needless mutual recursion in hpt370_ide_dma_end() and hpt370_ide_dma_timeout(); - get rid of hpt370_lostirq_timeout() since hwif->ide_dma_end() called from the driver's interrupt handler later does all its work. Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 62 +++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 37 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 7317defd821..9ad1531b603 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 0.51 Jun 04, 2006 + * linux/drivers/ide/pci/hpt366.c Version 0.52 Jun 07, 2006 * * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -90,6 +90,7 @@ * there; make HPT36x speedproc handler look the same way as the HPT37x one * - fix the tuneproc handler to always set the PIO mode requested, not the * best possible one + * - clean up DMA timeout handling for HPT370 * */ @@ -680,7 +681,7 @@ static int hpt366_ide_dma_lostirq(ide_drive_t *drive) return __ide_dma_lostirq(drive); } -static void hpt370_clear_engine (ide_drive_t *drive) +static void hpt370_clear_engine(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -688,6 +689,22 @@ static void hpt370_clear_engine (ide_drive_t *drive) udelay(10); } +static void hpt370_irq_timeout(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + u16 bfifo = 0; + u8 dma_cmd; + + pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo); + printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff); + + /* get DMA command mode */ + dma_cmd = hwif->INB(hwif->dma_command); + /* stop DMA */ + hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command); + hpt370_clear_engine(drive); +} + static void hpt370_ide_dma_start(ide_drive_t *drive) { #ifdef HPT_RESET_STATE_ENGINE @@ -696,55 +713,27 @@ static void hpt370_ide_dma_start(ide_drive_t *drive) ide_dma_start(drive); } -static int hpt370_ide_dma_end (ide_drive_t *drive) +static int hpt370_ide_dma_end(ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - u8 dma_stat = hwif->INB(hwif->dma_status); + u8 dma_stat = hwif->INB(hwif->dma_status); if (dma_stat & 0x01) { /* wait a little */ udelay(20); dma_stat = hwif->INB(hwif->dma_status); + if (dma_stat & 0x01) + hpt370_irq_timeout(drive); } - if ((dma_stat & 0x01) != 0) - /* fallthrough */ - (void) HWIF(drive)->ide_dma_timeout(drive); - return __ide_dma_end(drive); } -static void hpt370_lostirq_timeout (ide_drive_t *drive) +static int hpt370_ide_dma_timeout(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - u8 bfifo = 0; - u8 dma_stat = 0, dma_cmd = 0; - - pci_read_config_byte(HWIF(drive)->pci_dev, hwif->select_data + 2, &bfifo); - printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo); - hpt370_clear_engine(drive); - /* get dma command mode */ - dma_cmd = hwif->INB(hwif->dma_command); - /* stop dma */ - hwif->OUTB(dma_cmd & ~0x1, hwif->dma_command); - dma_stat = hwif->INB(hwif->dma_status); - /* clear errors */ - hwif->OUTB(dma_stat | 0x6, hwif->dma_status); -} - -static int hpt370_ide_dma_timeout (ide_drive_t *drive) -{ - hpt370_lostirq_timeout(drive); - hpt370_clear_engine(drive); + hpt370_irq_timeout(drive); return __ide_dma_timeout(drive); } -static int hpt370_ide_dma_lostirq (ide_drive_t *drive) -{ - hpt370_lostirq_timeout(drive); - hpt370_clear_engine(drive); - return __ide_dma_lostirq(drive); -} - /* returns 1 if DMA IRQ issued, 0 otherwise */ static int hpt374_ide_dma_test_irq(ide_drive_t *drive) { @@ -1226,7 +1215,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->dma_start = &hpt370_ide_dma_start; hwif->ide_dma_end = &hpt370_ide_dma_end; hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; - hwif->ide_dma_lostirq = &hpt370_ide_dma_lostirq; } else hwif->ide_dma_lostirq = &hpt366_ide_dma_lostirq; -- cgit v1.2.3 From 7b73ee05d0acb926923d43d78b61add776ea4bb1 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:18:16 +0100 Subject: hpt366: init code rewrite Finally, rework the driver init. code to correctly handle all the chip variants HighPoint has created so far. This should cure the rest of the timing issues in the driver (especially, on 66 MHz PCI) caused by the HighPoint's habit of switching the base DPLL clock with every new revision of the chips... - switch to using the enumeration type to differ between the numerous chip variants, matching PCI device/revision ID with the chip type early, at the init_setup stage; - extend the hpt_info structure to hold the DPLL and PCI clock frequencies, stop duplicating it for each channel by storing the pointer in the pci_dev structure: first, at the init_setup stage, point it to a static "template" with only the chip type and its specific base DPLL frequency, the highest supported DMA mode, and the chip settings table pointer filled, then, at the init_chipset stage, allocate per-chip instance and fill it with the rest of the necessary information; - get rid of the constant thresholds in the HPT37x PCI clock detection code, switch to calculating PCI clock frequency based on the chip's base DPLL frequency; - switch to using the DPLL clock and enable UltraATA/133 mode by default on anything newer than HPT370/A; - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(), unify the HPT36x/37x setup code and the speedproc handlers by joining the register setting lists into the table indexed by the clock selected; - add enablebits for all the chips to avoid touching disabled channels (though the HighPoint BIOS seem to only disable the primary one on HPT371/N); - separate the UltraDMA and MWDMA masks there to avoid changing PIO timings when setting an UltraDMA mode in hpt37x_tune_chipset(). This version has been tested on HPT370/302/371N. Thanks to Alan for the inspiration. Hopefully, his libata driver will also benefit from the work done on this "obsolete" driver... Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 851 +++++++++++++++++++++++++++-------------------- 1 file changed, 489 insertions(+), 362 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 9ad1531b603..4350e337136 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 0.52 Jun 07, 2006 + * linux/drivers/ide/pci/hpt366.c Version 1.00 Jun 25, 2006 * * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -60,13 +60,10 @@ * channel caused the cached register value to get out of sync with the * actual one, the channels weren't serialized, the turnaround shouldn't * be done on 66 MHz PCI bus - * - avoid calibrating PLL twice as the second time results in a wrong PCI - * frequency and thus in the wrong timings for the secondary channel - * - disable UltraATA/133 for HPT372 and UltraATA/100 for HPT370 by default - * as the ATA clock being used does not allow for this speed anyway - * - add support for HPT302N and HPT371N clocking (the same as for HPT372N) - * - HPT371/N are single channel chips, so avoid touching the primary channel - * which exists only virtually (there's no pins for it) + * - disable UltraATA/100 for HPT370 by default as the 33 MHz clock being used + * does not allow for this speed anyway + * - avoid touching disabled channels (e.g. HPT371/N are single channel chips, + * their primary channel is kind of virtual, it isn't tied to any pins) * - fix/remove bad/unused timing tables and use one set of tables for the whole * HPT37x chip family; save space by introducing the separate transfer mode * table in which the mode lookup is done @@ -76,22 +73,44 @@ * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead * - pass to init_chipset() handlers a copy of the IDE PCI device structure as * they tamper with its fields + * - pass to the init_setup handlers a copy of the ide_pci_device_t structure + * since they may tamper with its fields * - prefix the driver startup messages with the real chip name * - claim the extra 240 bytes of I/O space for all chips * - optimize the rate masking/filtering and the drive list lookup code * - use pci_get_slot() to get to the function 1 of HPT36x/374 - * - cache the channel's MCRs' offset; only touch the relevant MCR when detecting - * the cable type on HPT374's function 1 + * - cache offset of the channel's misc. control registers (MCRs) being used + * throughout the driver + * - only touch the relevant MCR when detecting the cable type on HPT374's + * function 1 * - rename all the register related variables consistently - * - move the interrupt twiddling code from the speedproc handlers into the - * init_hwif handler, also grouping all the DMA related code together there; - * simplify the init_chipset handler - * - merge two HPT37x speedproc handlers and fix the PIO timing register mask - * there; make HPT36x speedproc handler look the same way as the HPT37x one - * - fix the tuneproc handler to always set the PIO mode requested, not the - * best possible one + * - move all the interrupt twiddling code from the speedproc handlers into + * init_hwif_hpt366(), also grouping all the DMA related code together there + * - merge two HPT37x speedproc handlers, fix the PIO timing register mask and + * separate the UltraDMA and MWDMA masks there to avoid changing PIO timings + * when setting an UltraDMA mode + * - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select + * the best possible one * - clean up DMA timeout handling for HPT370 - * + * - switch to using the enumeration type to differ between the numerous chip + * variants, matching PCI device/revision ID with the chip type early, at the + * init_setup stage + * - extend the hpt_info structure to hold the DPLL and PCI clock frequencies, + * stop duplicating it for each channel by storing the pointer in the pci_dev + * structure: first, at the init_setup stage, point it to a static "template" + * with only the chip type and its specific base DPLL frequency, the highest + * supported DMA mode, and the chip settings table pointer filled, then, at + * the init_chipset stage, allocate per-chip instance and fill it with the + * rest of the necessary information + * - get rid of the constant thresholds in the HPT37x PCI clock detection code, + * switch to calculating PCI clock frequency based on the chip's base DPLL + * frequency + * - switch to using the DPLL clock and enable UltraATA/133 mode by default on + * anything newer than HPT370/A + * - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(); + * unify HPT36x/37x timing setup code and the speedproc handlers by joining + * the register setting lists into the table indexed by the clock selected + * Sergei Shtylyov, or */ #include @@ -345,71 +364,143 @@ static u32 sixty_six_base_hpt37x[] = { }; #define HPT366_DEBUG_DRIVE_INFO 0 -#define HPT374_ALLOW_ATA133_6 0 -#define HPT371_ALLOW_ATA133_6 0 -#define HPT302_ALLOW_ATA133_6 0 -#define HPT372_ALLOW_ATA133_6 0 +#define HPT374_ALLOW_ATA133_6 1 +#define HPT371_ALLOW_ATA133_6 1 +#define HPT302_ALLOW_ATA133_6 1 +#define HPT372_ALLOW_ATA133_6 1 #define HPT370_ALLOW_ATA100_5 0 #define HPT366_ALLOW_ATA66_4 1 #define HPT366_ALLOW_ATA66_3 1 #define HPT366_MAX_DEVS 8 -#define F_LOW_PCI_33 0x23 -#define F_LOW_PCI_40 0x29 -#define F_LOW_PCI_50 0x2d -#define F_LOW_PCI_66 0x42 +/* Supported ATA clock frequencies */ +enum ata_clock { + ATA_CLOCK_25MHZ, + ATA_CLOCK_33MHZ, + ATA_CLOCK_40MHZ, + ATA_CLOCK_50MHZ, + ATA_CLOCK_66MHZ, + NUM_ATA_CLOCKS +}; /* - * Hold all the highpoint quirks and revision information in one - * place. + * Hold all the HighPoint chip information in one place. */ -struct hpt_info -{ +struct hpt_info { + u8 chip_type; /* Chip type */ u8 max_mode; /* Speeds allowed */ - u8 revision; /* Chipset revision */ - u8 flags; /* Chipset properties */ -#define PLL_MODE 1 -#define IS_3xxN 2 -#define PCI_66MHZ 4 - /* Speed table */ - u32 *speed; + u8 dpll_clk; /* DPLL clock in MHz */ + u8 pci_clk; /* PCI clock in MHz */ + u32 **settings; /* Chipset settings table */ }; -/* - * This wants fixing so that we do everything not by revision - * (which breaks on the newest chips) but by creating an - * enumeration of chip variants and using that - */ +/* Supported HighPoint chips */ +enum { + HPT36x, + HPT370, + HPT370A, + HPT374, + HPT372, + HPT372A, + HPT302, + HPT371, + HPT372N, + HPT302N, + HPT371N +}; -static __devinit u8 hpt_revision(struct pci_dev *dev) -{ - u8 rev = 0; +static u32 *hpt36x_settings[NUM_ATA_CLOCKS] = { + twenty_five_base_hpt36x, + thirty_three_base_hpt36x, + forty_base_hpt36x, + NULL, + NULL +}; - pci_read_config_byte(dev, PCI_REVISION_ID, &rev); +static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = { + NULL, + thirty_three_base_hpt37x, + NULL, + fifty_base_hpt37x, + sixty_six_base_hpt37x +}; - switch(dev->device) { - /* Remap new 372N onto 372 */ - case PCI_DEVICE_ID_TTI_HPT372N: - rev = PCI_DEVICE_ID_TTI_HPT372; - break; - case PCI_DEVICE_ID_TTI_HPT374: - rev = PCI_DEVICE_ID_TTI_HPT374; - break; - case PCI_DEVICE_ID_TTI_HPT371: - rev = PCI_DEVICE_ID_TTI_HPT371; - break; - case PCI_DEVICE_ID_TTI_HPT302: - rev = PCI_DEVICE_ID_TTI_HPT302; - break; - case PCI_DEVICE_ID_TTI_HPT372: - rev = PCI_DEVICE_ID_TTI_HPT372; - break; - default: - break; - } - return rev; -} +static struct hpt_info hpt36x __devinitdata = { + .chip_type = HPT36x, + .max_mode = (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1, + .dpll_clk = 0, /* no DPLL */ + .settings = hpt36x_settings +}; + +static struct hpt_info hpt370 __devinitdata = { + .chip_type = HPT370, + .max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2, + .dpll_clk = 48, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt370a __devinitdata = { + .chip_type = HPT370A, + .max_mode = HPT370_ALLOW_ATA100_5 ? 3 : 2, + .dpll_clk = 48, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt374 __devinitdata = { + .chip_type = HPT374, + .max_mode = HPT374_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 48, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt372 __devinitdata = { + .chip_type = HPT372, + .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 55, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt372a __devinitdata = { + .chip_type = HPT372A, + .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 66, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt302 __devinitdata = { + .chip_type = HPT302, + .max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 66, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt371 __devinitdata = { + .chip_type = HPT371, + .max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 66, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt372n __devinitdata = { + .chip_type = HPT372N, + .max_mode = HPT372_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 77, + .settings = hpt37x_settings +}; + +static struct hpt_info hpt302n __devinitdata = { + .chip_type = HPT302N, + .max_mode = HPT302_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 77, +}; + +static struct hpt_info hpt371n __devinitdata = { + .chip_type = HPT371N, + .max_mode = HPT371_ALLOW_ATA133_6 ? 4 : 3, + .dpll_clk = 77, + .settings = hpt37x_settings +}; static int check_in_drive_list(ide_drive_t *drive, const char **list) { @@ -423,7 +514,7 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list) static u8 hpt3xx_ratemask(ide_drive_t *drive) { - struct hpt_info *info = ide_get_hwifdata(HWIF(drive)); + struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev); u8 mode = info->max_mode; if (!eighty_ninty_three(drive) && mode) @@ -438,7 +529,8 @@ static u8 hpt3xx_ratemask(ide_drive_t *drive) static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) { - struct hpt_info *info = ide_get_hwifdata(HWIF(drive)); + struct hpt_info *info = pci_get_drvdata(HWIF(drive)->pci_dev); + u8 chip_type = info->chip_type; u8 mode = hpt3xx_ratemask(drive); if (drive->media != ide_disk) @@ -446,21 +538,22 @@ static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) switch (mode) { case 0x04: - speed = min(speed, (u8)XFER_UDMA_6); + speed = min_t(u8, speed, XFER_UDMA_6); break; case 0x03: - speed = min(speed, (u8)XFER_UDMA_5); - if (info->revision >= 5) + speed = min_t(u8, speed, XFER_UDMA_5); + if (chip_type >= HPT374) break; if (!check_in_drive_list(drive, bad_ata100_5)) goto check_bad_ata33; /* fall thru */ case 0x02: speed = min_t(u8, speed, XFER_UDMA_4); - /* - * CHECK ME, Does this need to be set to 5 ?? - */ - if (info->revision >= 3) + + /* + * CHECK ME, Does this need to be changed to HPT374 ?? + */ + if (chip_type >= HPT370) goto check_bad_ata33; if (HPT366_ALLOW_ATA66_4 && !check_in_drive_list(drive, bad_ata66_4)) @@ -475,7 +568,7 @@ static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) speed = min_t(u8, speed, XFER_UDMA_2); check_bad_ata33: - if (info->revision >= 4) + if (chip_type >= HPT370A) break; if (!check_in_drive_list(drive, bad_ata33)) break; @@ -488,7 +581,7 @@ static u8 hpt3xx_ratefilter(ide_drive_t *drive, u8 speed) return speed; } -static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table) +static u32 get_speed_setting(u8 speed, struct hpt_info *info) { int i; @@ -501,18 +594,23 @@ static u32 pci_bus_clock_list(u8 speed, u32 *chipset_table) for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++) if (xfer_speeds[i] == speed) break; - return chipset_table[i]; + /* + * NOTE: info->settings only points to the pointer + * to the list of the actual register values + */ + return (*info->settings)[i]; } static int hpt36x_tune_chipset(ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata (hwif); + struct hpt_info *info = pci_get_drvdata(dev); u8 speed = hpt3xx_ratefilter(drive, xferspeed); u8 itr_addr = drive->dn ? 0x44 : 0x40; - u32 itr_mask = (speed < XFER_MW_DMA_0) ? 0x30070000 : 0xc0000000; - u32 new_itr = pci_bus_clock_list(speed, info->speed); + u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 : + (speed < XFER_UDMA_0 ? 0xc0070000 : 0xc03800ff); + u32 new_itr = get_speed_setting(speed, info); u32 old_itr = 0; /* @@ -532,11 +630,12 @@ static int hpt37x_tune_chipset(ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata (hwif); + struct hpt_info *info = pci_get_drvdata(dev); u8 speed = hpt3xx_ratefilter(drive, xferspeed); u8 itr_addr = 0x40 + (drive->dn * 4); - u32 itr_mask = (speed < XFER_MW_DMA_0) ? 0x303c0000 : 0xc0000000; - u32 new_itr = pci_bus_clock_list(speed, info->speed); + u32 itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 : + (speed < XFER_UDMA_0 ? 0xc03c0000 : 0xc1c001ff); + u32 new_itr = get_speed_setting(speed, info); u32 old_itr = 0; pci_read_config_dword(dev, itr_addr, &old_itr); @@ -552,9 +651,9 @@ static int hpt37x_tune_chipset(ide_drive_t *drive, u8 xferspeed) static int hpt3xx_tune_chipset(ide_drive_t *drive, u8 speed) { ide_hwif_t *hwif = HWIF(drive); - struct hpt_info *info = ide_get_hwifdata(hwif); + struct hpt_info *info = pci_get_drvdata(hwif->pci_dev); - if (info->revision >= 3) + if (info->chip_type >= HPT370) return hpt37x_tune_chipset(drive, speed); else /* hpt368: hpt_minimum_revision(dev, 2) */ return hpt36x_tune_chipset(drive, speed); @@ -576,16 +675,10 @@ static void hpt3xx_tune_drive(ide_drive_t *drive, u8 pio) static int config_chipset_for_dma(ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, hpt3xx_ratemask(drive)); - ide_hwif_t *hwif = HWIF(drive); - struct hpt_info *info = ide_get_hwifdata(hwif); if (!speed) return 0; - /* If we don't have any timings we can't do a lot */ - if (info->speed == NULL) - return 0; - (void) hpt3xx_tune_chipset(drive, speed); return ide_dma_enable(drive); } @@ -615,10 +708,10 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); + struct hpt_info *info = pci_get_drvdata(dev); if (drive->quirk_list) { - if (info->revision >= 3) { + if (info->chip_type >= HPT370) { u8 scr1 = 0; pci_read_config_byte(dev, 0x5a, &scr1); @@ -778,40 +871,37 @@ static int hpt374_ide_dma_end(ide_drive_t *drive) * @mode: clocking mode (0x21 for write, 0x23 otherwise) * * Switch the DPLL clock on the HPT3xxN devices. This is a right mess. - * NOTE: avoid touching the disabled primary channel on HPT371N -- it - * doesn't physically exist anyway... */ static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) { - u8 mcr1, scr2 = hwif->INB(hwif->dma_master + 0x7b); + u8 scr2 = hwif->INB(hwif->dma_master + 0x7b); if ((scr2 & 0x7f) == mode) return; - /* MISC. control register 1 has the channel enable bit... */ - mcr1 = hwif->INB(hwif->dma_master + 0x70); - /* Tristate the bus */ - if (mcr1 & 0x04) - hwif->OUTB(0x80, hwif->dma_master + 0x73); + hwif->OUTB(0x80, hwif->dma_master + 0x73); hwif->OUTB(0x80, hwif->dma_master + 0x77); /* Switch clock and reset channels */ hwif->OUTB(mode, hwif->dma_master + 0x7b); hwif->OUTB(0xc0, hwif->dma_master + 0x79); - /* Reset state machines */ - if (mcr1 & 0x04) - hwif->OUTB(0x37, hwif->dma_master + 0x70); - hwif->OUTB(0x37, hwif->dma_master + 0x74); + /* + * Reset the state machines. + * NOTE: avoid accidentally enabling the disabled channels. + */ + hwif->OUTB(hwif->INB(hwif->dma_master + 0x70) | 0x32, + hwif->dma_master + 0x70); + hwif->OUTB(hwif->INB(hwif->dma_master + 0x74) | 0x32, + hwif->dma_master + 0x74); /* Complete reset */ hwif->OUTB(0x00, hwif->dma_master + 0x79); /* Reconnect channels to bus */ - if (mcr1 & 0x04) - hwif->OUTB(0x00, hwif->dma_master + 0x73); + hwif->OUTB(0x00, hwif->dma_master + 0x73); hwif->OUTB(0x00, hwif->dma_master + 0x77); } @@ -826,10 +916,7 @@ static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode) static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq) { - ide_hwif_t *hwif = HWIF(drive); - u8 wantclock = rq_data_dir(rq) ? 0x23 : 0x21; - - hpt3xxn_set_clock(hwif, wantclock); + hpt3xxn_set_clock(HWIF(drive), rq_data_dir(rq) ? 0x23 : 0x21); } /* @@ -890,223 +977,293 @@ static int hpt3xx_busproc(ide_drive_t *drive, int state) return 0; } -static void __devinit hpt366_clocking(ide_hwif_t *hwif) +/** + * hpt37x_calibrate_dpll - calibrate the DPLL + * @dev: PCI device + * + * Perform a calibration cycle on the DPLL. + * Returns 1 if this succeeds + */ +static int __devinit hpt37x_calibrate_dpll(struct pci_dev *dev, u16 f_low, u16 f_high) { - u32 itr1 = 0; - struct hpt_info *info = ide_get_hwifdata(hwif); + u32 dpll = (f_high << 16) | f_low | 0x100; + u8 scr2; + int i; - pci_read_config_dword(hwif->pci_dev, 0x40, &itr1); + pci_write_config_dword(dev, 0x5c, dpll); - /* detect bus speed by looking at control reg timing: */ - switch((itr1 >> 8) & 7) { - case 5: - info->speed = forty_base_hpt36x; - break; - case 9: - info->speed = twenty_five_base_hpt36x; - break; - case 7: - default: - info->speed = thirty_three_base_hpt36x; + /* Wait for oscillator ready */ + for(i = 0; i < 0x5000; ++i) { + udelay(50); + pci_read_config_byte(dev, 0x5b, &scr2); + if (scr2 & 0x80) break; } + /* See if it stays ready (we'll just bail out if it's not yet) */ + for(i = 0; i < 0x1000; ++i) { + pci_read_config_byte(dev, 0x5b, &scr2); + /* DPLL destabilized? */ + if(!(scr2 & 0x80)) + return 0; + } + /* Turn off tuning, we have the DPLL set */ + pci_read_config_dword (dev, 0x5c, &dpll); + pci_write_config_dword(dev, 0x5c, (dpll & ~0x100)); + return 1; } -static void __devinit hpt37x_clocking(ide_hwif_t *hwif) +static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name) { - struct hpt_info *info = ide_get_hwifdata(hwif); - struct pci_dev *dev = hwif->pci_dev; - char *name = hwif->cds->name; - int adjust, i; - u16 freq = 0; - u32 pll, temp = 0; - u8 scr2 = 0, mcr1 = 0; - + struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL); + unsigned long io_base = pci_resource_start(dev, 4); + u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */ + enum ata_clock clock; + + if (info == NULL) { + printk(KERN_ERR "%s: out of memory!\n", name); + return -ENOMEM; + } + /* - * default to pci clock. make sure MA15/16 are set to output - * to prevent drives having problems with 40-pin cables. Needed - * for some drives such as IBM-DTLA which will not enter ready - * state on reset when PDIAG is a input. - * - * ToDo: should we set 0x21 when using PLL mode ? + * Copy everything from a static "template" structure + * to just allocated per-chip hpt_info structure. */ - pci_write_config_byte(dev, 0x5b, 0x23); + *info = *(struct hpt_info *)pci_get_drvdata(dev); /* - * We'll have to read f_CNT value in order to determine - * the PCI clock frequency according to the following ratio: - * - * f_CNT = Fpci * 192 / Fdpll - * - * First try reading the register in which the HighPoint BIOS - * saves f_CNT value before reprogramming the DPLL from its - * default setting (which differs for the various chips). - * NOTE: This register is only accessible via I/O space. - * - * In case the signature check fails, we'll have to resort to - * reading the f_CNT register itself in hopes that nobody has - * touched the DPLL yet... + * FIXME: Not portable. Also, why do we enable the ROM in the first place? + * We don't seem to be using it. */ - temp = inl(pci_resource_start(dev, 4) + 0x90); - if ((temp & 0xFFFFF000) != 0xABCDE000) { - printk(KERN_WARNING "%s: no clock data saved by BIOS\n", name); - - /* Calculate the average value of f_CNT */ - for (temp = i = 0; i < 128; i++) { - pci_read_config_word(dev, 0x78, &freq); - temp += freq & 0x1ff; - mdelay(1); - } - freq = temp / 128; - } else - freq = temp & 0x1ff; + 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); + + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); + pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); + pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); /* - * HPT3xxN chips use different PCI clock information. - * Currently we always set up the PLL for them. + * First, try to estimate the PCI clock frequency... */ + if (info->chip_type >= HPT370) { + u8 scr1 = 0; + u16 f_cnt = 0; + u32 temp = 0; + + /* Interrupt force enable. */ + pci_read_config_byte(dev, 0x5a, &scr1); + if (scr1 & 0x10) + pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); + + /* + * HighPoint does this for HPT372A. + * NOTE: This register is only writeable via I/O space. + */ + if (info->chip_type == HPT372A) + outb(0x0e, io_base + 0x9c); + + /* + * Default to PCI clock. Make sure MA15/16 are set to output + * to prevent drives having problems with 40-pin cables. + */ + pci_write_config_byte(dev, 0x5b, 0x23); - if (info->flags & IS_3xxN) { - if(freq < 0x55) - pll = F_LOW_PCI_33; - else if(freq < 0x70) - pll = F_LOW_PCI_40; - else if(freq < 0x7F) - pll = F_LOW_PCI_50; + /* + * We'll have to read f_CNT value in order to determine + * the PCI clock frequency according to the following ratio: + * + * f_CNT = Fpci * 192 / Fdpll + * + * First try reading the register in which the HighPoint BIOS + * saves f_CNT value before reprogramming the DPLL from its + * default setting (which differs for the various chips). + * NOTE: This register is only accessible via I/O space. + * + * In case the signature check fails, we'll have to resort to + * reading the f_CNT register itself in hopes that nobody has + * touched the DPLL yet... + */ + temp = inl(io_base + 0x90); + if ((temp & 0xFFFFF000) != 0xABCDE000) { + int i; + + printk(KERN_WARNING "%s: no clock data saved by BIOS\n", + name); + + /* Calculate the average value of f_CNT. */ + for (temp = i = 0; i < 128; i++) { + pci_read_config_word(dev, 0x78, &f_cnt); + temp += f_cnt & 0x1ff; + mdelay(1); + } + f_cnt = temp / 128; + } else + f_cnt = temp & 0x1ff; + + dpll_clk = info->dpll_clk; + pci_clk = (f_cnt * dpll_clk) / 192; + + /* Clamp PCI clock to bands. */ + if (pci_clk < 40) + pci_clk = 33; + else if(pci_clk < 45) + pci_clk = 40; + else if(pci_clk < 55) + pci_clk = 50; else - pll = F_LOW_PCI_66; + pci_clk = 66; + printk(KERN_INFO "%s: DPLL base: %d MHz, f_CNT: %d, " + "assuming %d MHz PCI\n", name, dpll_clk, f_cnt, pci_clk); } else { - if(freq < 0x9C) - pll = F_LOW_PCI_33; - else if(freq < 0xb0) - pll = F_LOW_PCI_40; - else if(freq <0xc8) - pll = F_LOW_PCI_50; - else - pll = F_LOW_PCI_66; - } - printk(KERN_INFO "%s: FREQ: %d, PLL: %d\n", name, freq, pll); - - if (!(info->flags & IS_3xxN)) { - if (pll == F_LOW_PCI_33) { - info->speed = thirty_three_base_hpt37x; - printk(KERN_DEBUG "%s: using 33MHz PCI clock\n", name); - } else if (pll == F_LOW_PCI_40) { - /* Unsupported */ - } else if (pll == F_LOW_PCI_50) { - info->speed = fifty_base_hpt37x; - printk(KERN_DEBUG "%s: using 50MHz PCI clock\n", name); - } else { - info->speed = sixty_six_base_hpt37x; - printk(KERN_DEBUG "%s: using 66MHz PCI clock\n", name); + u32 itr1 = 0; + + pci_read_config_dword(dev, 0x40, &itr1); + + /* Detect PCI clock by looking at cmd_high_time. */ + switch((itr1 >> 8) & 0x07) { + case 0x09: + pci_clk = 40; + case 0x05: + pci_clk = 25; + case 0x07: + default: + pci_clk = 33; } } - if (pll == F_LOW_PCI_66) - info->flags |= PCI_66MHZ; + /* Let's assume we'll use PCI clock for the ATA clock... */ + switch (pci_clk) { + case 25: + clock = ATA_CLOCK_25MHZ; + break; + case 33: + default: + clock = ATA_CLOCK_33MHZ; + break; + case 40: + clock = ATA_CLOCK_40MHZ; + break; + case 50: + clock = ATA_CLOCK_50MHZ; + break; + case 66: + clock = ATA_CLOCK_66MHZ; + break; + } /* - * only try the pll if we don't have a table for the clock - * speed that we're running at. NOTE: the internal PLL will - * result in slow reads when using a 33MHz PCI clock. we also - * don't like to use the PLL because it will cause glitches - * on PRST/SRST when the HPT state engine gets reset. + * Only try the DPLL if we don't have a table for the PCI clock that + * we are running at for HPT370/A, always use it for anything newer... * - * ToDo: Use 66MHz PLL when ATA133 devices are present on a - * 372 device so we can get ATA133 support + * NOTE: Using the internal DPLL results in slow reads on 33 MHz PCI. + * We also don't like using the DPLL because this causes glitches + * on PRST-/SRST- when the state engine gets reset... */ - if (info->speed) - goto init_hpt37X_done; + if (info->chip_type >= HPT374 || info->settings[clock] == NULL) { + u16 f_low, delta = pci_clk < 50 ? 2 : 4; + int adjust; + + /* + * Select 66 MHz DPLL clock only if UltraATA/133 mode is + * supported/enabled, use 50 MHz DPLL clock otherwise... + */ + if (info->max_mode == 0x04) { + dpll_clk = 66; + clock = ATA_CLOCK_66MHZ; + } else if (dpll_clk) { /* HPT36x chips don't have DPLL */ + dpll_clk = 50; + clock = ATA_CLOCK_50MHZ; + } - info->flags |= PLL_MODE; - - /* - * Adjust the PLL based upon the PCI clock, enable it, and - * wait for stabilization... - */ - adjust = 0; - freq = (pll < F_LOW_PCI_50) ? 2 : 4; - while (adjust++ < 6) { - pci_write_config_dword(dev, 0x5c, (freq + pll) << 16 | - pll | 0x100); - - /* wait for clock stabilization */ - for (i = 0; i < 0x50000; i++) { - pci_read_config_byte(dev, 0x5b, &scr2); - if (scr2 & 0x80) { - /* spin looking for the clock to destabilize */ - for (i = 0; i < 0x1000; ++i) { - pci_read_config_byte(dev, 0x5b, - &scr2); - if ((scr2 & 0x80) == 0) - goto pll_recal; - } - pci_read_config_dword(dev, 0x5c, &pll); - pci_write_config_dword(dev, 0x5c, - pll & ~0x100); - pci_write_config_byte(dev, 0x5b, 0x21); - - info->speed = fifty_base_hpt37x; - printk("%s: using 50MHz internal PLL\n", name); - goto init_hpt37X_done; - } + if (info->settings[clock] == NULL) { + printk(KERN_ERR "%s: unknown bus timing!\n", name); + kfree(info); + return -EIO; } -pll_recal: - if (adjust & 1) - pll -= (adjust >> 1); - else - pll += (adjust >> 1); - } -init_hpt37X_done: - if (!info->speed) - printk(KERN_ERR "%s: unknown bus timing [%d %d].\n", - name, pll, freq); - /* - * Reset the state engines. - * NOTE: avoid accidentally enabling the primary channel on HPT371N. - */ - pci_read_config_byte(dev, 0x50, &mcr1); - if (mcr1 & 0x04) - pci_write_config_byte(dev, 0x50, 0x37); - pci_write_config_byte(dev, 0x54, 0x37); - udelay(100); -} + /* Select the DPLL clock. */ + pci_write_config_byte(dev, 0x5b, 0x21); + + /* + * Adjust the DPLL based upon PCI clock, enable it, + * and wait for stabilization... + */ + f_low = (pci_clk * 48) / dpll_clk; + + for (adjust = 0; adjust < 8; adjust++) { + if(hpt37x_calibrate_dpll(dev, f_low, f_low + delta)) + break; + + /* + * See if it'll settle at a fractionally different clock + */ + if (adjust & 1) + f_low -= adjust >> 1; + else + f_low += adjust >> 1; + } + if (adjust == 8) { + printk(KERN_ERR "%s: DPLL did not stabilize!\n", name); + kfree(info); + return -EIO; + } + + printk("%s: using %d MHz DPLL clock\n", name, dpll_clk); + } else { + /* Mark the fact that we're not using the DPLL. */ + dpll_clk = 0; + + printk("%s: using %d MHz PCI clock\n", name, pci_clk); + } -static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const char *name) -{ /* - * FIXME: Not portable. Also, why do we enable the ROM in the first place? - * We don't seem to be using it. + * Advance the table pointer to a slot which points to the list + * of the register values settings matching the clock being used. */ - 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); + info->settings += clock; - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); - pci_write_config_byte(dev, PCI_MIN_GNT, 0x08); - pci_write_config_byte(dev, PCI_MAX_LAT, 0x08); + /* Store the clock frequencies. */ + info->dpll_clk = dpll_clk; + info->pci_clk = pci_clk; - if (hpt_revision(dev) >= 3) { - u8 scr1 = 0; + /* Point to this chip's own instance of the hpt_info structure. */ + pci_set_drvdata(dev, info); - /* Interrupt force enable. */ - pci_read_config_byte(dev, 0x5a, &scr1); - if (scr1 & 0x10) - pci_write_config_byte(dev, 0x5a, scr1 & ~0x10); + if (info->chip_type >= HPT370) { + u8 mcr1, mcr4; + + /* + * Reset the state engines. + * NOTE: Avoid accidentally enabling the disabled channels. + */ + pci_read_config_byte (dev, 0x50, &mcr1); + pci_read_config_byte (dev, 0x54, &mcr4); + pci_write_config_byte(dev, 0x50, (mcr1 | 0x32)); + pci_write_config_byte(dev, 0x54, (mcr4 | 0x32)); + udelay(100); } + /* + * On HPT371N, if ATA clock is 66 MHz we must set bit 2 in + * the MISC. register to stretch the UltraDMA Tss timing. + * NOTE: This register is only writeable via I/O space. + */ + if (info->chip_type == HPT371N && clock == ATA_CLOCK_66MHZ) + + outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c); + return dev->irq; } static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); + struct hpt_info *info = pci_get_drvdata(dev); int serialize = HPT_SERIALIZE_IO; u8 scr1 = 0, ata66 = (hwif->channel) ? 0x01 : 0x02; + u8 chip_type = info->chip_type; u8 new_mcr, old_mcr = 0; /* Cache the channel's MISC. control registers' offset */ @@ -1125,7 +1282,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) * - on 33 MHz PCI we must clock switch * - on 66 MHz PCI we must NOT use the PCI clock */ - if ((info->flags & (IS_3xxN | PCI_66MHZ)) == IS_3xxN) { + if (chip_type >= HPT372N && info->dpll_clk && info->pci_clk < 66) { /* * Clock is shared between the channels, * so we'll have to serialize them... :-( @@ -1144,9 +1301,9 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) */ pci_read_config_byte(dev, hwif->select_data + 1, &old_mcr); - if (info->revision >= 5) /* HPT372 and newer */ + if (info->chip_type >= HPT374) new_mcr = old_mcr & ~0x07; - else if (info->revision >= 3) { /* HPT370 and HPT370A */ + else if (info->chip_type >= HPT370) { new_mcr = old_mcr; new_mcr &= ~0x02; @@ -1174,7 +1331,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) * address lines to access an external EEPROM. To read valid * cable detect state the pins must be enabled as inputs. */ - if (info->revision >= 8 && (PCI_FUNC(dev->devfn) & 1)) { + if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) { /* * HPT374 PCI function 1 * - set bit 15 of reg 0x52 to enable TCBLID as input @@ -1188,7 +1345,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) /* now read cable id register */ pci_read_config_byte (dev, 0x5a, &scr1); pci_write_config_word(dev, mcr_addr, mcr); - } else if (info->revision >= 3) { + } else if (chip_type >= HPT370) { /* * HPT370/372 and 374 pcifn 0 * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs @@ -1208,10 +1365,10 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) hwif->ide_dma_check = &hpt366_config_drive_xfer_rate; - if (info->revision >= 5) { + if (chip_type >= HPT374) { hwif->ide_dma_test_irq = &hpt374_ide_dma_test_irq; hwif->ide_dma_end = &hpt374_ide_dma_end; - } else if (info->revision >= 3) { + } else if (chip_type >= HPT370) { hwif->dma_start = &hpt370_ide_dma_start; hwif->ide_dma_end = &hpt370_ide_dma_end; hwif->ide_dma_timeout = &hpt370_ide_dma_timeout; @@ -1226,7 +1383,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) { struct pci_dev *dev = hwif->pci_dev; - struct hpt_info *info = ide_get_hwifdata(hwif); u8 masterdma = 0, slavedma = 0; u8 dma_new = 0, dma_old = 0; unsigned long flags; @@ -1234,12 +1390,6 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) if (!dmabase) return; - if(info->speed == NULL) { - printk(KERN_WARNING "%s: no known IDE timings, disabling DMA.\n", - hwif->cds->name); - return; - } - dma_old = hwif->INB(dmabase + 2); local_irq_save(flags); @@ -1258,60 +1408,6 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) ide_setup_dma(hwif, dmabase, 8); } -/* - * We "borrow" this hook in order to set the data structures - * up early enough before dma or init_hwif calls are made. - */ - -static void __devinit init_iops_hpt366(ide_hwif_t *hwif) -{ - struct hpt_info *info = kzalloc(sizeof(struct hpt_info), GFP_KERNEL); - struct pci_dev *dev = hwif->pci_dev; - u16 did = dev->device; - u8 mode, rid = 0; - - if(info == NULL) { - printk(KERN_WARNING "%s: out of memory.\n", hwif->cds->name); - return; - } - ide_set_hwifdata(hwif, info); - - /* Avoid doing the same thing twice. */ - if (hwif->channel && hwif->mate) { - memcpy(info, ide_get_hwifdata(hwif->mate), sizeof(struct hpt_info)); - return; - } - - pci_read_config_byte(dev, PCI_REVISION_ID, &rid); - - if (( did == PCI_DEVICE_ID_TTI_HPT366 && rid == 6) || - ((did == PCI_DEVICE_ID_TTI_HPT372 || - did == PCI_DEVICE_ID_TTI_HPT302 || - did == PCI_DEVICE_ID_TTI_HPT371) && rid > 1) || - did == PCI_DEVICE_ID_TTI_HPT372N) - info->flags |= IS_3xxN; - - rid = info->revision = hpt_revision(dev); - if (rid >= 8) /* HPT374 */ - mode = HPT374_ALLOW_ATA133_6 ? 4 : 3; - else if (rid >= 7) /* HPT371 and HPT371N */ - mode = HPT371_ALLOW_ATA133_6 ? 4 : 3; - else if (rid >= 6) /* HPT302 and HPT302N */ - mode = HPT302_ALLOW_ATA133_6 ? 4 : 3; - else if (rid >= 5) /* HPT372, HPT372A, and HPT372N */ - mode = HPT372_ALLOW_ATA133_6 ? 4 : 3; - else if (rid >= 3) /* HPT370 and HPT370A */ - mode = HPT370_ALLOW_ATA100_5 ? 3 : 2; - else /* HPT366 and HPT368 */ - mode = (HPT366_ALLOW_ATA66_4 || HPT366_ALLOW_ATA66_3) ? 2 : 1; - info->max_mode = mode; - - if (rid >= 3) - hpt37x_clocking(hwif); - else - hpt366_clocking(hwif); -} - static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d) { struct pci_dev *dev2; @@ -1319,9 +1415,13 @@ static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d) if (PCI_FUNC(dev->devfn) & 1) return -ENODEV; + pci_set_drvdata(dev, &hpt374); + if ((dev2 = pci_get_slot(dev->bus, dev->devfn + 1)) != NULL) { int ret; + pci_set_drvdata(dev2, &hpt374); + if (dev2->irq != dev->irq) { /* FIXME: we need a core pci_set_interrupt() */ dev2->irq = dev->irq; @@ -1338,18 +1438,25 @@ static int __devinit init_setup_hpt374(struct pci_dev *dev, ide_pci_device_t *d) static int __devinit init_setup_hpt372n(struct pci_dev *dev, ide_pci_device_t *d) { + pci_set_drvdata(dev, &hpt372n); + return ide_setup_pci_device(dev, d); } static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) { + struct hpt_info *info; u8 rev = 0, mcr1 = 0; pci_read_config_byte(dev, PCI_REVISION_ID, &rev); - if (rev > 1) + if (rev > 1) { d->name = "HPT371N"; + info = &hpt371n; + } else + info = &hpt371; + /* * HPT371 chips physically have only one channel, the secondary one, * but the primary channel registers do exist! Go figure... @@ -1360,30 +1467,44 @@ static int __devinit init_setup_hpt371(struct pci_dev *dev, ide_pci_device_t *d) if (mcr1 & 0x04) pci_write_config_byte(dev, 0x50, mcr1 & ~0x04); + pci_set_drvdata(dev, info); + return ide_setup_pci_device(dev, d); } static int __devinit init_setup_hpt372a(struct pci_dev *dev, ide_pci_device_t *d) { + struct hpt_info *info; u8 rev = 0; pci_read_config_byte(dev, PCI_REVISION_ID, &rev); - if (rev > 1) + if (rev > 1) { d->name = "HPT372N"; + info = &hpt372n; + } else + info = &hpt372a; + pci_set_drvdata(dev, info); + return ide_setup_pci_device(dev, d); } static int __devinit init_setup_hpt302(struct pci_dev *dev, ide_pci_device_t *d) { + struct hpt_info *info; u8 rev = 0; pci_read_config_byte(dev, PCI_REVISION_ID, &rev); - if (rev > 1) + if (rev > 1) { d->name = "HPT302N"; + info = &hpt302n; + } else + info = &hpt302; + pci_set_drvdata(dev, info); + return ide_setup_pci_device(dev, d); } @@ -1394,6 +1515,9 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) static char *chipset_names[] = { "HPT366", "HPT366", "HPT368", "HPT370", "HPT370A", "HPT372", "HPT372N" }; + static struct hpt_info *info[] = { &hpt36x, &hpt36x, &hpt36x, + &hpt370, &hpt370a, &hpt372, + &hpt372n }; if (PCI_FUNC(dev->devfn) & 1) return -ENODEV; @@ -1405,6 +1529,8 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) d->name = chipset_names[rev]; + pci_set_drvdata(dev, info[rev]); + if (rev > 2) goto init_single; @@ -1414,6 +1540,8 @@ static int __devinit init_setup_hpt366(struct pci_dev *dev, ide_pci_device_t *d) u8 pin1 = 0, pin2 = 0; int ret; + pci_set_drvdata(dev2, info[rev]); + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2); if (pin1 != pin2 && dev->irq == dev2->irq) { @@ -1435,40 +1563,39 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .name = "HPT366", .init_setup = init_setup_hpt366, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, + .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, .extra = 240 },{ /* 1 */ .name = "HPT372A", .init_setup = init_setup_hpt372a, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, + .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, .extra = 240 },{ /* 2 */ .name = "HPT302", .init_setup = init_setup_hpt302, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, .autodma = AUTODMA, + .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, .extra = 240 },{ /* 3 */ .name = "HPT371", .init_setup = init_setup_hpt371, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, @@ -1480,22 +1607,22 @@ static ide_pci_device_t hpt366_chipsets[] __devinitdata = { .name = "HPT374", .init_setup = init_setup_hpt374, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, /* 4 */ .autodma = AUTODMA, + .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, .extra = 240 },{ /* 5 */ .name = "HPT372N", .init_setup = init_setup_hpt372n, .init_chipset = init_chipset_hpt366, - .init_iops = init_iops_hpt366, .init_hwif = init_hwif_hpt366, .init_dma = init_dma_hpt366, .channels = 2, /* 4 */ .autodma = AUTODMA, + .enablebits = {{0x50,0x04,0x04}, {0x54,0x04,0x04}}, .bootable = OFF_BOARD, .extra = 240 } -- cgit v1.2.3 From 6273d26a5b280cb96b804424de323560b301ca51 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:18:20 +0100 Subject: hpt366: HPT36x PCI clock detection fix Fix minor coding mistake in the HPT36x PCI clock detection code noticed by Bartlomiej Zolnierkiewicz -- it always reported 33 MHz due to the missing 'break' statements. This, however, most probably never mattered -- in fact, I was thinking of removing the 25/40 MHz cases completely since HPT36x BIOSes didn't seem to set any other value than 7 into the 'cmd_high_time' field, i.e. supported only 33 MHz PCI. Note that in the original driver there was another bug: 25 and 40 MHz cases were interchanged. Since the 'cmd_high_time' field is in units of PCI clocks, a lower clock count just *cannot* correspond to a higher frequency, i. e. it should be 5 for 25 MHz PCI and 9 for 40 MHz PCI, not the other way around. Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/hpt366.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 4350e337136..05be8fadda7 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/hpt366.c Version 1.00 Jun 25, 2006 + * linux/drivers/ide/pci/hpt366.c Version 1.01 Dec 23, 2006 * * Copyright (C) 1999-2003 Andre Hedrick * Portions Copyright (C) 2001 Sun Microsystems, Inc. @@ -107,7 +107,8 @@ * frequency * - switch to using the DPLL clock and enable UltraATA/133 mode by default on * anything newer than HPT370/A - * - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(); + * - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(), + * also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips; * unify HPT36x/37x timing setup code and the speedproc handlers by joining * the register setting lists into the table indexed by the clock selected * Sergei Shtylyov, or @@ -1125,11 +1126,14 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha switch((itr1 >> 8) & 0x07) { case 0x09: pci_clk = 40; + break; case 0x05: pci_clk = 25; + break; case 0x07: default: pci_clk = 33; + break; } } -- cgit v1.2.3 From d2872239737ad6394b49c7c9ce9ae8d0f07165e5 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:18:25 +0100 Subject: piix: fix 82371MX enablebits According to the datasheet, Intel 82371MX (MPIIX) actually has only a single IDE channel mapped to the primary or secondary ports depending on the value of the bit 14 of the IDETIM register at PCI config. offset 0x6C (the register at 0x6F which the driver refers to. doesn't exist). So, disguise the controller as dual channel and set enablebits masks/values such that only either primary or secondary channel is detected enabled. Also, preclude the IDE probing code from reading PCI BARs, this controller just doesn't have them (it's not the separate PCI function like the other PCI controllers), it only decodes the legacy addresses. [ Alan sayeth " MPIIX does not work with or without the change. It needs its own different driver and not to use setup-pci. Huge job and since it works well with libata who cares. Ditto the early PIIX chip." ] Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/piix.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index edb37f3d558..236d8fd4e72 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -539,13 +539,19 @@ static ide_pci_device_t piix_pci_info[] __devinitdata = { /* 0 */ DECLARE_PIIX_DEV("PIIXa"), /* 1 */ DECLARE_PIIX_DEV("PIIXb"), - { /* 2 */ + /* 2 */ + { /* + * MPIIX actually has only a single IDE channel mapped to + * the primary or secondary ports depending on the value + * of the bit 14 of the IDETIM register at offset 0x6c + */ .name = "MPIIX", .init_hwif = init_hwif_piix, .channels = 2, .autodma = NODMA, - .enablebits = {{0x6D,0x80,0x80}, {0x6F,0x80,0x80}}, + .enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}}, .bootable = ON_BOARD, + .flags = IDEPCI_FLAG_ISA_PORTS }, /* 3 */ DECLARE_PIIX_DEV("PIIX3"), -- cgit v1.2.3 From 30dfd12f5384d30c0d0de05eb34d0e26352a20ff Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:18:28 +0100 Subject: piix: tuneproc() fixes/cleanups Fix/cleanup the driver's tuneproc() and ratemask() methods: - PPE, IE, and TIME bits need to be cleared beforehand for the slave drive as well as master (Alan probably just forgot about it); - this driver only supports PIO modes up to 4, so must pass the correct limit to ide_get_best_pio_mode(); - use min_t() macro instead of min(); - simplify slave vs master drive evaluation; - do come coding and formatting cleanups... Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/piix.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index 236d8fd4e72..52cfc2ac22c 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/piix.c Version 0.45 May 12, 2006 + * linux/drivers/ide/pci/piix.c Version 0.46 December 3, 2006 * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick @@ -163,7 +163,7 @@ static u8 piix_ratemask (ide_drive_t *drive) * if the drive cannot see an 80pin cable. */ if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); + mode = min_t(u8, mode, 1); return mode; } @@ -216,7 +216,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - int is_slave = (&hwif->drives[1] == drive); + int is_slave = drive->dn & 1; int master_port = hwif->channel ? 0x42 : 0x40; int slave_port = 0x44; unsigned long flags; @@ -225,7 +225,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) static DEFINE_SPINLOCK(tune_lock); int control = 0; - /* ISP RTC */ + /* ISP RTC */ static const u8 timings[][2]= { { 0, 0 }, { 0, 0 }, @@ -233,7 +233,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) { 2, 1 }, { 2, 3 }, }; - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); /* * Master vs slave is synchronized above us but the slave register is @@ -243,25 +243,24 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio) spin_lock_irqsave(&tune_lock, flags); pci_read_config_word(dev, master_port, &master_data); - if (pio >= 2) + if (pio > 1) control |= 1; /* Programmable timing on */ if (drive->media == ide_disk) control |= 4; /* Prefetch, post write */ - if (pio >= 3) + if (pio > 2) control |= 2; /* IORDY */ if (is_slave) { - master_data = master_data | 0x4000; + master_data |= 0x4000; + master_data &= ~0x0070; if (pio > 1) { /* enable PPE, IE and TIME */ master_data = master_data | (control << 4); - } else { - master_data &= ~0x0070; } pci_read_config_byte(dev, slave_port, &slave_data); slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); } else { - master_data = master_data & 0xccf8; + master_data &= ~0x3307; if (pio > 1) { /* enable PPE, IE and TIME */ master_data = master_data | control; -- cgit v1.2.3 From 24e6458d9c0c445141488b70e1a01fa31ed86c8d Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:18:34 +0100 Subject: slc90e66: carry over fixes from piix driver Synchronize with version 0.46 of the Intel PIIX/ICH driver: - carry over Alan's and my own fixes in the tuneproc() method and my cleanups both there and in the ratemask() method; - SLC90E66 only supports MW DMA modes 1/2 and SW DMA mode 2 (just like Intel chips), so don't claim support for other MW/SW DMA modes; - don't check dor non-NULL drive->id in the ide_dma_check() method -- this is assumed to be true in all other drivers; - do some coding/formatting cleanups while at it... Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/slc90e66.c | 55 ++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 21 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c index 90e79c0844d..2663ddbd9b6 100644 --- a/drivers/ide/pci/slc90e66.c +++ b/drivers/ide/pci/slc90e66.c @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/slc90e66.c Version 0.12 May 12, 2006 + * linux/drivers/ide/pci/slc90e66.c Version 0.13 December 30, 2006 * * Copyright (C) 2000-2002 Andre Hedrick * Copyright (C) 2006 MontaVista Software, Inc. @@ -26,7 +26,7 @@ static u8 slc90e66_ratemask (ide_drive_t *drive) u8 mode = 2; if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); + mode = min_t(u8, mode, 1); return mode; } @@ -65,36 +65,47 @@ static void slc90e66_tune_drive (ide_drive_t *drive, u8 pio) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - int is_slave = (&hwif->drives[1] == drive); + int is_slave = drive->dn & 1; int master_port = hwif->channel ? 0x42 : 0x40; int slave_port = 0x44; unsigned long flags; u16 master_data; u8 slave_data; - /* ISP RTC */ + int control = 0; + /* ISP RTC */ static const u8 timings[][2]= { - { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; + { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); spin_lock_irqsave(&ide_lock, flags); pci_read_config_word(dev, master_port, &master_data); + + if (pio > 1) + control |= 1; /* Programmable timing on */ + if (drive->media == ide_disk) + control |= 4; /* Prefetch, post write */ + if (pio > 2) + control |= 2; /* IORDY */ if (is_slave) { - master_data = master_data | 0x4000; - if (pio > 1) + master_data |= 0x4000; + master_data &= ~0x0070; + if (pio > 1) { /* enable PPE, IE and TIME */ - master_data = master_data | 0x0070; + master_data = master_data | (control << 4); + } pci_read_config_byte(dev, slave_port, &slave_data); slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0); slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0)); } else { - master_data = master_data & 0xccf8; - if (pio > 1) + master_data &= ~0x3307; + if (pio > 1) { /* enable PPE, IE and TIME */ - master_data = master_data | 0x0007; + master_data = master_data | control; + } master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); } pci_write_config_word(dev, master_port, master_data); @@ -173,7 +184,7 @@ static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive) drive->init_speed = 0; - if (id && (id->capability & 1) && drive->autodma) { + if ((id->capability & 1) && drive->autodma) { if (ide_use_dma(drive) && slc90e66_config_drive_for_dma(drive)) return hwif->ide_dma_on(drive); @@ -201,7 +212,7 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) hwif->irq = hwif->channel ? 15 : 14; hwif->speedproc = &slc90e66_tune_chipset; - hwif->tuneproc = &slc90e66_tune_drive; + hwif->tuneproc = &slc90e66_tune_drive; pci_read_config_byte(hwif->pci_dev, 0x47, ®47); @@ -213,14 +224,16 @@ static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif) hwif->atapi_dma = 1; hwif->ultra_mask = 0x1f; - hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x07; + hwif->mwdma_mask = 0x06; + hwif->swdma_mask = 0x04; - if (!(hwif->udma_four)) + if (!hwif->udma_four) { /* bit[0(1)]: 0:80, 1:40 */ hwif->udma_four = (reg47 & mask) ? 0 : 1; + } hwif->ide_dma_check = &slc90e66_config_drive_xfer_rate; + if (!noautodma) hwif->autodma = 1; hwif->drives[0].autodma = hwif->autodma; -- cgit v1.2.3 From 272103144ac1ff937ed22917e1de05da4d6943dd Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:18:37 +0100 Subject: pdc202xx_new: remove useless code Remove the following useless fragments from the driver: - the ide_dma_lostirq() and ide_dma_timeout() handlers which boil down to just printing the incoherent reset message and calling their default counterparts; - check for non-NULL drive->id in the ide_dma_check() handler -- this is assumed to be true by all other handlers (also, get rid of unnecessary nesting of the conditional statements there); - the comment before pdcnew_tune_drive() which has nothing to do with the code. Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/pdc202xx_new.c | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 77a9aaa7dab..fc2a45bb965 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -249,13 +249,6 @@ static int pdcnew_tune_chipset(ide_drive_t *drive, u8 speed) return err; } -/* 0 1 2 3 4 5 6 7 8 - * 960, 480, 390, 300, 240, 180, 120, 90, 60 - * 180, 150, 120, 90, 60 - * DMA_Speed - * 180, 120, 90, 90, 90, 60, 30 - * 11, 5, 4, 3, 2, 1, 0 - */ static void pdcnew_tune_drive(ide_drive_t *drive, u8 pio) { pio = ide_get_best_pio_mode(drive, pio, 4, NULL); @@ -313,12 +306,10 @@ static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive) drive->init_speed = 0; - if (id && (id->capability & 1) && drive->autodma) { + if ((id->capability & 1) && drive->autodma) { - if (ide_use_dma(drive)) { - if (config_chipset_for_dma(drive)) - return hwif->ide_dma_on(drive); - } + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); goto fast_ata_pio; @@ -336,20 +327,6 @@ static int pdcnew_quirkproc(ide_drive_t *drive) return check_in_drive_lists(drive, pdc_quirk_drives); } -static int pdcnew_ide_dma_lostirq(ide_drive_t *drive) -{ - if (HWIF(drive)->resetproc != NULL) - HWIF(drive)->resetproc(drive); - return __ide_dma_lostirq(drive); -} - -static int pdcnew_ide_dma_timeout(ide_drive_t *drive) -{ - if (HWIF(drive)->resetproc != NULL) - HWIF(drive)->resetproc(drive); - return __ide_dma_timeout(drive); -} - static void pdcnew_reset(ide_drive_t *drive) { /* @@ -599,8 +576,6 @@ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif) hwif->err_stops_fifo = 1; hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate; - hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq; - hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout; if (!hwif->udma_four) hwif->udma_four = pdcnew_cable_detect(hwif) ? 0 : 1; -- cgit v1.2.3 From d24ec426b3be3a011bc8568d53fea486b604a684 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:18:39 +0100 Subject: pdc202xx_new: remove check_in_drive_lists abomination Fold check_in_drive_lists() into quirkproc() handler in both PDC202xx drivers-- this function was never called with a list other than pdc_quirk_drives and was a bad example of code overall... Signed-off-by: Sergei Shtylyov Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/pdc202xx_new.c | 27 ++++++--------------------- drivers/ide/pci/pdc202xx_old.c | 27 ++++++--------------------- 2 files changed, 12 insertions(+), 42 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index fc2a45bb965..236a03144a2 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -92,26 +92,6 @@ static u8 pdcnew_ratemask(ide_drive_t *drive) return mode; } -static int check_in_drive_lists(ide_drive_t *drive, const char **list) -{ - struct hd_driveid *id = drive->id; - - if (pdc_quirk_drives == list) { - while (*list) { - if (strstr(id->model, *list++)) { - return 2; - } - } - } else { - while (*list) { - if (!strcmp(*list++,id->model)) { - return 1; - } - } - } - return 0; -} - /** * get_indexed_reg - Get indexed register * @hwif: for the port address @@ -324,7 +304,12 @@ fast_ata_pio: static int pdcnew_quirkproc(ide_drive_t *drive) { - return check_in_drive_lists(drive, pdc_quirk_drives); + const char **list, *model = drive->id->model; + + for (list = pdc_quirk_drives; *list != NULL; list++) + if (strstr(model, *list) != NULL) + return 2; + return 0; } static void pdcnew_reset(ide_drive_t *drive) diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c index 143239c093d..730e8d1ec2f 100644 --- a/drivers/ide/pci/pdc202xx_old.c +++ b/drivers/ide/pci/pdc202xx_old.c @@ -123,26 +123,6 @@ static u8 pdc202xx_ratemask (ide_drive_t *drive) return mode; } -static int check_in_drive_lists (ide_drive_t *drive, const char **list) -{ - struct hd_driveid *id = drive->id; - - if (pdc_quirk_drives == list) { - while (*list) { - if (strstr(id->model, *list++)) { - return 2; - } - } - } else { - while (*list) { - if (!strcmp(*list++,id->model)) { - return 1; - } - } - } - return 0; -} - static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); @@ -377,7 +357,12 @@ fast_ata_pio: static int pdc202xx_quirkproc (ide_drive_t *drive) { - return ((int) check_in_drive_lists(drive, pdc_quirk_drives)); + const char **list, *model = drive->id->model; + + for (list = pdc_quirk_drives; *list != NULL; list++) + if (strstr(model, *list) != NULL) + return 2; + return 0; } static void pdc202xx_old_ide_dma_start(ide_drive_t *drive) -- cgit v1.2.3 From 33dced2ea5ed03dda10e7f9f41f0910f32e02eaa Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 7 Feb 2007 18:18:45 +0100 Subject: ide: add Toshiba TC86C001 IDE driver (take 2) This is the driver for the Toshiba TC86C001 GOKU-S PCI IDE controller, completely reworked from the original brain-damaged Toshiba's 2.4 version. This single channel UltraDMA/66 controller is very simple in programming, yet Toshiba managed to plant many interesting bugs in it. The particularly nasty "limitation 5" (as they call the errata) caused me to abuse the IDE core in a possibly most interesting way so far. However, this is still better than the #ifdef mess in drivers/ide/ide-io.c that the original version included (well, it had much more mess)... Signed-off-by: Sergei Shtylyov Acked-by: Alan Cox Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 5 + drivers/ide/pci/Makefile | 1 + drivers/ide/pci/tc86c001.c | 308 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 314 insertions(+) create mode 100644 drivers/ide/pci/tc86c001.c (limited to 'drivers/ide') diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 3f828052f8d..4eb420891f9 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -742,6 +742,11 @@ config BLK_DEV_VIA82CXXX This allows the kernel to change PIO, DMA and UDMA speeds and to configure the chip to optimum performance. +config BLK_DEV_TC86C001 + tristate "Toshiba TC86C001 support" + help + This driver adds support for Toshiba TC86C001 GOKU-S chip. + endif config BLK_DEV_IDE_PMAC diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile index fef08960aa4..73f54dfb8c0 100644 --- a/drivers/ide/pci/Makefile +++ b/drivers/ide/pci/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_BLK_DEV_SIIMAGE) += siimage.o obj-$(CONFIG_BLK_DEV_SIS5513) += sis5513.o obj-$(CONFIG_BLK_DEV_SL82C105) += sl82c105.o obj-$(CONFIG_BLK_DEV_SLC90E66) += slc90e66.o +obj-$(CONFIG_BLK_DEV_TC86C001) += tc86c001.o obj-$(CONFIG_BLK_DEV_TRIFLEX) += triflex.o obj-$(CONFIG_BLK_DEV_TRM290) += trm290.o obj-$(CONFIG_BLK_DEV_VIA82CXXX) += via82cxxx.o diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c new file mode 100644 index 00000000000..b6566534a31 --- /dev/null +++ b/drivers/ide/pci/tc86c001.c @@ -0,0 +1,308 @@ +/* + * drivers/ide/pci/tc86c001.c Version 1.00 Dec 12, 2006 + * + * Copyright (C) 2002 Toshiba Corporation + * Copyright (C) 2005-2006 MontaVista Software, Inc. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include + +static inline u8 tc86c001_ratemask(ide_drive_t *drive) +{ + return eighty_ninty_three(drive) ? 2 : 1; +} + +static int tc86c001_tune_chipset(ide_drive_t *drive, u8 speed) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long scr_port = hwif->config_data + (drive->dn ? 0x02 : 0x00); + u16 mode, scr = hwif->INW(scr_port); + + speed = ide_rate_filter(tc86c001_ratemask(drive), speed); + + switch (speed) { + case XFER_UDMA_4: mode = 0x00c0; break; + case XFER_UDMA_3: mode = 0x00b0; break; + case XFER_UDMA_2: mode = 0x00a0; break; + case XFER_UDMA_1: mode = 0x0090; break; + case XFER_UDMA_0: mode = 0x0080; break; + case XFER_MW_DMA_2: mode = 0x0070; break; + case XFER_MW_DMA_1: mode = 0x0060; break; + case XFER_MW_DMA_0: mode = 0x0050; break; + case XFER_PIO_4: mode = 0x0400; break; + case XFER_PIO_3: mode = 0x0300; break; + case XFER_PIO_2: mode = 0x0200; break; + case XFER_PIO_1: mode = 0x0100; break; + case XFER_PIO_0: + default: mode = 0x0000; break; + } + + scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f; + scr |= mode; + hwif->OUTW(scr, scr_port); + + return ide_config_drive_speed(drive, speed); +} + +static void tc86c001_tune_drive(ide_drive_t *drive, u8 pio) +{ + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + (void) tc86c001_tune_chipset(drive, XFER_PIO_0 + pio); +} + +/* + * HACKITY HACK + * + * This is a workaround for the limitation 5 of the TC86C001 IDE controller: + * if a DMA transfer terminates prematurely, the controller leaves the device's + * interrupt request (INTRQ) pending and does not generate a PCI interrupt (or + * set the interrupt bit in the DMA status register), thus no PCI interrupt + * will occur until a DMA transfer has been successfully completed. + * + * We work around this by initiating dummy, zero-length DMA transfer on + * a DMA timeout expiration. I found no better way to do this with the current + * IDE core than to temporarily replace a higher level driver's timer expiry + * handler with our own backing up to that handler in case our recovery fails. + */ +static int tc86c001_timer_expiry(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + ide_expiry_t *expiry = ide_get_hwifdata(hwif); + ide_hwgroup_t *hwgroup = HWGROUP(drive); + u8 dma_stat = hwif->INB(hwif->dma_status); + + /* Restore a higher level driver's expiry handler first. */ + hwgroup->expiry = expiry; + + if ((dma_stat & 5) == 1) { /* DMA active and no interrupt */ + unsigned long sc_base = hwif->config_data; + unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04); + u8 dma_cmd = hwif->INB(hwif->dma_command); + + printk(KERN_WARNING "%s: DMA interrupt possibly stuck, " + "attempting recovery...\n", drive->name); + + /* Stop DMA */ + hwif->OUTB(dma_cmd & ~0x01, hwif->dma_command); + + /* Setup the dummy DMA transfer */ + hwif->OUTW(0, sc_base + 0x0a); /* Sector Count */ + hwif->OUTW(0, twcr_port); /* Transfer Word Count 1 or 2 */ + + /* Start the dummy DMA transfer */ + hwif->OUTB(0x00, hwif->dma_command); /* clear R_OR_WCTR for write */ + hwif->OUTB(0x01, hwif->dma_command); /* set START_STOPBM */ + + /* + * If an interrupt was pending, it should come thru shortly. + * If not, a higher level driver's expiry handler should + * eventually cause some kind of recovery from the DMA stall. + */ + return WAIT_MIN_SLEEP; + } + + /* Chain to the restored expiry handler if DMA wasn't active. */ + if (likely(expiry != NULL)) + return expiry(drive); + + /* If there was no handler, "emulate" that for ide_timer_expiry()... */ + return -1; +} + +static void tc86c001_dma_start(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + ide_hwgroup_t *hwgroup = HWGROUP(drive); + unsigned long sc_base = hwif->config_data; + unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04); + unsigned long nsectors = hwgroup->rq->nr_sectors; + + /* + * We have to manually load the sector count and size into + * the appropriate system control registers for DMA to work + * with LBA48 and ATAPI devices... + */ + hwif->OUTW(nsectors, sc_base + 0x0a); /* Sector Count */ + hwif->OUTW(SECTOR_SIZE / 2, twcr_port); /* Transfer Word Count 1/2 */ + + /* Install our timeout expiry hook, saving the current handler... */ + ide_set_hwifdata(hwif, hwgroup->expiry); + hwgroup->expiry = &tc86c001_timer_expiry; + + ide_dma_start(drive); +} + +static int tc86c001_busproc(ide_drive_t *drive, int state) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned long sc_base = hwif->config_data; + u16 scr1; + + /* System Control 1 Register bit 11 (ATA Hard Reset) read */ + scr1 = hwif->INW(sc_base + 0x00); + + switch (state) { + case BUSSTATE_ON: + if (!(scr1 & 0x0800)) + return 0; + scr1 &= ~0x0800; + + hwif->drives[0].failures = hwif->drives[1].failures = 0; + break; + case BUSSTATE_OFF: + if (scr1 & 0x0800) + return 0; + scr1 |= 0x0800; + + hwif->drives[0].failures = hwif->drives[0].max_failures + 1; + hwif->drives[1].failures = hwif->drives[1].max_failures + 1; + break; + default: + return -EINVAL; + } + + /* System Control 1 Register bit 11 (ATA Hard Reset) write */ + hwif->OUTW(scr1, sc_base + 0x00); + return 0; +} + +static int config_chipset_for_dma(ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, tc86c001_ratemask(drive)); + + if (!speed) + return 0; + + (void) tc86c001_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +static int tc86c001_config_drive_xfer_rate(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct hd_driveid *id = drive->id; + + if ((id->capability & 1) && drive->autodma) { + + if (ide_use_dma(drive) && config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); + + goto fast_ata_pio; + + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: + tc86c001_tune_drive(drive, 255); + return hwif->ide_dma_off_quietly(drive); + } + /* IORDY not supported */ + return 0; +} + +void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) +{ + unsigned long sc_base = pci_resource_start(hwif->pci_dev, 5); + u16 scr1 = hwif->INW(sc_base + 0x00);; + + /* System Control 1 Register bit 15 (Soft Reset) set */ + hwif->OUTW(scr1 | 0x8000, sc_base + 0x00); + + /* System Control 1 Register bit 14 (FIFO Reset) set */ + hwif->OUTW(scr1 | 0x4000, sc_base + 0x00); + + /* System Control 1 Register: reset clear */ + hwif->OUTW(scr1 & ~0xc000, sc_base + 0x00); + + /* Store the system control register base for convenience... */ + hwif->config_data = sc_base; + + hwif->tuneproc = &tc86c001_tune_drive; + hwif->speedproc = &tc86c001_tune_chipset; + hwif->busproc = &tc86c001_busproc; + + hwif->drives[0].autotune = hwif->drives[1].autotune = 1; + + if (!hwif->dma_base) + return; + + /* + * Sector Count Control Register bits 0 and 1 set: + * software sets Sector Count Register for master and slave device + */ + hwif->OUTW(0x0003, sc_base + 0x0c); + + /* Sector Count Register limit */ + hwif->rqsize = 0xffff; + + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x1f; + hwif->mwdma_mask = 0x07; + + hwif->ide_dma_check = &tc86c001_config_drive_xfer_rate; + hwif->dma_start = &tc86c001_dma_start; + + if (!hwif->udma_four) { + /* + * System Control 1 Register bit 13 (PDIAGN): + * 0=80-pin cable, 1=40-pin cable + */ + scr1 = hwif->INW(sc_base + 0x00); + hwif->udma_four = (scr1 & 0x2000) ? 0 : 1; + } + + if (!noautodma) + hwif->autodma = 1; + hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; +} + +static unsigned int init_chipset_tc86c001(struct pci_dev *dev, const char *name) +{ + int err = pci_request_region(dev, 5, name); + + if (err) + printk(KERN_ERR "%s: system control regs already in use", name); + return err; +} + +static ide_pci_device_t tc86c001_chipset __devinitdata = { + .name = "TC86C001", + .init_chipset = init_chipset_tc86c001, + .init_hwif = init_hwif_tc86c001, + .channels = 1, + .autodma = AUTODMA, + .bootable = OFF_BOARD +}; + +static int __devinit tc86c001_init_one(struct pci_dev *dev, + const struct pci_device_id *id) +{ + return ide_setup_pci_device(dev, &tc86c001_chipset); +} + +static struct pci_device_id tc86c001_pci_tbl[] = { + { PCI_VENDOR_ID_TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, tc86c001_pci_tbl); + +static struct pci_driver driver = { + .name = "TC86C001", + .id_table = tc86c001_pci_tbl, + .probe = tc86c001_init_one +}; + +static int tc86c001_ide_init(void) +{ + return ide_pci_register_driver(&driver); +} +module_init(tc86c001_ide_init); + +MODULE_AUTHOR("MontaVista Software, Inc. "); +MODULE_DESCRIPTION("PCI driver module for TC86C001 IDE"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From e8ab7f536f014e5d86ce6cf7860d5def6cc5f715 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 7 Feb 2007 18:18:52 +0100 Subject: tc86c001: init_hwif_tc86c001() can be static Signed-off-by: Adrian Bunk Cc: Sergei Shtylyov Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/tc86c001.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c index b6566534a31..5bf28c5f631 100644 --- a/drivers/ide/pci/tc86c001.c +++ b/drivers/ide/pci/tc86c001.c @@ -204,7 +204,7 @@ fast_ata_pio: return 0; } -void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) +static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) { unsigned long sc_base = pci_resource_start(hwif->pci_dev, 5); u16 scr1 = hwif->INW(sc_base + 0x00);; -- cgit v1.2.3 From ba59c4b84a064e3e9d72d98b56f92a5b2aa71c22 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 7 Feb 2007 18:19:01 +0100 Subject: tc86c001: mark init_chipset_tc86c001() with __devinit tag Signed-off-by: Andrew Morton Cc: Sergei Shtylyov Cc: Adrian Bunk Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/tc86c001.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c index 5bf28c5f631..97dd709f211 100644 --- a/drivers/ide/pci/tc86c001.c +++ b/drivers/ide/pci/tc86c001.c @@ -260,7 +260,8 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif) hwif->drives[0].autodma = hwif->drives[1].autodma = hwif->autodma; } -static unsigned int init_chipset_tc86c001(struct pci_dev *dev, const char *name) +static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev, + const char *name) { int err = pci_request_region(dev, 5, name); -- cgit v1.2.3 From a534b68da0471dd9e4e3f7fc922faba74f8f4506 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 7 Feb 2007 18:19:09 +0100 Subject: tc86c001: add missing __init tag for tc86c001_ide_init() Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/tc86c001.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c index 97dd709f211..2ad72bbda34 100644 --- a/drivers/ide/pci/tc86c001.c +++ b/drivers/ide/pci/tc86c001.c @@ -298,7 +298,7 @@ static struct pci_driver driver = { .probe = tc86c001_init_one }; -static int tc86c001_ide_init(void) +static int __init tc86c001_ide_init(void) { return ide_pci_register_driver(&driver); } -- cgit v1.2.3 From 9c6712c0bcd2954fb4ca58d31f7316292a4b0945 Mon Sep 17 00:00:00 2001 From: Jack Lee Date: Wed, 7 Feb 2007 18:19:09 +0100 Subject: ide: add it8213 IDE driver From: Alan Cox Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 5 + drivers/ide/pci/Makefile | 2 +- drivers/ide/pci/it8213.c | 402 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 408 insertions(+), 1 deletion(-) create mode 100644 drivers/ide/pci/it8213.c (limited to 'drivers/ide') diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 4eb420891f9..d781b2cd3d6 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -606,6 +606,11 @@ config BLK_DEV_PIIX the kernel to change PIO, DMA and UDMA speeds and to configure the chip to optimum performance. +config BLK_DEV_IT8213 + tristate "IT8213 IDE support" + help + This driver adds support for the ITE 8213 IDE controller. + config BLK_DEV_IT821X tristate "IT821X IDE support" help diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile index 73f54dfb8c0..64776ab4329 100644 --- a/drivers/ide/pci/Makefile +++ b/drivers/ide/pci/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o -#obj-$(CONFIG_BLK_DEV_HPT37X) += hpt37x.o +obj-$(CONFIG_BLK_DEV_IT8213) += it8213.o obj-$(CONFIG_BLK_DEV_IT821X) += it821x.o obj-$(CONFIG_BLK_DEV_JMICRON) += jmicron.o obj-$(CONFIG_BLK_DEV_NS87415) += ns87415.o diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c new file mode 100644 index 00000000000..6b46edfba81 --- /dev/null +++ b/drivers/ide/pci/it8213.c @@ -0,0 +1,402 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * it8213_ratemask - Compute available modes + * @drive: IDE drive + * + * Compute the available speeds for the devices on the interface. This + * is all modes to ATA100 clipped by drive cable setup. + */ + +static u8 it8213_ratemask (ide_drive_t *drive) +{ + u8 mode = 4; + if (!eighty_ninty_three(drive)) + mode = min(mode, (u8)1); + return mode; +} + +/** + * it8213_dma_2_pio - return the PIO mode matching DMA + * @xfer_rate: transfer speed + * + * Returns the nearest equivalent PIO timing for the PIO or DMA + * mode requested by the controller. + */ + +static u8 it8213_dma_2_pio (u8 xfer_rate) { + switch(xfer_rate) { + case XFER_UDMA_6: + case XFER_UDMA_5: + case XFER_UDMA_4: + case XFER_UDMA_3: + case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + case XFER_MW_DMA_2: + case XFER_PIO_4: + return 4; + case XFER_MW_DMA_1: + case XFER_PIO_3: + return 3; + case XFER_SW_DMA_2: + case XFER_PIO_2: + return 2; + case XFER_MW_DMA_0: + case XFER_SW_DMA_1: + case XFER_SW_DMA_0: + case XFER_PIO_1: + case XFER_PIO_0: + case XFER_PIO_SLOW: + default: + return 0; + } +} + +static spinlock_t tune_lock = SPIN_LOCK_UNLOCKED; + +/* + * it8213_tuneproc - tune a drive + * @drive: drive to tune + * @mode_wanted: the target operating mode + * + * Load the timing settings for this device mode into the + * controller. By the time we are called the mode has been + * modified as neccessary to handle the absence of seperate + * master/slave timers for MWDMA/PIO. + * + * This code is only used in pass through mode. + */ + +static void it8213_tuneproc (ide_drive_t *drive, u8 pio) +{ + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + int is_slave = (&hwif->drives[1] == drive); + int master_port = 0x40; + int slave_port = 0x44; + unsigned long flags; + u16 master_data; + u8 slave_data; + + u8 timings[][2] = { { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; + + pio = ide_get_best_pio_mode(drive, pio, 5, NULL); + + spin_lock_irqsave(&tune_lock, flags); + pci_read_config_word(dev, master_port, &master_data); + if (is_slave) { + master_data = master_data | 0x4000; + if (pio > 1) + + master_data = master_data | 0x0070; + pci_read_config_byte(dev, slave_port, &slave_data); + slave_data = slave_data & 0xf0; + slave_data = slave_data | (((timings[pio][0] << 2) | (timings[pio][1]) << 0)); + } else { + master_data = master_data & 0xccf8; + if (pio > 1) + + master_data = master_data | 0x0007; + master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); + } + pci_write_config_word(dev, master_port, master_data); + if (is_slave) + pci_write_config_byte(dev, slave_port, slave_data); + spin_unlock_irqrestore(&tune_lock, flags); +} + + +/** + * it8213_tune_chipset - set controller timings + * @drive: Drive to set up + * @xferspeed: speed we want to achieve + * + * Tune the ITE chipset for the desired mode. If we can't achieve + * the desired mode then tune for a lower one, but ultimately + * make the thing work. + */ + +static int it8213_tune_chipset (ide_drive_t *drive, byte xferspeed) +{ + + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + u8 maslave = 0x40; + u8 speed = ide_rate_filter(it8213_ratemask(drive), xferspeed); + int a_speed = 3 << (drive->dn * 4); + int u_flag = 1 << drive->dn; + int v_flag = 0x01 << drive->dn; + int w_flag = 0x10 << drive->dn; + int u_speed = 0; + u16 reg4042, reg4a; + u8 reg48, reg54, reg55; + + pci_read_config_word(dev, maslave, ®4042); + pci_read_config_byte(dev, 0x48, ®48); + pci_read_config_word(dev, 0x4a, ®4a); + pci_read_config_byte(dev, 0x54, ®54); + pci_read_config_byte(dev, 0x55, ®55); + + switch(speed) { + case XFER_UDMA_6: + case XFER_UDMA_4: + case XFER_UDMA_2:u_speed = 2 << (drive->dn * 4); break; + case XFER_UDMA_5: + case XFER_UDMA_3: + case XFER_UDMA_1:u_speed = 1 << (drive->dn * 4); break; + case XFER_UDMA_0:u_speed = 0 << (drive->dn * 4); break; + break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_MW_DMA_0: + break; + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_1: + case XFER_PIO_0: + break; + default: + return -1; + } + + if (speed >= XFER_UDMA_0) + { + if (!(reg48 & u_flag)) + pci_write_config_byte(dev, 0x48, reg48 | u_flag); + if (speed >= XFER_UDMA_5) { + pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag); + } else { + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + } + + if ((reg4a & a_speed) != u_speed) + pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); + if (speed > XFER_UDMA_2) + { + if (!(reg54 & v_flag)) + pci_write_config_byte(dev, 0x54, reg54 | v_flag); + } else + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); + } else /*if(speed >= XFER_UDMA_0)*/ + { + if (reg48 & u_flag) + pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); + if (reg4a & a_speed) + pci_write_config_word(dev, 0x4a, reg4a & ~a_speed); + if (reg54 & v_flag) + pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); + if (reg55 & w_flag) + pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); + } + it8213_tuneproc(drive, it8213_dma_2_pio(speed)); + return ide_config_drive_speed(drive, speed); + } + + +/* + * config_chipset_for_dma - configure for DMA + * @drive: drive to configure + * + * Called by the IDE layer when it wants the timings set up. + */ + +static int config_chipset_for_dma (ide_drive_t *drive) +{ + u8 speed = ide_dma_speed(drive, it8213_ratemask(drive)); + if (!speed) + { + u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); + speed = it8213_dma_2_pio(XFER_PIO_0 + tspeed); + } +// config_it8213_chipset_for_pio(drive, !speed); + it8213_tune_chipset(drive, speed); + return ide_dma_enable(drive); +} + +/** + * config_it8213_chipset_for_pio - set drive timings + * @drive: drive to tune + * @speed we want + * + * Compute the best pio mode we can for a given device. We must + * pick a speed that does not cause problems with the other device + * on the cable. + */ +/* +static void config_it8213_chipset_for_pio (ide_drive_t *drive, byte set_speed) +{ + ide_hwif_t *hwif = HWIF(drive); +// u8 unit = drive->select.b.unit; + ide_hwif_t *hwif = drive->hwif; + ide_drive_t *pair = &hwif->drives[1-unit]; + u8 speed = 0, set_pio = ide_get_best_pio_mode(drive, 255, 5, NULL); + u8 pair_pio; + + if(pair != NULL) { + pair_pio = ide_get_best_pio_mode(pair, 255, 5, NULL); + if(pair_pio < set_pio) + set_pio = pair_pio; + } + it8213_tuneproc(drive, set_pio); + speed = XFER_PIO_0 + set_pio; + if (set_speed) + (void) ide_config_drive_speed(drive, speed); +} +*/ +/** + * it8213_configure_drive_for_dma - set up for DMA transfers + * @drive: drive we are going to set up + * + * Set up the drive for DMA, tune the controller and drive as + * required. If the drive isn't suitable for DMA or we hit + * other problems then we will drop down to PIO and set up + * PIO appropriately + */ + +static int it8213_config_drive_for_dma (ide_drive_t *drive) +{ +// ide_hwif_t *hwif = drive->hwif; +// struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + if (ide_use_dma(drive)) { + if (config_chipset_for_dma(drive)) + return hwif->ide_dma_on(drive); + } +// config_it8213_chipset_for_pio(drive, 1); + hwif->tuneproc(drive, 255); + return hwif->ide_dma_off_quietly(drive); +} + + +static unsigned int __devinit init_chipset_it8213(struct pci_dev *dev, const char *name) +{ + printk(KERN_INFO "it8213: controller in IDE mode.\n"); + return 0; +} + + +/** + * init_hwif_it8213 - set up hwif structs + * @hwif: interface to set up + * + * We do the basic set up of the interface structure. The IT8212 + * requires several custom handlers so we override the default + * ide DMA handlers appropriately + */ + +static void __devinit init_hwif_it8213(ide_hwif_t *hwif) +{ + u8 reg42h = 0, ata66 = 0; + u8 mask = 0x02; + + hwif->atapi_dma = 1; + + hwif->speedproc = &it8213_tune_chipset; + hwif->tuneproc = &it8213_tuneproc; + + hwif->autodma = 0; + + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + + if (!hwif->dma_base) + goto fallback; + hwif->atapi_dma = 1; + hwif->ultra_mask = 0x7f; + hwif->mwdma_mask = 0x07; + hwif->swdma_mask = 0x07; + + pci_read_config_byte(hwif->pci_dev, 0x42, ®42h); + ata66 = (reg42h & mask) ? 0 : 1; + + hwif->ide_dma_check = &it8213_config_drive_for_dma; + if (!(hwif->udma_four)) + hwif->udma_four = ata66; +// hwif->udma_four = 0; + + /* + * The BIOS often doesn't set up DMA on this controller + * so we always do it. + */ + if (!noautodma) + hwif->autodma = 1; + + hwif->drives[0].autodma = hwif->autodma; + hwif->drives[1].autodma = hwif->autodma; + return; +fallback: + hwif->autodma = 0; + return; +} + + +#define DECLARE_ITE_DEV(name_str) \ + { \ + .name = name_str, \ + .init_chipset = init_chipset_it8213, \ + .init_hwif = init_hwif_it8213, \ + .channels = 1, \ + .autodma = AUTODMA, \ + .enablebits = {{0x41,0x80,0x80}}, \ + .bootable = ON_BOARD, \ + } + +static ide_pci_device_t it8213_chipsets[] __devinitdata = { + /* 0 */ DECLARE_ITE_DEV("IT8213"), +}; + + +/** + * it8213_init_one - pci layer discovery entry + * @dev: PCI device + * @id: ident table entry + * + * Called by the PCI code when it finds an ITE8213 controller. As + * this device follows the standard interfaces we can use the + * standard helper functions to do almost all the work for us. + */ + +static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_device_id *id) +{ + ide_setup_pci_device(dev, &it8213_chipsets[id->driver_data]); + return 0; +} + + +static struct pci_device_id it8213_pci_tbl[] = { + { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8213, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; + +MODULE_DEVICE_TABLE(pci, it8213_pci_tbl); + +static struct pci_driver driver = { + .name = "ITE8213_IDE", + .id_table = it8213_pci_tbl, + .probe = it8213_init_one, +}; + +static int __init it8213_ide_init(void) +{ + return ide_pci_register_driver(&driver); } + +module_init(it8213_ide_init); + +MODULE_AUTHOR("Jack and Alan Cox"); /* Update this */ +MODULE_DESCRIPTION("PCI driver module for the ITE 8213"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 6788182602f6862688d9a14e6f527449696f65c6 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 7 Feb 2007 18:19:26 +0100 Subject: ide: it8213 IDE driver update (version 2) * set ATAPI/IORDY/TIME bits correctly in it8213_tuneproc() * fix UDMA/MWDMA/SWDMA masks in it8213_init_hwif() * in it8213_tune_chipset() SWDMA2 mode should be used instead of MWDMA0 * backport various fixes from piix/slc90e66 drivers: - in it8213_tuneproc() the highest possible PIO mode is PIO4 (not PIO5) - clear ATAPI/IORDY/TIME bits before setting them also for slave device - use ->speedproc in it8213_config_drive_for_dma() - don't try to tune PIO in config_chipset_for_pio() - simplify is_slave calculation in it8213_tuneproc() - misc cleanups * fix it8213_ratemask() and it8213_tuneproc() comments * simplify it8213_init_hwif() * remove init_chipset_it8213() * add missing Copyrights and update MODULE_AUTHOR() * CodingStyle cleanups * remove dead code v2: * PCI_DEVICE_ID_ITE_8213 is only defined in -mm kernels, so just use PCI Device ID (0x8213) directly * fix ->ultra_mask incorrectly changed to 0x3f in v1 version of the patch Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/it8213.c | 172 ++++++++++++++++++----------------------------- 1 file changed, 66 insertions(+), 106 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c index 6b46edfba81..63248b6909f 100644 --- a/drivers/ide/pci/it8213.c +++ b/drivers/ide/pci/it8213.c @@ -1,3 +1,11 @@ +/* + * ITE 8213 IDE driver + * + * Copyright (C) 2006 Jack Lee + * Copyright (C) 2006 Alan Cox + * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + */ + #include #include #include @@ -14,14 +22,14 @@ * @drive: IDE drive * * Compute the available speeds for the devices on the interface. This - * is all modes to ATA100 clipped by drive cable setup. + * is all modes to ATA133 clipped by drive cable setup. */ static u8 it8213_ratemask (ide_drive_t *drive) { u8 mode = 4; if (!eighty_ninty_three(drive)) - mode = min(mode, (u8)1); + mode = min_t(u8, mode, 1); return mode; } @@ -62,55 +70,57 @@ static u8 it8213_dma_2_pio (u8 xfer_rate) { } } -static spinlock_t tune_lock = SPIN_LOCK_UNLOCKED; - /* * it8213_tuneproc - tune a drive * @drive: drive to tune - * @mode_wanted: the target operating mode - * - * Load the timing settings for this device mode into the - * controller. By the time we are called the mode has been - * modified as neccessary to handle the absence of seperate - * master/slave timers for MWDMA/PIO. + * @pio: desired PIO mode * - * This code is only used in pass through mode. + * Set the interface PIO mode. */ -static void it8213_tuneproc (ide_drive_t *drive, u8 pio) +static void it8213_tuneproc (ide_drive_t *drive, u8 pio) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - int is_slave = (&hwif->drives[1] == drive); + int is_slave = drive->dn & 1; int master_port = 0x40; int slave_port = 0x44; unsigned long flags; u16 master_data; u8 slave_data; + static DEFINE_SPINLOCK(tune_lock); + int control = 0; - u8 timings[][2] = { { 0, 0 }, - { 0, 0 }, - { 1, 0 }, - { 2, 1 }, - { 2, 3 }, }; + static const u8 timings[][2]= { + { 0, 0 }, + { 0, 0 }, + { 1, 0 }, + { 2, 1 }, + { 2, 3 }, }; - pio = ide_get_best_pio_mode(drive, pio, 5, NULL); + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); spin_lock_irqsave(&tune_lock, flags); pci_read_config_word(dev, master_port, &master_data); + + if (pio > 1) + control |= 1; /* Programmable timing on */ + if (drive->media != ide_disk) + control |= 4; /* ATAPI */ + if (pio > 2) + control |= 2; /* IORDY */ if (is_slave) { - master_data = master_data | 0x4000; + master_data |= 0x4000; + master_data &= ~0x0070; if (pio > 1) - - master_data = master_data | 0x0070; + master_data = master_data | (control << 4); pci_read_config_byte(dev, slave_port, &slave_data); slave_data = slave_data & 0xf0; - slave_data = slave_data | (((timings[pio][0] << 2) | (timings[pio][1]) << 0)); + slave_data = slave_data | (timings[pio][0] << 2) | timings[pio][1]; } else { - master_data = master_data & 0xccf8; + master_data &= ~0x3307; if (pio > 1) - - master_data = master_data | 0x0007; + master_data = master_data | control; master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8); } pci_write_config_word(dev, master_port, master_data); @@ -119,7 +129,6 @@ static void it8213_tuneproc (ide_drive_t *drive, u8 pio) spin_unlock_irqrestore(&tune_lock, flags); } - /** * it8213_tune_chipset - set controller timings * @drive: Drive to set up @@ -130,7 +139,7 @@ static void it8213_tuneproc (ide_drive_t *drive, u8 pio) * make the thing work. */ -static int it8213_tune_chipset (ide_drive_t *drive, byte xferspeed) +static int it8213_tune_chipset (ide_drive_t *drive, u8 xferspeed) { ide_hwif_t *hwif = HWIF(drive); @@ -154,15 +163,15 @@ static int it8213_tune_chipset (ide_drive_t *drive, byte xferspeed) switch(speed) { case XFER_UDMA_6: case XFER_UDMA_4: - case XFER_UDMA_2:u_speed = 2 << (drive->dn * 4); break; + case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; case XFER_UDMA_5: case XFER_UDMA_3: - case XFER_UDMA_1:u_speed = 1 << (drive->dn * 4); break; - case XFER_UDMA_0:u_speed = 0 << (drive->dn * 4); break; + case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; + case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; break; case XFER_MW_DMA_2: case XFER_MW_DMA_1: - case XFER_MW_DMA_0: + case XFER_SW_DMA_2: break; case XFER_PIO_4: case XFER_PIO_3: @@ -174,8 +183,7 @@ static int it8213_tune_chipset (ide_drive_t *drive, byte xferspeed) return -1; } - if (speed >= XFER_UDMA_0) - { + if (speed >= XFER_UDMA_0) { if (!(reg48 & u_flag)) pci_write_config_byte(dev, 0x48, reg48 | u_flag); if (speed >= XFER_UDMA_5) { @@ -186,14 +194,12 @@ static int it8213_tune_chipset (ide_drive_t *drive, byte xferspeed) if ((reg4a & a_speed) != u_speed) pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed); - if (speed > XFER_UDMA_2) - { + if (speed > XFER_UDMA_2) { if (!(reg54 & v_flag)) pci_write_config_byte(dev, 0x54, reg54 | v_flag); } else pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); - } else /*if(speed >= XFER_UDMA_0)*/ - { + } else { if (reg48 & u_flag) pci_write_config_byte(dev, 0x48, reg48 & ~u_flag); if (reg4a & a_speed) @@ -202,11 +208,10 @@ static int it8213_tune_chipset (ide_drive_t *drive, byte xferspeed) pci_write_config_byte(dev, 0x54, reg54 & ~v_flag); if (reg55 & w_flag) pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag); - } + } it8213_tuneproc(drive, it8213_dma_2_pio(speed)); return ide_config_drive_speed(drive, speed); - } - +} /* * config_chipset_for_dma - configure for DMA @@ -217,47 +222,16 @@ static int it8213_tune_chipset (ide_drive_t *drive, byte xferspeed) static int config_chipset_for_dma (ide_drive_t *drive) { - u8 speed = ide_dma_speed(drive, it8213_ratemask(drive)); + u8 speed = ide_dma_speed(drive, it8213_ratemask(drive)); + if (!speed) - { - u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL); - speed = it8213_dma_2_pio(XFER_PIO_0 + tspeed); - } -// config_it8213_chipset_for_pio(drive, !speed); + return 0; + it8213_tune_chipset(drive, speed); + return ide_dma_enable(drive); } -/** - * config_it8213_chipset_for_pio - set drive timings - * @drive: drive to tune - * @speed we want - * - * Compute the best pio mode we can for a given device. We must - * pick a speed that does not cause problems with the other device - * on the cable. - */ -/* -static void config_it8213_chipset_for_pio (ide_drive_t *drive, byte set_speed) -{ - ide_hwif_t *hwif = HWIF(drive); -// u8 unit = drive->select.b.unit; - ide_hwif_t *hwif = drive->hwif; - ide_drive_t *pair = &hwif->drives[1-unit]; - u8 speed = 0, set_pio = ide_get_best_pio_mode(drive, 255, 5, NULL); - u8 pair_pio; - - if(pair != NULL) { - pair_pio = ide_get_best_pio_mode(pair, 255, 5, NULL); - if(pair_pio < set_pio) - set_pio = pair_pio; - } - it8213_tuneproc(drive, set_pio); - speed = XFER_PIO_0 + set_pio; - if (set_speed) - (void) ide_config_drive_speed(drive, speed); -} -*/ /** * it8213_configure_drive_for_dma - set up for DMA transfers * @drive: drive we are going to set up @@ -270,26 +244,19 @@ static void config_it8213_chipset_for_pio (ide_drive_t *drive, byte set_speed) static int it8213_config_drive_for_dma (ide_drive_t *drive) { -// ide_hwif_t *hwif = drive->hwif; -// struct hd_driveid *id = drive->id; - ide_hwif_t *hwif = HWIF(drive); + ide_hwif_t *hwif = drive->hwif; + if (ide_use_dma(drive)) { if (config_chipset_for_dma(drive)) return hwif->ide_dma_on(drive); } -// config_it8213_chipset_for_pio(drive, 1); - hwif->tuneproc(drive, 255); - return hwif->ide_dma_off_quietly(drive); -} + hwif->speedproc(drive, XFER_PIO_0 + + ide_get_best_pio_mode(drive, 255, 4, NULL)); -static unsigned int __devinit init_chipset_it8213(struct pci_dev *dev, const char *name) -{ - printk(KERN_INFO "it8213: controller in IDE mode.\n"); - return 0; + return hwif->ide_dma_off_quietly(drive); } - /** * init_hwif_it8213 - set up hwif structs * @hwif: interface to set up @@ -302,9 +269,6 @@ static unsigned int __devinit init_chipset_it8213(struct pci_dev *dev, const cha static void __devinit init_hwif_it8213(ide_hwif_t *hwif) { u8 reg42h = 0, ata66 = 0; - u8 mask = 0x02; - - hwif->atapi_dma = 1; hwif->speedproc = &it8213_tune_chipset; hwif->tuneproc = &it8213_tuneproc; @@ -315,19 +279,19 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif) hwif->drives[1].autotune = 1; if (!hwif->dma_base) - goto fallback; + return; + hwif->atapi_dma = 1; hwif->ultra_mask = 0x7f; - hwif->mwdma_mask = 0x07; - hwif->swdma_mask = 0x07; + hwif->mwdma_mask = 0x06; + hwif->swdma_mask = 0x04; pci_read_config_byte(hwif->pci_dev, 0x42, ®42h); - ata66 = (reg42h & mask) ? 0 : 1; + ata66 = (reg42h & 0x02) ? 0 : 1; hwif->ide_dma_check = &it8213_config_drive_for_dma; if (!(hwif->udma_four)) hwif->udma_four = ata66; -// hwif->udma_four = 0; /* * The BIOS often doesn't set up DMA on this controller @@ -338,20 +302,15 @@ static void __devinit init_hwif_it8213(ide_hwif_t *hwif) hwif->drives[0].autodma = hwif->autodma; hwif->drives[1].autodma = hwif->autodma; - return; -fallback: - hwif->autodma = 0; - return; } #define DECLARE_ITE_DEV(name_str) \ { \ .name = name_str, \ - .init_chipset = init_chipset_it8213, \ .init_hwif = init_hwif_it8213, \ .channels = 1, \ - .autodma = AUTODMA, \ + .autodma = AUTODMA, \ .enablebits = {{0x41,0x80,0x80}}, \ .bootable = ON_BOARD, \ } @@ -379,7 +338,7 @@ static int __devinit it8213_init_one(struct pci_dev *dev, const struct pci_devic static struct pci_device_id it8213_pci_tbl[] = { - { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8213, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_ITE, 0x8213, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 0, }, }; @@ -393,10 +352,11 @@ static struct pci_driver driver = { static int __init it8213_ide_init(void) { - return ide_pci_register_driver(&driver); } + return ide_pci_register_driver(&driver); +} module_init(it8213_ide_init); -MODULE_AUTHOR("Jack and Alan Cox"); /* Update this */ +MODULE_AUTHOR("Jack Lee, Alan Cox"); MODULE_DESCRIPTION("PCI driver module for the ITE 8213"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 78281c5350029e3fa21758d6db9b45ffc7bf72a1 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 7 Feb 2007 18:19:32 +0100 Subject: IDE Driver for Delkin/Lexar/etc.. cardbus CF adapter On Thursday 11 January 2007 23:17, Bartlomiej Zolnierkiewicz wrote: > > My working IDE tree (against Linus' tree) now resides here: > > http://kernel.org/pub/linux/kernel/people/bart/pata-2.6/patches/ Bart, here's a driver I've been keeping out-of-tree for the past couple of years. This is for the Delking/Lexar/ASKA/etc.. 32-bit cardbus IDE CompactFlash adapter card. It's probably way out of sync with the latest driver model (??), but it still builds/works. I'm not interested in doing much of a rewrite, other than for libata someday, as I no longer use the card myself. But lots of other people do seem to use it, so it might be nice to see it "in-tree". Signed-off-by: Mark Lord Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 7 +++ drivers/ide/pci/Makefile | 1 + drivers/ide/pci/delkin_cb.c | 140 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) create mode 100644 drivers/ide/pci/delkin_cb.c (limited to 'drivers/ide') diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index d781b2cd3d6..0e511ca50b8 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -167,6 +167,13 @@ config BLK_DEV_IDECS Support for Compact Flash cards, outboard IDE disks, tape drives, and CD-ROM drives connected through a PCMCIA card. +config BLK_DEV_DELKIN + tristate "Cardbus IDE support (Delkin/ASKA/Workbit)" + depends on CARDBUS && PCI + help + Support for Delkin, ASKA, and Workbit Cardbus CompactFlash + Adapters. This may also work for similar SD and XD adapters. + config BLK_DEV_IDECD tristate "Include IDE/ATAPI CDROM support" ---help--- diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile index 64776ab4329..6591ff4753c 100644 --- a/drivers/ide/pci/Makefile +++ b/drivers/ide/pci/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o obj-$(CONFIG_BLK_DEV_CS5535) += cs5535.o obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o +obj-$(CONFIG_BLK_DEV_DELKIN) += delkin_cb.o obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o obj-$(CONFIG_BLK_DEV_IT8213) += it8213.o diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c new file mode 100644 index 00000000000..e2672fc65d3 --- /dev/null +++ b/drivers/ide/pci/delkin_cb.c @@ -0,0 +1,140 @@ +/* + * linux/drivers/ide/pci/delkin_cb.c + * + * Created 20 Oct 2004 by Mark Lord + * + * Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter + * + * Modeled after the 16-bit PCMCIA driver: ide-cs.c + * + * This is slightly peculiar, in that it is a PCI driver, + * but is NOT an IDE PCI driver -- the IDE layer does not directly + * support hot insertion/removal of PCI interfaces, so this driver + * is unable to use the IDE PCI interfaces. Instead, it uses the + * same interfaces as the ide-cs (PCMCIA) driver uses. + * On the plus side, the driver is also smaller/simpler this way. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * No chip documentation has yet been found, + * so these configuration values were pulled from + * a running Win98 system using "debug". + * This gives around 3MByte/second read performance, + * which is about 2/3 of what the chip is capable of. + * + * There is also a 4KByte mmio region on the card, + * but its purpose has yet to be reverse-engineered. + */ +static const u8 setup[] = { + 0x00, 0x05, 0xbe, 0x01, 0x20, 0x8f, 0x00, 0x00, + 0xa4, 0x1f, 0xb3, 0x1b, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa4, 0x83, 0x02, 0x13, +}; + +static int __devinit +delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id) +{ + unsigned long base; + hw_regs_t hw; + ide_hwif_t *hwif = NULL; + ide_drive_t *drive; + int i, rc; + + rc = pci_enable_device(dev); + if (rc) { + printk(KERN_ERR "delkin_cb: pci_enable_device failed (%d)\n", rc); + return rc; + } + rc = pci_request_regions(dev, "delkin_cb"); + if (rc) { + printk(KERN_ERR "delkin_cb: pci_request_regions failed (%d)\n", rc); + pci_disable_device(dev); + return rc; + } + base = pci_resource_start(dev, 0); + outb(0x02, base + 0x1e); /* set nIEN to block interrupts */ + inb(base + 0x17); /* read status to clear interrupts */ + for (i = 0; i < sizeof(setup); ++i) { + if (setup[i]) + outb(setup[i], base + i); + } + pci_release_regions(dev); /* IDE layer handles regions itself */ + + memset(&hw, 0, sizeof(hw)); + ide_std_init_ports(&hw, base + 0x10, base + 0x1e); + hw.irq = dev->irq; + hw.chipset = ide_pci; /* this enables IRQ sharing */ + + rc = ide_register_hw_with_fixup(&hw, &hwif, ide_undecoded_slave); + if (rc < 0) { + printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc); + pci_disable_device(dev); + return -ENODEV; + } + pci_set_drvdata(dev, hwif); + hwif->pci_dev = dev; + drive = &hwif->drives[0]; + if (drive->present) { + drive->io_32bit = 1; + drive->unmask = 1; + } + return 0; +} + +static void +delkin_cb_remove (struct pci_dev *dev) +{ + ide_hwif_t *hwif = pci_get_drvdata(dev); + + if (hwif) + ide_unregister(hwif->index); + pci_disable_device(dev); +} + +static struct pci_device_id delkin_cb_pci_tbl[] __devinitdata = { + { 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { 0, }, +}; +MODULE_DEVICE_TABLE(pci, delkin_cb_pci_tbl); + +static struct pci_driver driver = { + .name = "Delkin-ASKA-Workbit Cardbus IDE", + .id_table = delkin_cb_pci_tbl, + .probe = delkin_cb_probe, + .remove = delkin_cb_remove, +}; + +static int +delkin_cb_init (void) +{ + return pci_module_init(&driver); +} + +static void +delkin_cb_exit (void) +{ + pci_unregister_driver(&driver); +} + +module_init(delkin_cb_init); +module_exit(delkin_cb_exit); + +MODULE_AUTHOR("Mark Lord"); +MODULE_DESCRIPTION("Basic support for Delkin/ASKA/Workbit Cardbus IDE"); +MODULE_LICENSE("GPL"); + -- cgit v1.2.3 From e3a59b4d9378522479609042836ae930305a67fe Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 7 Feb 2007 18:19:37 +0100 Subject: ACPI support for IDE devices This patch implements ACPI integration for generic IDE devices. The ACPI spec mandates that some methods are called during suspend and resume. And consequently there most modern Laptops cannot resume properly without it. According to the spec, we should call '_GTM' (Get Timing) upon suspend to store the current IDE adapter settings. Upon resume we should call '_STM' (Set Timing) to initialize the adapter with the stored settings; afterwards '_GTF' (Get Taskfile) should be called which returns a buffer with some IDE initialisation commands. Those commands should be passed to the drive. There are two module params which control the behaviour of this patch: 'ide=noacpi' Do not call any ACPI methods (Disables any ACPI method calls) 'ide=acpigtf' Enable execution of _GTF methods upon resume. Has no effect if 'ide=noacpi' is set. 'ide=acpionboot' Enable execution of ACPI methods during boot. This might be required on some machines if 'ide=acpigtf' is selected as some machines modify the _GTF information depending on the drive identification passed down with _STM. Signed-off-by: Hannes Reinecke Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 7 + drivers/ide/Makefile | 1 + drivers/ide/ide-acpi.c | 696 ++++++++++++++++++++++++++++++++++++++++++++++++ drivers/ide/ide-probe.c | 3 + drivers/ide/ide.c | 36 +++ 5 files changed, 743 insertions(+) create mode 100644 drivers/ide/ide-acpi.c (limited to 'drivers/ide') diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 0e511ca50b8..ec03341d2bd 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -271,6 +271,13 @@ config BLK_DEV_IDESCSI If both this SCSI emulation and native ATAPI support are compiled into the kernel, the native support will be used. +config BLK_DEV_IDEACPI + bool "IDE ACPI support" + depends on ACPI + ---help--- + Implement ACPI support for generic IDE devices. On modern + machines ACPI support is required to properly handle ACPI S3 states. + config IDE_TASK_IOCTL bool "IDE Taskfile Access" help diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 569fae71750..d9f029e8ff7 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -22,6 +22,7 @@ ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o ide-core-$(CONFIG_BLK_DEV_IDEDMA) += ide-dma.o ide-core-$(CONFIG_PROC_FS) += ide-proc.o ide-core-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o +ide-core-$(CONFIG_BLK_DEV_IDEACPI) += ide-acpi.o # built-in only drivers from arm/ ide-core-$(CONFIG_IDE_ARM) += arm/ide_arm.o diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c new file mode 100644 index 00000000000..1eb734951dc --- /dev/null +++ b/drivers/ide/ide-acpi.c @@ -0,0 +1,696 @@ +/* + * ide-acpi.c + * Provides ACPI support for IDE drives. + * + * Copyright (C) 2005 Intel Corp. + * Copyright (C) 2005 Randy Dunlap + * Copyright (C) 2006 SUSE Linux Products GmbH + * Copyright (C) 2006 Hannes Reinecke + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define REGS_PER_GTF 7 +struct taskfile_array { + u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ +}; + +struct GTM_buffer { + u32 PIO_speed0; + u32 DMA_speed0; + u32 PIO_speed1; + u32 DMA_speed1; + u32 GTM_flags; +}; + +struct ide_acpi_drive_link { + ide_drive_t *drive; + acpi_handle obj_handle; + u8 idbuff[512]; +}; + +struct ide_acpi_hwif_link { + ide_hwif_t *hwif; + acpi_handle obj_handle; + struct GTM_buffer gtm; + struct ide_acpi_drive_link master; + struct ide_acpi_drive_link slave; +}; + +#undef DEBUGGING +/* note: adds function name and KERN_DEBUG */ +#ifdef DEBUGGING +#define DEBPRINT(fmt, args...) \ + printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args) +#else +#define DEBPRINT(fmt, args...) do {} while (0) +#endif /* DEBUGGING */ + +extern int ide_noacpi; +extern int ide_noacpitfs; +extern int ide_noacpionboot; + +/** + * ide_get_dev_handle - finds acpi_handle and PCI device.function + * @dev: device to locate + * @handle: returned acpi_handle for @dev + * @pcidevfn: return PCI device.func for @dev + * + * Returns the ACPI object handle to the corresponding PCI device. + * + * Returns 0 on success, <0 on error. + */ +static int ide_get_dev_handle(struct device *dev, acpi_handle *handle, + acpi_integer *pcidevfn) +{ + struct pci_dev *pdev = to_pci_dev(dev); + unsigned int bus, devnum, func; + acpi_integer addr; + acpi_handle dev_handle; + struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER, + .pointer = NULL}; + acpi_status status; + struct acpi_device_info *dinfo = NULL; + int ret = -ENODEV; + + bus = pdev->bus->number; + devnum = PCI_SLOT(pdev->devfn); + func = PCI_FUNC(pdev->devfn); + /* ACPI _ADR encoding for PCI bus: */ + addr = (acpi_integer)(devnum << 16 | func); + + DEBPRINT("ENTER: pci %02x:%02x.%01x\n", bus, devnum, func); + + dev_handle = DEVICE_ACPI_HANDLE(dev); + if (!dev_handle) { + DEBPRINT("no acpi handle for device\n"); + goto err; + } + + status = acpi_get_object_info(dev_handle, &buffer); + if (ACPI_FAILURE(status)) { + DEBPRINT("get_object_info for device failed\n"); + goto err; + } + dinfo = buffer.pointer; + if (dinfo && (dinfo->valid & ACPI_VALID_ADR) && + dinfo->address == addr) { + *pcidevfn = addr; + *handle = dev_handle; + } else { + DEBPRINT("get_object_info for device has wrong " + " address: %llu, should be %u\n", + dinfo ? (unsigned long long)dinfo->address : -1ULL, + (unsigned int)addr); + goto err; + } + + DEBPRINT("for dev=0x%x.%x, addr=0x%llx, *handle=0x%p\n", + devnum, func, (unsigned long long)addr, *handle); + ret = 0; +err: + kfree(dinfo); + return ret; +} + +/** + * ide_acpi_hwif_get_handle - Get ACPI object handle for a given hwif + * @hwif: device to locate + * + * Retrieves the object handle for a given hwif. + * + * Returns handle on success, 0 on error. + */ +static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif) +{ + struct device *dev = hwif->gendev.parent; + acpi_handle dev_handle; + acpi_integer pcidevfn; + acpi_handle chan_handle; + int err; + + DEBPRINT("ENTER: device %s\n", hwif->name); + + if (!dev) { + DEBPRINT("no PCI device for %s\n", hwif->name); + return NULL; + } + + err = ide_get_dev_handle(dev, &dev_handle, &pcidevfn); + if (err < 0) { + DEBPRINT("ide_get_dev_handle failed (%d)\n", err); + return NULL; + } + + /* get child objects of dev_handle == channel objects, + * + _their_ children == drive objects */ + /* channel is hwif->channel */ + chan_handle = acpi_get_child(dev_handle, hwif->channel); + DEBPRINT("chan adr=%d: handle=0x%p\n", + hwif->channel, chan_handle); + + return chan_handle; +} + +/** + * ide_acpi_drive_get_handle - Get ACPI object handle for a given drive + * @drive: device to locate + * + * Retrieves the object handle of a given drive. According to the ACPI + * spec the drive is a child of the hwif. + * + * Returns handle on success, 0 on error. + */ +static acpi_handle ide_acpi_drive_get_handle(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + int port; + acpi_handle drive_handle; + + if (!hwif->acpidata) + return NULL; + + if (!hwif->acpidata->obj_handle) + return NULL; + + port = hwif->channel ? drive->dn - 2: drive->dn; + + DEBPRINT("ENTER: %s at channel#: %d port#: %d\n", + drive->name, hwif->channel, port); + + + /* TBD: could also check ACPI object VALID bits */ + drive_handle = acpi_get_child(hwif->acpidata->obj_handle, port); + DEBPRINT("drive %s handle 0x%p\n", drive->name, drive_handle); + + return drive_handle; +} + +/** + * do_drive_get_GTF - get the drive bootup default taskfile settings + * @drive: the drive for which the taskfile settings should be retrieved + * @gtf_length: number of bytes of _GTF data returned at @gtf_address + * @gtf_address: buffer containing _GTF taskfile arrays + * + * The _GTF method has no input parameters. + * It returns a variable number of register set values (registers + * hex 1F1..1F7, taskfiles). + * The is not known in advance, so have ACPI-CA + * allocate the buffer as needed and return it, then free it later. + * + * The returned @gtf_length and @gtf_address are only valid if the + * function return value is 0. + */ +static int do_drive_get_GTF(ide_drive_t *drive, + unsigned int *gtf_length, unsigned long *gtf_address, + unsigned long *obj_loc) +{ + acpi_status status; + struct acpi_buffer output; + union acpi_object *out_obj; + ide_hwif_t *hwif = HWIF(drive); + struct device *dev = hwif->gendev.parent; + int err = -ENODEV; + int port; + + *gtf_length = 0; + *gtf_address = 0UL; + *obj_loc = 0UL; + + if (ide_noacpi) + return 0; + + if (!dev) { + DEBPRINT("no PCI device for %s\n", hwif->name); + goto out; + } + + if (!hwif->acpidata) { + DEBPRINT("no ACPI data for %s\n", hwif->name); + goto out; + } + + port = hwif->channel ? drive->dn - 2: drive->dn; + + if (!drive->acpidata) { + if (port == 0) { + drive->acpidata = &hwif->acpidata->master; + hwif->acpidata->master.drive = drive; + } else { + drive->acpidata = &hwif->acpidata->slave; + hwif->acpidata->slave.drive = drive; + } + } + + DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n", + hwif->name, dev->bus_id, port, hwif->channel); + + if (!drive->present) { + DEBPRINT("%s drive %d:%d not present\n", + hwif->name, hwif->channel, port); + goto out; + } + + /* Get this drive's _ADR info. if not already known. */ + if (!drive->acpidata->obj_handle) { + drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive); + if (!drive->acpidata->obj_handle) { + DEBPRINT("No ACPI object found for %s\n", + drive->name); + goto out; + } + } + + /* Setting up output buffer */ + output.length = ACPI_ALLOCATE_BUFFER; + output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ + + /* _GTF has no input parameters */ + err = -EIO; + status = acpi_evaluate_object(drive->acpidata->obj_handle, "_GTF", + NULL, &output); + if (ACPI_FAILURE(status)) { + printk(KERN_DEBUG + "%s: Run _GTF error: status = 0x%x\n", + __FUNCTION__, status); + goto out; + } + + if (!output.length || !output.pointer) { + DEBPRINT("Run _GTF: " + "length or ptr is NULL (0x%llx, 0x%p)\n", + (unsigned long long)output.length, + output.pointer); + goto out; + } + + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) { + DEBPRINT("Run _GTF: error: " + "expected object type of ACPI_TYPE_BUFFER, " + "got 0x%x\n", out_obj->type); + err = -ENOENT; + kfree(output.pointer); + goto out; + } + + if (!out_obj->buffer.length || !out_obj->buffer.pointer || + out_obj->buffer.length % REGS_PER_GTF) { + printk(KERN_ERR + "%s: unexpected GTF length (%d) or addr (0x%p)\n", + __FUNCTION__, out_obj->buffer.length, + out_obj->buffer.pointer); + err = -ENOENT; + kfree(output.pointer); + goto out; + } + + *gtf_length = out_obj->buffer.length; + *gtf_address = (unsigned long)out_obj->buffer.pointer; + *obj_loc = (unsigned long)out_obj; + DEBPRINT("returning gtf_length=%d, gtf_address=0x%lx, obj_loc=0x%lx\n", + *gtf_length, *gtf_address, *obj_loc); + err = 0; +out: + return err; +} + +/** + * taskfile_load_raw - send taskfile registers to drive + * @drive: drive to which output is sent + * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) + * + * Outputs IDE taskfile to the drive. + */ +static int taskfile_load_raw(ide_drive_t *drive, + const struct taskfile_array *gtf) +{ + ide_task_t args; + int err = 0; + + DEBPRINT("(0x1f1-1f7): hex: " + "%02x %02x %02x %02x %02x %02x %02x\n", + gtf->tfa[0], gtf->tfa[1], gtf->tfa[2], + gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]); + + memset(&args, 0, sizeof(ide_task_t)); + args.command_type = IDE_DRIVE_TASK_NO_DATA; + args.data_phase = TASKFILE_IN; + args.handler = &task_no_data_intr; + + /* convert gtf to IDE Taskfile */ + args.tfRegister[1] = gtf->tfa[0]; /* 0x1f1 */ + args.tfRegister[2] = gtf->tfa[1]; /* 0x1f2 */ + args.tfRegister[3] = gtf->tfa[2]; /* 0x1f3 */ + args.tfRegister[4] = gtf->tfa[3]; /* 0x1f4 */ + args.tfRegister[5] = gtf->tfa[4]; /* 0x1f5 */ + args.tfRegister[6] = gtf->tfa[5]; /* 0x1f6 */ + args.tfRegister[7] = gtf->tfa[6]; /* 0x1f7 */ + + if (ide_noacpitfs) { + DEBPRINT("_GTF execution disabled\n"); + return err; + } + + err = ide_raw_taskfile(drive, &args, NULL); + if (err) + printk(KERN_ERR "%s: ide_raw_taskfile failed: %u\n", + __FUNCTION__, err); + + return err; +} + +/** + * do_drive_set_taskfiles - write the drive taskfile settings from _GTF + * @drive: the drive to which the taskfile command should be sent + * @gtf_length: total number of bytes of _GTF taskfiles + * @gtf_address: location of _GTF taskfile arrays + * + * Write {gtf_address, length gtf_length} in groups of + * REGS_PER_GTF bytes. + */ +static int do_drive_set_taskfiles(ide_drive_t *drive, + unsigned int gtf_length, + unsigned long gtf_address) +{ + int rc = -ENODEV, err; + int gtf_count = gtf_length / REGS_PER_GTF; + int ix; + struct taskfile_array *gtf; + + if (ide_noacpi) + return 0; + + DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn); + + if (!drive->present) + goto out; + if (!gtf_count) /* shouldn't be here */ + goto out; + + DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n", + gtf_length, gtf_length, gtf_count, gtf_address); + + if (gtf_length % REGS_PER_GTF) { + printk(KERN_ERR "%s: unexpected GTF length (%d)\n", + __FUNCTION__, gtf_length); + goto out; + } + + rc = 0; + for (ix = 0; ix < gtf_count; ix++) { + gtf = (struct taskfile_array *) + (gtf_address + ix * REGS_PER_GTF); + + /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */ + err = taskfile_load_raw(drive, gtf); + if (err) + rc = err; + } + +out: + return rc; +} + +/** + * ide_acpi_exec_tfs - get then write drive taskfile settings + * @drive: the drive for which the taskfile settings should be + * written. + * + * According to the ACPI spec this should be called after _STM + * has been evaluated for the interface. Some ACPI vendors interpret + * that as a hard requirement and modify the taskfile according + * to the Identify Drive information passed down with _STM. + * So one should really make sure to call this only after _STM has + * been executed. + */ +int ide_acpi_exec_tfs(ide_drive_t *drive) +{ + int ret; + unsigned int gtf_length; + unsigned long gtf_address; + unsigned long obj_loc; + + if (ide_noacpi) + return 0; + + DEBPRINT("call get_GTF, drive=%s port=%d\n", drive->name, drive->dn); + + ret = do_drive_get_GTF(drive, >f_length, >f_address, &obj_loc); + if (ret < 0) { + DEBPRINT("get_GTF error (%d)\n", ret); + return ret; + } + + DEBPRINT("call set_taskfiles, drive=%s\n", drive->name); + + ret = do_drive_set_taskfiles(drive, gtf_length, gtf_address); + kfree((void *)obj_loc); + if (ret < 0) { + DEBPRINT("set_taskfiles error (%d)\n", ret); + } + + DEBPRINT("ret=%d\n", ret); + + return ret; +} +EXPORT_SYMBOL_GPL(ide_acpi_exec_tfs); + +/** + * ide_acpi_get_timing - get the channel (controller) timings + * @hwif: target IDE interface (channel) + * + * This function executes the _GTM ACPI method for the target channel. + * + */ +void ide_acpi_get_timing(ide_hwif_t *hwif) +{ + acpi_status status; + struct acpi_buffer output; + union acpi_object *out_obj; + + if (ide_noacpi) + return; + + DEBPRINT("ENTER:\n"); + + if (!hwif->acpidata) { + DEBPRINT("no ACPI data for %s\n", hwif->name); + return; + } + + /* Setting up output buffer for _GTM */ + output.length = ACPI_ALLOCATE_BUFFER; + output.pointer = NULL; /* ACPI-CA sets this; save/free it later */ + + /* _GTM has no input parameters */ + status = acpi_evaluate_object(hwif->acpidata->obj_handle, "_GTM", + NULL, &output); + + DEBPRINT("_GTM status: %d, outptr: 0x%p, outlen: 0x%llx\n", + status, output.pointer, + (unsigned long long)output.length); + + if (ACPI_FAILURE(status)) { + DEBPRINT("Run _GTM error: status = 0x%x\n", status); + return; + } + + if (!output.length || !output.pointer) { + DEBPRINT("Run _GTM: length or ptr is NULL (0x%llx, 0x%p)\n", + (unsigned long long)output.length, + output.pointer); + kfree(output.pointer); + return; + } + + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) { + kfree(output.pointer); + DEBPRINT("Run _GTM: error: " + "expected object type of ACPI_TYPE_BUFFER, " + "got 0x%x\n", out_obj->type); + return; + } + + if (!out_obj->buffer.length || !out_obj->buffer.pointer || + out_obj->buffer.length != sizeof(struct GTM_buffer)) { + kfree(output.pointer); + printk(KERN_ERR + "%s: unexpected _GTM length (0x%x)[should be 0x%x] or addr (0x%p)\n", + __FUNCTION__, out_obj->buffer.length, + sizeof(struct GTM_buffer), out_obj->buffer.pointer); + return; + } + + memcpy(&hwif->acpidata->gtm, out_obj->buffer.pointer, + sizeof(struct GTM_buffer)); + + DEBPRINT("_GTM info: ptr: 0x%p, len: 0x%x, exp.len: 0x%Zx\n", + out_obj->buffer.pointer, out_obj->buffer.length, + sizeof(struct GTM_buffer)); + + DEBPRINT("_GTM fields: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", + hwif->acpidata->gtm.PIO_speed0, + hwif->acpidata->gtm.DMA_speed0, + hwif->acpidata->gtm.PIO_speed1, + hwif->acpidata->gtm.DMA_speed1, + hwif->acpidata->gtm.GTM_flags); + + kfree(output.pointer); +} +EXPORT_SYMBOL_GPL(ide_acpi_get_timing); + +/** + * ide_acpi_push_timing - set the channel (controller) timings + * @hwif: target IDE interface (channel) + * + * This function executes the _STM ACPI method for the target channel. + * + * _STM requires Identify Drive data, which has to passed as an argument. + * Unfortunately hd_driveid is a mangled version which we can't readily + * use; hence we'll get the information afresh. + */ +void ide_acpi_push_timing(ide_hwif_t *hwif) +{ + acpi_status status; + struct acpi_object_list input; + union acpi_object in_params[3]; + struct ide_acpi_drive_link *master = &hwif->acpidata->master; + struct ide_acpi_drive_link *slave = &hwif->acpidata->slave; + + if (ide_noacpi) + return; + + DEBPRINT("ENTER:\n"); + + if (!hwif->acpidata) { + DEBPRINT("no ACPI data for %s\n", hwif->name); + return; + } + + /* Give the GTM buffer + drive Identify data to the channel via the + * _STM method: */ + /* setup input parameters buffer for _STM */ + input.count = 3; + input.pointer = in_params; + in_params[0].type = ACPI_TYPE_BUFFER; + in_params[0].buffer.length = sizeof(struct GTM_buffer); + in_params[0].buffer.pointer = (u8 *)&hwif->acpidata->gtm; + in_params[1].type = ACPI_TYPE_BUFFER; + in_params[1].buffer.length = sizeof(struct hd_driveid); + in_params[1].buffer.pointer = (u8 *)&master->idbuff; + in_params[2].type = ACPI_TYPE_BUFFER; + in_params[2].buffer.length = sizeof(struct hd_driveid); + in_params[2].buffer.pointer = (u8 *)&slave->idbuff; + /* Output buffer: _STM has no output */ + + status = acpi_evaluate_object(hwif->acpidata->obj_handle, "_STM", + &input, NULL); + + if (ACPI_FAILURE(status)) { + DEBPRINT("Run _STM error: status = 0x%x\n", status); + } + DEBPRINT("_STM status: %d\n", status); +} +EXPORT_SYMBOL_GPL(ide_acpi_push_timing); + +/** + * ide_acpi_init - initialize the ACPI link for an IDE interface + * @hwif: target IDE interface (channel) + * + * The ACPI spec is not quite clear when the drive identify buffer + * should be obtained. Calling IDENTIFY DEVICE during shutdown + * is not the best of ideas as the drive might already being put to + * sleep. And obviously we can't call it during resume. + * So we get the information during startup; but this means that + * any changes during run-time will be lost after resume. + */ +void ide_acpi_init(ide_hwif_t *hwif) +{ + int unit; + int err; + struct ide_acpi_drive_link *master; + struct ide_acpi_drive_link *slave; + + hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL); + if (!hwif->acpidata) + return; + + hwif->acpidata->obj_handle = ide_acpi_hwif_get_handle(hwif); + if (!hwif->acpidata->obj_handle) { + DEBPRINT("no ACPI object for %s found\n", hwif->name); + kfree(hwif->acpidata); + hwif->acpidata = NULL; + return; + } + + /* + * The ACPI spec mandates that we send information + * for both drives, regardless whether they are connected + * or not. + */ + hwif->acpidata->master.drive = &hwif->drives[0]; + hwif->drives[0].acpidata = &hwif->acpidata->master; + master = &hwif->acpidata->master; + + hwif->acpidata->slave.drive = &hwif->drives[1]; + hwif->drives[1].acpidata = &hwif->acpidata->slave; + slave = &hwif->acpidata->slave; + + + /* + * Send IDENTIFY for each drive + */ + if (master->drive->present) { + err = taskfile_lib_get_identify(master->drive, master->idbuff); + if (err) { + DEBPRINT("identify device %s failed (%d)\n", + master->drive->name, err); + } + } + + if (slave->drive->present) { + err = taskfile_lib_get_identify(slave->drive, slave->idbuff); + if (err) { + DEBPRINT("identify device %s failed (%d)\n", + slave->drive->name, err); + } + } + + if (ide_noacpionboot) { + DEBPRINT("ACPI methods disabled on boot\n"); + return; + } + + /* + * ACPI requires us to call _STM on startup + */ + ide_acpi_get_timing(hwif); + ide_acpi_push_timing(hwif); + + for (unit = 0; unit < MAX_DRIVES; ++unit) { + ide_drive_t *drive = &hwif->drives[unit]; + + if (drive->present) { + /* Execute ACPI startup code */ + ide_acpi_exec_tfs(drive); + } + } +} +EXPORT_SYMBOL_GPL(ide_acpi_init); diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 5a5c565a32a..176bbc850d6 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1384,6 +1384,9 @@ static int hwif_init(ide_hwif_t *hwif) done: init_gendisk(hwif); + + ide_acpi_init(hwif); + hwif->present = 1; /* success */ return 1; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 6c9bd5165bd..c750f6ce770 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -187,6 +187,12 @@ int noautodma = 1; EXPORT_SYMBOL(noautodma); +#ifdef CONFIG_BLK_DEV_IDEACPI +int ide_noacpi = 0; +int ide_noacpitfs = 1; +int ide_noacpionboot = 1; +#endif + /* * This is declared extern in ide.h, for access by other IDE modules: */ @@ -1214,10 +1220,15 @@ EXPORT_SYMBOL(system_bus_clock); static int generic_ide_suspend(struct device *dev, pm_message_t mesg) { ide_drive_t *drive = dev->driver_data; + ide_hwif_t *hwif = HWIF(drive); struct request rq; struct request_pm_state rqpm; ide_task_t args; + /* Call ACPI _GTM only once */ + if (!(drive->dn % 2)) + ide_acpi_get_timing(hwif); + memset(&rq, 0, sizeof(rq)); memset(&rqpm, 0, sizeof(rqpm)); memset(&args, 0, sizeof(args)); @@ -1235,10 +1246,17 @@ static int generic_ide_suspend(struct device *dev, pm_message_t mesg) static int generic_ide_resume(struct device *dev) { ide_drive_t *drive = dev->driver_data; + ide_hwif_t *hwif = HWIF(drive); struct request rq; struct request_pm_state rqpm; ide_task_t args; + /* Call ACPI _STM only once */ + if (!(drive->dn % 2)) + ide_acpi_push_timing(hwif); + + ide_acpi_exec_tfs(drive); + memset(&rq, 0, sizeof(rq)); memset(&rqpm, 0, sizeof(rqpm)); memset(&args, 0, sizeof(args)); @@ -1543,6 +1561,24 @@ static int __init ide_setup(char *s) } #endif /* CONFIG_BLK_DEV_IDEPCI */ +#ifdef CONFIG_BLK_DEV_IDEACPI + if (!strcmp(s, "ide=noacpi")) { + //printk(" : Disable IDE ACPI support.\n"); + ide_noacpi = 1; + return 1; + } + if (!strcmp(s, "ide=acpigtf")) { + //printk(" : Enable IDE ACPI _GTF support.\n"); + ide_noacpitfs = 0; + return 1; + } + if (!strcmp(s, "ide=acpionboot")) { + //printk(" : Call IDE ACPI methods on boot.\n"); + ide_noacpionboot = 0; + return 1; + } +#endif /* CONFIG_BLK_DEV_IDEACPI */ + /* * Look for drive options: "hdx=" */ -- cgit v1.2.3 From 1e8f34f7d88c969a06229a786241839d49dd63e3 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 7 Feb 2007 18:19:42 +0100 Subject: ide-acpi support warning fix drivers/ide/ide-acpi.c: In function 'ide_acpi_get_timing': drivers/ide/ide-acpi.c:537: warning: format '%x' expects type 'unsigned int', but argument 4 has type 'long unsigned int' Signed-off-by: Andrew Morton Signed-off-by: Hannes Reinecke Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 1eb734951dc..17aea65d7dd 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -532,9 +532,10 @@ void ide_acpi_get_timing(ide_hwif_t *hwif) out_obj->buffer.length != sizeof(struct GTM_buffer)) { kfree(output.pointer); printk(KERN_ERR - "%s: unexpected _GTM length (0x%x)[should be 0x%x] or addr (0x%p)\n", - __FUNCTION__, out_obj->buffer.length, - sizeof(struct GTM_buffer), out_obj->buffer.pointer); + "%s: unexpected _GTM length (0x%x)[should be 0x%zx] or " + "addr (0x%p)\n", + __FUNCTION__, out_obj->buffer.length, + sizeof(struct GTM_buffer), out_obj->buffer.pointer); return; } -- cgit v1.2.3 From 725522b5453dd680412f2b6463a988e4fd148757 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 15 Jan 2007 11:50:02 -0800 Subject: PCI: add the sysfs driver name to all modules This adds the module name to all PCI drivers, if they are built into the kernel or not. It will show up in /sys/modules/MODULE_NAME/drivers/ It also fixes up the IDE core, which was calling __pci_register_driver() directly. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/ide/setup-pci.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/ide') diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 695e23904d3..a52c80fe7d3 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -783,10 +783,11 @@ static LIST_HEAD(ide_pci_drivers); * Returns are the same as for pci_register_driver */ -int __ide_pci_register_driver(struct pci_driver *driver, struct module *module) +int __ide_pci_register_driver(struct pci_driver *driver, struct module *module, + const char *mod_name) { if(!pre_init) - return __pci_register_driver(driver, module); + return __pci_register_driver(driver, module, mod_name); driver->driver.owner = module; list_add_tail(&driver->node, &ide_pci_drivers); return 0; @@ -862,6 +863,6 @@ void __init ide_scan_pcibus (int scan_direction) { list_del(l); d = list_entry(l, struct pci_driver, node); - __pci_register_driver(d, d->driver.owner); + __pci_register_driver(d, d->driver.owner, d->driver.mod_name); } } -- cgit v1.2.3