X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fide%2Fpci%2Fns87415.c;h=8aaea4ea5549526c12b199d9d1bbe500509e53da;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=a5b6e7e5c8e788f7be90a2a519c850be4014fe79;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c index a5b6e7e5c..8aaea4ea5 100644 --- a/drivers/ide/pci/ns87415.c +++ b/drivers/ide/pci/ns87415.c @@ -4,11 +4,11 @@ * Copyright (C) 1997-1998 Mark Lord * Copyright (C) 1998 Eddie C. Dost * Copyright (C) 1999-2000 Andre Hedrick + * Copyright (C) 2004 Grant Grundler * * Inspired by an earlier effort from David S. Miller */ -#include #include #include #include @@ -25,6 +25,81 @@ #include +#ifdef CONFIG_SUPERIO +/* SUPERIO 87560 is a PoS chip that NatSem denies exists. + * Unfortunately, it's built-in on all Astro-based PA-RISC workstations + * which use the integrated NS87514 cell for CD-ROM support. + * i.e we have to support for CD-ROM installs. + * See drivers/parisc/superio.c for more gory details. + */ +#include + +static unsigned long superio_ide_status[2]; +static unsigned long superio_ide_select[2]; +static unsigned long superio_ide_dma_status[2]; + +#define SUPERIO_IDE_MAX_RETRIES 25 + +/* Because of a defect in Super I/O, all reads of the PCI DMA status + * registers, IDE status register and the IDE select register need to be + * retried + */ +static u8 superio_ide_inb (unsigned long port) +{ + if (port == superio_ide_status[0] || + port == superio_ide_status[1] || + port == superio_ide_select[0] || + port == superio_ide_select[1] || + port == superio_ide_dma_status[0] || + port == superio_ide_dma_status[1]) { + u8 tmp; + int retries = SUPERIO_IDE_MAX_RETRIES; + + /* printk(" [ reading port 0x%x with retry ] ", port); */ + + do { + tmp = inb(port); + if (tmp == 0) + udelay(50); + } while (tmp == 0 && retries-- > 0); + + return tmp; + } + + return inb(port); +} + +static void __devinit superio_ide_init_iops (struct hwif_s *hwif) +{ + u32 base, dmabase; + u8 tmp; + struct pci_dev *pdev = hwif->pci_dev; + u8 port = hwif->channel; + + base = pci_resource_start(pdev, port * 2) & ~3; + dmabase = pci_resource_start(pdev, 4) & ~3; + + superio_ide_status[port] = base + IDE_STATUS_OFFSET; + superio_ide_select[port] = base + IDE_SELECT_OFFSET; + superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa); + + /* Clear error/interrupt, enable dma */ + tmp = superio_ide_inb(superio_ide_dma_status[port]); + outb(tmp | 0x66, superio_ide_dma_status[port]); + + /* We need to override inb to workaround a SuperIO errata */ + hwif->INB = superio_ide_inb; +} + +static void __devinit init_iops_ns87415(ide_hwif_t *hwif) +{ + if (PCI_SLOT(hwif->pci_dev->devfn) == 0xE) { + /* Built-in - assume it's under superio. */ + superio_ide_init_iops(hwif); + } +} +#endif + static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; /* @@ -101,22 +176,11 @@ static int ns87415_ide_dma_end (ide_drive_t *drive) return (dma_stat & 7) != 4; } -static int ns87415_ide_dma_read (ide_drive_t *drive) -{ - /* select DMA xfer */ - ns87415_prepare_drive(drive, 1); - if (!(__ide_dma_read(drive))) - return 0; - /* DMA failed: select PIO xfer */ - ns87415_prepare_drive(drive, 0); - return 1; -} - -static int ns87415_ide_dma_write (ide_drive_t *drive) +static int ns87415_ide_dma_setup(ide_drive_t *drive) { /* select DMA xfer */ ns87415_prepare_drive(drive, 1); - if (!(__ide_dma_write(drive))) + if (!ide_dma_setup(drive)) return 0; /* DMA failed: select PIO xfer */ ns87415_prepare_drive(drive, 0); @@ -130,7 +194,7 @@ static int ns87415_ide_dma_check (ide_drive_t *drive) return __ide_dma_check(drive); } -static void __init init_hwif_ns87415 (ide_hwif_t *hwif) +static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; unsigned int ctrl, using_inta; @@ -143,10 +207,6 @@ static void __init init_hwif_ns87415 (ide_hwif_t *hwif) hwif->autodma = 0; hwif->selectproc = &ns87415_selectproc; - /* Set a good latency timer and cache line size value. */ - (void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); - /* FIXME: use pci_set_master() to ensure good latency timer value */ - /* * We cannot probe for IRQ: both ports share common IRQ on INTA. * Also, leave IRQ masked during drive probing, to prevent infinite @@ -204,8 +264,7 @@ static void __init init_hwif_ns87415 (ide_hwif_t *hwif) return; hwif->OUTB(0x60, hwif->dma_status); - hwif->ide_dma_read = &ns87415_ide_dma_read; - hwif->ide_dma_write = &ns87415_ide_dma_write; + hwif->dma_setup = &ns87415_ide_dma_setup; hwif->ide_dma_check = &ns87415_ide_dma_check; hwif->ide_dma_end = &ns87415_ide_dma_end; @@ -217,6 +276,9 @@ static void __init init_hwif_ns87415 (ide_hwif_t *hwif) static ide_pci_device_t ns87415_chipset __devinitdata = { .name = "NS87415", +#ifdef CONFIG_SUPERIO + .init_iops = init_iops_ns87415, +#endif .init_hwif = init_hwif_ns87415, .channels = 2, .autodma = AUTODMA, @@ -225,8 +287,7 @@ static ide_pci_device_t ns87415_chipset __devinitdata = { static int __devinit ns87415_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - ide_setup_pci_device(dev, &ns87415_chipset); - return 0; + return ide_setup_pci_device(dev, &ns87415_chipset); } static struct pci_device_id ns87415_pci_tbl[] = { @@ -236,12 +297,12 @@ static struct pci_device_id ns87415_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, ns87415_pci_tbl); static struct pci_driver driver = { - .name = "NS87415IDE", + .name = "NS87415_IDE", .id_table = ns87415_pci_tbl, .probe = ns87415_init_one, }; -static int ns87415_ide_init(void) +static int __init ns87415_ide_init(void) { return ide_pci_register_driver(&driver); }