Index: drivers/ide/pci/ns87415.c =================================================================== RCS file: /var/cvs/linux-2.6/drivers/ide/pci/ns87415.c,v retrieving revision 1.17 diff -u -p -r1.17 ns87415.c --- drivers/ide/pci/ns87415.c 13 Sep 2004 15:23:04 -0000 1.17 +++ drivers/ide/pci/ns87415.c 28 Sep 2004 05:20:37 -0000 @@ -4,6 +4,7 @@ * 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 */ @@ -24,8 +25,74 @@ #include #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; +} +#else +static void __devinit superio_ide_init_iops (struct hwif_s *hwif) {} #endif static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 }; @@ -135,8 +202,11 @@ static int ns87415_ide_dma_check (ide_dr static void __init init_iops_ns87415(ide_hwif_t *hwif) { -#ifdef CONFIG_SUPERIO - superio_ide_init_iops(hwif); +#ifdef CONFIG_PARISC + if (PCI_SLOT(hwif->pci_dev->devfn) == 0xE) { + /* Built-in - assume it's under superio. */ + superio_ide_init_iops(hwif); + } #endif } @@ -153,10 +223,6 @@ static void __init init_hwif_ns87415 (id 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 @@ -227,6 +293,7 @@ static void __init init_hwif_ns87415 (id static ide_pci_device_t ns87415_chipset __devinitdata = { .name = "NS87415", + .init_iops = init_iops_ns87415, .init_hwif = init_hwif_ns87415, .channels = 2, .autodma = AUTODMA, Index: drivers/parisc/superio.c =================================================================== RCS file: /var/cvs/linux-2.6/drivers/parisc/superio.c,v retrieving revision 1.10 diff -u -p -r1.10 superio.c --- drivers/parisc/superio.c 13 Sep 2004 15:23:20 -0000 1.10 +++ drivers/parisc/superio.c 28 Sep 2004 05:20:38 -0000 @@ -69,15 +69,12 @@ #include #include #include -#include #include #include #include #include -#define SUPERIO_IDE_MAX_RETRIES 25 - static struct superio_device sio_dev; @@ -101,16 +98,20 @@ superio_interrupt(int irq, void *devp, s results = inb(IC_PIC1+0); + /* + * Bit 7: 1 = active Interrupt; 0 = no Interrupt pending + * Bits 6-3: zero + * Bits 2-0: highest priority, active requesting interrupt ID (0-7) + */ if ((results & 0x80) == 0) { -#ifndef CONFIG_SMP - /* HACK: need to investigate why this happens if SMP enabled */ - BUG(); /* This shouldn't happen */ -#endif + /* I suspect "spurious" interrupts are from unmasking an IRQ. + * We don't know if an interrupt was/is pending and thus + * just call the handler for that IRQ as if it were pending. + */ return IRQ_HANDLED; } /* Check to see which device is interrupting */ - local_irq = results & 0x0f; if (local_irq == 2 || local_irq > 7) { @@ -136,8 +137,9 @@ superio_interrupt(int irq, void *devp, s sio->irq_region->data.irqbase + local_irq, regs); - /* set EOI */ - + /* set EOI - forces a new interrupt if a lower priority device + * still needs service. + */ outb((OCW2_SEOI|local_irq),IC_PIC1 + 0); return IRQ_HANDLED; } @@ -469,11 +471,6 @@ superio_parport_init(void) } -static u8 superio_ide_inb (unsigned long port); -static unsigned long superio_ide_status[2]; -static unsigned long superio_ide_select[2]; -static unsigned long superio_ide_dma_status[2]; - void superio_fixup_pci(struct pci_dev *pdev) { u8 prog; @@ -486,56 +483,6 @@ void superio_fixup_pci(struct pci_dev *p } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415, superio_fixup_pci); -/* 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); -} - -void __init 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 int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_id *id) { Index: include/asm-parisc/superio.h =================================================================== RCS file: /var/cvs/linux-2.6/include/asm-parisc/superio.h,v retrieving revision 1.4 diff -u -p -r1.4 superio.h --- include/asm-parisc/superio.h 11 Mar 2004 05:41:54 -0000 1.4 +++ include/asm-parisc/superio.h 28 Sep 2004 05:20:41 -0000 @@ -87,6 +87,5 @@ extern void superio_inform_irq(int irq); extern void superio_serial_init(void); /* called by rs_init() */ extern int superio_fixup_irq(struct pci_dev *pcidev); /* called by iosapic */ extern void superio_fixup_pci(struct pci_dev *pdev); -extern void superio_ide_init_iops (struct hwif_s *hwif); #endif /* _PARISC_SUPERIO_H */