Index: Makefile =================================================================== RCS file: /var/cvs/linux-2.6/Makefile,v retrieving revision 1.98 diff -u -p -r1.98 Makefile --- Makefile 20 Dec 2003 07:46:39 -0000 1.98 +++ Makefile 21 Dec 2003 03:35:47 -0000 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 0 -EXTRAVERSION = -pa2 +EXTRAVERSION = -pa3 # *DOCUMENTATION* # To see a list of typical targets execute "make help" Index: arch/parisc/kernel/firmware.c =================================================================== RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/firmware.c,v retrieving revision 1.4 diff -u -p -r1.4 firmware.c --- arch/parisc/kernel/firmware.c 1 Oct 2003 20:24:44 -0000 1.4 +++ arch/parisc/kernel/firmware.c 21 Dec 2003 03:35:48 -0000 @@ -1,10 +1,22 @@ -/* arch/parisc/kernel/pdc.c - safe pdc access routines +/* + * arch/parisc/kernel/firmware.c - safe PDC access routines + * + * PDC == Processor Dependent Code + * + * See http://www.parisc-linux.org/documentation/index.html + * for documentation describing the entry points and calling + * conventions defined below. * * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org) - * portions Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy) + * Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy) + * Copyright 2003 Grant Grundler * - * only these routines should be used out of the real kernel (i.e. everything - * using virtual addresses) for obvious reasons */ + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ /* I think it would be in everyone's best interest to follow this * guidelines when writing PDC wrappers: @@ -642,6 +654,49 @@ int pdc_pci_irt(unsigned long num_entrie return retval; } + +#if 0 /* UNTEST CODE - left here in case someone needs it */ + +/** + * pdc_pci_config_read - read PCI config space. + * @hpa token from PDC to indicate which PCI device + * @pci_addr configuration space address to read from + * + * Read PCI Configuration space *before* linux PCI subsystem is running. + */ +unsigned int pdc_pci_config_read(void *hpa, unsigned long cfg_addr) +{ + int retval; + spin_lock_irq(&pdc_lock); + pdc_result[0] = 0; + pdc_result[1] = 0; + retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_READ_CONFIG, + __pa(pdc_result), hpa, cfg_addr&~3UL, 4UL); + spin_unlock_irq(&pdc_lock); + return retval ? ~0 : (unsigned int) pdc_result[0]; +} + + +/** + * pdc_pci_config_write - read PCI config space. + * @hpa token from PDC to indicate which PCI device + * @pci_addr configuration space address to write + * @val value we want in the 32-bit register + * + * Write PCI Configuration space *before* linux PCI subsystem is running. + */ +void pdc_pci_config_write(void *hpa, unsigned long cfg_addr, unsigned int val) +{ + int retval; + spin_lock_irq(&pdc_lock); + pdc_result[0] = 0; + retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_WRITE_CONFIG, + __pa(pdc_result), hpa, + cfg_addr&~3UL, 4UL, (unsigned long) val); + spin_unlock_irq(&pdc_lock); + return retval; +} +#endif /* UNTESTED CODE */ /** * pdc_tod_read - Read the Time-Of-Day clock. Index: arch/parisc/kernel/inventory.c =================================================================== RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/inventory.c,v retrieving revision 1.3 diff -u -p -r1.3 inventory.c --- arch/parisc/kernel/inventory.c 8 Dec 2003 01:14:18 -0000 1.3 +++ arch/parisc/kernel/inventory.c 21 Dec 2003 03:35:48 -0000 @@ -526,20 +526,6 @@ static void __init system_map_inventory( int i; long status = PDC_OK; -#if defined(CONFIG_IOMMU_SBA) && defined(CONFIG_SUPERIO) - /* - * Stop the suckyio usb controller on Astro based systems. - * Otherwise the machine might crash during iommu setup. - */ - pdc_io_reset(); - - /* - * Unfortunately if we reset devices here, serial console - * stops working :-( - */ - /* pdc_io_reset_devices(); */ -#endif - for (i = 0; status != PDC_BAD_PROC && status != PDC_NE_MOD; i++) { struct parisc_device *dev; struct pdc_system_map_mod_info module_result; Index: drivers/net/tulip/media.c =================================================================== RCS file: /var/cvs/linux-2.6/drivers/net/tulip/media.c,v retrieving revision 1.10 diff -u -p -r1.10 media.c --- drivers/net/tulip/media.c 8 Sep 2003 22:00:24 -0000 1.10 +++ drivers/net/tulip/media.c 21 Dec 2003 03:35:50 -0000 @@ -43,8 +43,10 @@ static const unsigned char comet_miireg2 /* MII transceiver control section. Read and write the MII registers using software-generated serial - MDIO protocol. See the MII specifications or DP83840A data sheet - for details. */ + MDIO protocol. + See IEEE 802.3-2002.pdf (Section 2, Chapter "22.2.4 Management functions") + or DP83840A data sheet for more details. + */ int tulip_mdio_read(struct net_device *dev, int phy_id, int location) { @@ -271,17 +273,19 @@ void tulip_select_media(struct net_devic int reset_length = p[2 + init_length]; misc_info = (u16*)(reset_sequence + reset_length); if (startup) { - int timeout = 20; /* 2 ms */ + int timeout = 10; /* max 1 ms */ outl(mtable->csr12dir | 0x100, ioaddr + CSR12); for (i = 0; i < reset_length; i++) outl(reset_sequence[i], ioaddr + CSR12); /* flush posted writes */ inl(ioaddr + CSR12); + /* Sect 3.10.3 in DP83840A.pdf (p39) */ udelay(500); /* Section 4.2 in DP83840A.pdf (p43) */ + /* and IEEE 802.3 "22.2.4.1.1 Reset" */ while (timeout-- && (tulip_mdio_read (dev, phy_num, MII_BMCR) & BMCR_RESET)) udelay(100); Index: drivers/parisc/Kconfig =================================================================== RCS file: /var/cvs/linux-2.6/drivers/parisc/Kconfig,v retrieving revision 1.3 diff -u -p -r1.3 Kconfig --- drivers/parisc/Kconfig 15 Oct 2003 14:01:11 -0000 1.3 +++ drivers/parisc/Kconfig 21 Dec 2003 03:35:50 -0000 @@ -106,6 +106,9 @@ config IOMMU_SBA #config PCI_EPIC # bool "EPIC/SAGA PCI support" # depends on PCI +# default y +# help +# Say Y here for V-class PCI, DMA/IOMMU, IRQ subsystem support. config SUPERIO bool "SuperIO (SuckyIO) support" Index: drivers/parisc/iosapic.c =================================================================== RCS file: /var/cvs/linux-2.6/drivers/parisc/iosapic.c,v retrieving revision 1.4 diff -u -p -r1.4 iosapic.c --- drivers/parisc/iosapic.c 8 Sep 2003 22:00:24 -0000 1.4 +++ drivers/parisc/iosapic.c 21 Dec 2003 03:35:50 -0000 @@ -610,19 +610,19 @@ iosapic_interrupt(int irq, void *dev_id, { struct vector_info *vi = (struct vector_info *)dev_id; extern void do_irq(struct irqaction *a, int i, struct pt_regs *p); - int irq_num = vi->vi_ios->isi_region->data.irqbase + vi->vi_irqline; + int irq_num = vi->iosapic->isi_region->data.irqbase + vi->irqline; DBG("iosapic_interrupt(): irq %d line %d eoi %p\n", - irq, vi->vi_irqline, vi->vi_eoi_addr); + irq, vi->irqline, vi->eoi_addr); /* FIXME: Need to mask/unmask? processor IRQ is already masked... */ - do_irq(&vi->vi_ios->isi_region->action[vi->vi_irqline], irq_num, regs); + do_irq(&vi->iosapic->isi_region->action[vi->irqline], irq_num, regs); /* ** PCI only supports level triggered in order to share IRQ lines. ** I/O SAPIC must always issue EOI. */ - IOSAPIC_EOI(vi->vi_eoi_addr, vi->vi_eoi_data); + IOSAPIC_EOI(vi->eoi_addr, vi->eoi_data); return IRQ_HANDLED; } @@ -636,10 +636,6 @@ iosapic_fixup_irq(void *isi_obj, struct struct vector_info *vi; int isi_line; /* line used by device */ int tmp; - int return_irq; -#ifdef CONFIG_SUPERIO - int superio_irq = -1; -#endif if (NULL == isi) { printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n", @@ -648,30 +644,29 @@ iosapic_fixup_irq(void *isi_obj, struct } #ifdef CONFIG_SUPERIO + /* + * HACK ALERT! (non-compliant PCI device support) + * + * All SuckyIO interrupts are routed through the PIC's on function 1. + * But SuckyIO OHCI USB controller gets an IRT entry anyway because + * it advertises INT D for INT_PIN. Use that IRT entry to get the + * SuckyIO interrupt routing for PICs on function 1 (*BLEECCHH*). + */ if (is_superio_device(pcidev)) { - superio_irq = superio_fixup_irq(pcidev); - if (superio_irq == -1) - return(-1); - - if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN) { - - /* - * SuperIO USB controller has an irt entry. - * Only let the USB controller hookup the rest - * of the interrupt routing when it comes through. - * Note that interrupts for all three functions - * actually come through the PIC's on function 1! - */ - - pcidev->irq = superio_irq; - return superio_irq; - } + /* We must call superio_fixup_irq() to register the pdev */ + pcidev->irq = superio_fixup_irq(pcidev); + + /* Don't return if need to program the IOSAPIC's IRT... */ + if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN) + return pcidev->irq; } #endif /* CONFIG_SUPERIO */ /* lookup IRT entry for isi/slot/pin set */ irte = iosapic_xlate_pin(isi, pcidev); if (NULL == irte) { + printk("iosapic: no IRTE for %s (IRQ not connected?)\n", + pci_name(pcidev)); return(-1); } DBG_IRT("iosapic_fixup_irq(): irte %p %x %x %x %x %x %x %x %x\n", @@ -685,15 +680,21 @@ iosapic_fixup_irq(void *isi_obj, struct irte->dest_iosapic_intin, (u32) irte->dest_iosapic_addr); isi_line = irte->dest_iosapic_intin; + pcidev->irq = isi->isi_region->data.irqbase + isi_line; /* get vector info for this input line */ ASSERT(NULL != isi->isi_vector); vi = &(isi->isi_vector[isi_line]); DBG_IRT("iosapic_fixup_irq: line %d vi 0x%p\n", isi_line, vi); - vi->vi_irte = irte; + + /* If this IRQ line has already been setup, skip it */ + if (vi->irte) + return pcidev->irq; + + vi->irte = irte; /* Allocate processor IRQ */ - vi->vi_txn_irq = txn_alloc_irq(); + vi->txn_irq = txn_alloc_irq(); /* XXX/FIXME The txn_alloc_irq() code and related code should be moved ** to enable_irq(). That way we only allocate processor IRQ bits @@ -701,47 +702,36 @@ iosapic_fixup_irq(void *isi_obj, struct ** Right now we assign an IRQ to every PCI device present regardless ** of whether it's used or not. */ - if (vi->vi_txn_irq < 0) + if (vi->txn_irq < 0) panic("I/O sapic: couldn't get TXN IRQ\n"); /* enable_irq() will use txn_* to program IRdT */ - vi->vi_txn_addr = txn_alloc_addr(vi->vi_txn_irq); - vi->vi_txn_data = txn_alloc_data(vi->vi_txn_irq, 8); - ASSERT(vi->vi_txn_data < 256); /* matches 8 above */ + vi->txn_addr = txn_alloc_addr(vi->txn_irq); + vi->txn_data = txn_alloc_data(vi->txn_irq, 8); + ASSERT(vi->txn_data < 256); /* matches 8 above */ - tmp = request_irq(vi->vi_txn_irq, iosapic_interrupt, 0, - vi->vi_name, vi); + tmp = request_irq(vi->txn_irq, iosapic_interrupt, 0, + vi->name, vi); ASSERT(tmp == 0); - vi->vi_eoi_addr = (u32 *) (isi->isi_hpa + IOSAPIC_REG_EOI); - vi->vi_eoi_data = cpu_to_le32(vi->vi_irqline); + vi->eoi_addr = (u32 *) (isi->isi_hpa + IOSAPIC_REG_EOI); + vi->eoi_data = cpu_to_le32(vi->irqline); ASSERT(NULL != isi->isi_region); - /* pcidev->irq still needs to be virtualized. */ - - return_irq = isi->isi_region->data.irqbase + isi_line; - -#ifdef CONFIG_SUPERIO - if (superio_irq != -1) { - superio_inform_irq(return_irq); - return_irq = superio_irq; - } -#endif - pcidev->irq = return_irq; DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n", - PCI_SLOT(pcidev->devfn), - PCI_FUNC(pcidev->devfn), pcidev->vendor, pcidev->device, isi_line, return_irq); + PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->irq), + pcidev->vendor, pcidev->device, isi_line, pcidev->irq); - return return_irq; + return pcidev->irq; } static void iosapic_rd_irt_entry(struct vector_info *vi , u32 *dp0, u32 *dp1) { - struct iosapic_info *isp = vi->vi_ios; - u8 idx = vi->vi_irqline; + struct iosapic_info *isp = vi->iosapic; + u8 idx = vi->irqline; /* point the window register to the lower word */ WRITE_U32(IOSAPIC_IRDT_ENTRY(idx), isp->isi_hpa+IOSAPIC_REG_SELECT); @@ -756,24 +746,24 @@ iosapic_rd_irt_entry(struct vector_info static void iosapic_wr_irt_entry(struct vector_info *vi, u32 dp0, u32 dp1) { - struct iosapic_info *isp = vi->vi_ios; + struct iosapic_info *isp = vi->iosapic; ASSERT(NULL != isp); ASSERT(0 != isp->isi_hpa); DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p WINDOW %p 0x%x 0x%x\n", - vi->vi_irqline, + vi->irqline, isp->isi_hpa, isp->isi_hpa+IOSAPIC_REG_WINDOW, dp0, dp1); /* point the window register to the lower word */ - WRITE_U32(IOSAPIC_IRDT_ENTRY(vi->vi_irqline), isp->isi_hpa+IOSAPIC_REG_SELECT); + WRITE_U32(IOSAPIC_IRDT_ENTRY(vi->irqline), isp->isi_hpa+IOSAPIC_REG_SELECT); WRITE_U32( dp0, isp->isi_hpa+IOSAPIC_REG_WINDOW); /* Read the window register to flush the writes down to HW */ dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW); /* point the window register to the higher word */ - WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(vi->vi_irqline), isp->isi_hpa+IOSAPIC_REG_SELECT); + WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(vi->irqline), isp->isi_hpa+IOSAPIC_REG_SELECT); WRITE_U32( dp1, isp->isi_hpa+IOSAPIC_REG_WINDOW); /* Read the window register to flush the writes down to HW */ @@ -790,8 +780,8 @@ static void iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1) { u32 mode = 0; - struct irt_entry *p = vi->vi_irte; - ASSERT(NULL != vi->vi_irte); + struct irt_entry *p = vi->irte; + ASSERT(NULL != vi->irte); if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO) mode |= IOSAPIC_IRDT_PO_LOW; @@ -804,8 +794,8 @@ iosapic_set_irt_data( struct vector_info ** PA doesn't support EXTINT or LPRIO bits. */ - ASSERT(vi->vi_txn_data); - *dp0 = mode | (u32) vi->vi_txn_data; + ASSERT(vi->txn_data); + *dp0 = mode | (u32) vi->txn_data; /* ** Extracting id_eid isn't a real clean way of getting it. @@ -814,9 +804,9 @@ iosapic_set_irt_data( struct vector_info if (is_pdc_pat()) { /* ** PAT PDC just hands it to us "right". - ** vi_txn_addr comes from cpu_data[x].txn_addr. + ** txn_addr comes from cpu_data[x].txn_addr. */ - *dp1 = (u32) (vi->vi_txn_addr); + *dp1 = (u32) (vi->txn_addr); } else { /* ** eg if base_addr == 0xfffa0000), @@ -825,8 +815,8 @@ iosapic_set_irt_data( struct vector_info ** eid 0x0ff00000 -> 0x00ff0000 ** id 0x000ff000 -> 0xff000000 */ - *dp1 = (((u32)vi->vi_txn_addr & 0x0ff00000) >> 4) | - (((u32)vi->vi_txn_addr & 0x000ff000) << 12); + *dp1 = (((u32)vi->txn_addr & 0x0ff00000) >> 4) | + (((u32)vi->txn_addr & 0x000ff000) << 12); } DBG_IRT("iosapic_set_irt_data(): 0x%x 0x%x\n", *dp0, *dp1); } @@ -872,7 +862,7 @@ Need more info on how Linux supports sha IOSAPIC_UNLOCK(&iosapic_lock); /* disable ISR for parent */ - disable_irq(vi->vi_txn_irq); + disable_irq(vi->txn_irq); } @@ -883,11 +873,11 @@ iosapic_enable_irq(void *dev, int irq) u32 d0, d1; ASSERT(NULL != vi); - ASSERT(NULL != vi->vi_irte); + ASSERT(NULL != vi->irte); /* data is initialized by fixup_irq */ - ASSERT(0 < vi->vi_txn_irq); - ASSERT(0UL != vi->vi_txn_data); + ASSERT(0 < vi->txn_irq); + ASSERT(0UL != vi->txn_data); iosapic_set_irt_data(vi, &d0, &d1); iosapic_wr_irt_entry(vi, d0, d1); @@ -895,15 +885,15 @@ iosapic_enable_irq(void *dev, int irq) #ifdef DEBUG_IOSAPIC_IRT { - u32 *t = (u32 *) ((ulong) vi->vi_eoi_addr & ~0xffUL); - printk("iosapic_enable_irq(): regs %p", vi->vi_eoi_addr); - while (t < vi->vi_eoi_addr) printk(" %x", READ_U32(t++)); + u32 *t = (u32 *) ((ulong) vi->eoi_addr & ~0xffUL); + printk("iosapic_enable_irq(): regs %p", vi->eoi_addr); + while (t < vi->eoi_addr) printk(" %x", READ_U32(t++)); printk("\n"); } printk("iosapic_enable_irq(): sel "); { - struct iosapic_info *isp = vi->vi_ios; + struct iosapic_info *isp = vi->iosapic; for (d0=0x10; d0<0x1e; d0++) { /* point the window register to the lower word */ @@ -924,7 +914,7 @@ printk("\n"); ** Issueing I/O SAPIC an EOI causes an interrupt iff IRQ line is ** asserted. */ - IOSAPIC_EOI(vi->vi_eoi_addr, vi->vi_eoi_data); + IOSAPIC_EOI(vi->eoi_addr, vi->eoi_data); } @@ -1034,9 +1024,9 @@ iosapic_register(unsigned long hpa) ** Initialize vector array */ for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) { - vip->vi_irqline = (unsigned char) cnt; - vip->vi_ios = isi; - sprintf(vip->vi_name, "%s-L%d", isi->isi_name, cnt); + vip->irqline = (unsigned char) cnt; + vip->iosapic = isi; + sprintf(vip->name, "%s-L%d", isi->isi_name, cnt); } isi->isi_region = alloc_irq_region(isi->isi_num_vectors, @@ -1071,13 +1061,13 @@ iosapic_prt_vi(struct vector_info *vi) { ASSERT(NULL != vi); - printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->vi_irqline, vi); - printk(KERN_DEBUG "\t\tvi_status: %.4x\n", vi->vi_status); - printk(KERN_DEBUG "\t\tvi_txn_irq: %d\n", vi->vi_txn_irq); - printk(KERN_DEBUG "\t\tvi_txn_addr: %lx\n", vi->vi_txn_addr); - printk(KERN_DEBUG "\t\tvi_txn_data: %lx\n", vi->vi_txn_data); - printk(KERN_DEBUG "\t\tvi_eoi_addr: %p\n", vi->vi_eoi_addr); - printk(KERN_DEBUG "\t\tvi_eoi_data: %x\n", vi->vi_eoi_data); + printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->irqline, vi); + printk(KERN_DEBUG "\t\tstatus: %.4x\n", vi->status); + printk(KERN_DEBUG "\t\ttxn_irq: %d\n", vi->txn_irq); + printk(KERN_DEBUG "\t\ttxn_addr: %lx\n", vi->txn_addr); + printk(KERN_DEBUG "\t\ttxn_data: %lx\n", vi->txn_data); + printk(KERN_DEBUG "\t\teoi_addr: %p\n", vi->eoi_addr); + printk(KERN_DEBUG "\t\teoi_data: %x\n", vi->eoi_data); } Index: drivers/parisc/iosapic_private.h =================================================================== RCS file: /var/cvs/linux-2.6/drivers/parisc/iosapic_private.h,v retrieving revision 1.1 diff -u -p -r1.1 iosapic_private.h --- drivers/parisc/iosapic_private.h 29 Jul 2003 17:01:24 -0000 1.1 +++ drivers/parisc/iosapic_private.h 21 Dec 2003 03:35:51 -0000 @@ -107,16 +107,16 @@ struct iosapic_irt { #endif struct vector_info { - struct iosapic_info *vi_ios; /* I/O SAPIC this vector is on */ - struct irt_entry *vi_irte; /* IRT entry */ - u32 *vi_eoi_addr; /* precalculate EOI reg address */ - u32 vi_eoi_data; /* IA64: ? PA: swapped txn_data */ - int vi_txn_irq; /* virtual IRQ number for processor */ - ulong vi_txn_addr; /* IA64: id_eid PA: partial HPA */ - ulong vi_txn_data; /* IA64: vector PA: EIR bit */ - u8 vi_status; /* status/flags */ - u8 vi_irqline; /* INTINn(IRQ) */ - char vi_name[32]; /* user visible identity */ + struct iosapic_info *iosapic; /* I/O SAPIC this vector is on */ + struct irt_entry *irte; /* IRT entry */ + u32 *eoi_addr; /* precalculate EOI reg address */ + u32 eoi_data; /* IA64: ? PA: swapped txn_data */ + int txn_irq; /* virtual IRQ number for processor */ + ulong txn_addr; /* IA64: id_eid PA: partial HPA */ + ulong txn_data; /* IA64: vector PA: EIR bit */ + u8 status; /* status/flags */ + u8 irqline; /* INTINn(IRQ) */ + char name[32]; /* user visible identity */ }; Index: drivers/parisc/sba_iommu.c =================================================================== RCS file: /var/cvs/linux-2.6/drivers/parisc/sba_iommu.c,v retrieving revision 1.4 diff -u -p -r1.4 sba_iommu.c --- drivers/parisc/sba_iommu.c 8 Sep 2003 22:00:24 -0000 1.4 +++ drivers/parisc/sba_iommu.c 21 Dec 2003 03:35:51 -0000 @@ -1680,6 +1680,21 @@ sba_hw_init(struct sba_device *sba_dev) int num_ioc; u64 ioc_ctl; + if (!is_pdc_pat()) { + /* Shutdown the USB controller on Astro-based workstations. + ** Once we reprogram the IOMMU, the next DMA performed by + ** USB will HPMC the box. + */ + pdc_io_reset_devices(); + + /* + ** XXX May need something more sophisticated to deal + ** with DMA from LAN. Maybe use page zero boot device + ** as a handle to talk to PDC about which device to + ** shutdown. This also needs to work for is_pdc_pat(). + */ + } + ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL); DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->", __FUNCTION__, sba_dev->sba_hpa, ioc_ctl); Index: drivers/parisc/superio.c =================================================================== RCS file: /var/cvs/linux-2.6/drivers/parisc/superio.c,v retrieving revision 1.4 diff -u -p -r1.4 superio.c --- drivers/parisc/superio.c 8 Dec 2003 01:14:18 -0000 1.4 +++ drivers/parisc/superio.c 21 Dec 2003 03:35:51 -0000 @@ -9,7 +9,8 @@ * (C) Copyright 2000 Linuxcare Canada, Inc. * (C) Copyright 2000 Martin K. Petersen * (C) Copyright 2000 Alex deVries - * (C) Copyright 2001 John Marvin + * (C) Copyright 2001 John Marvin + * (C) Copyright 2003 Grant Grundler * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -73,24 +74,16 @@ #include #include -static struct superio_device sio_dev = { - .iosapic_irq = -1 -}; - +static struct superio_device sio_dev; -#undef DEBUG_INIT -void -superio_inform_irq(int irq) -{ - if (sio_dev.iosapic_irq != -1) { - printk(KERN_ERR "SuperIO: superio_inform_irq called twice! (more than one SuperIO?)\n"); - BUG(); - return; - } +#undef DEBUG_SUPERIO_INIT - sio_dev.iosapic_irq = irq; -} +#ifdef DEBUG_SUPERIO_INIT +#define DBG_INIT(x...) printk(x) +#else +#define DBG_INIT(x...) +#endif static irqreturn_t superio_interrupt(int irq, void *devp, struct pt_regs *regs) @@ -135,7 +128,6 @@ superio_interrupt(int irq, void *devp, s } /* Call the appropriate device's interrupt */ - do_irq(&sio->irq_region->action[local_irq], sio->irq_region->data.irqbase + local_irq, regs); @@ -153,34 +145,39 @@ superio_init(struct superio_device *sio) { struct pci_dev *pdev = sio->lio_pdev; u16 word; - u8 i; - if (!pdev || sio->iosapic_irq == -1) { - printk(KERN_ERR "All SuperIO functions not found!\n"); - BUG(); + if (sio->suckyio_irq_enabled) return; - } + + if (!pdev) BUG(); + if (!sio->usb_pdev) BUG(); + + /* use the IRQ iosapic found for USB INT D... */ + pdev->irq = sio->usb_pdev->irq; + + /* ...then properly fixup the USB to point at suckyio PIC */ + sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev); printk (KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n", - pci_name(pdev),sio->iosapic_irq); + pci_name(pdev),pdev->irq); /* Find our I/O devices */ - pci_read_config_word (pdev, SIO_SP1BAR, &sio->sp1_base); + pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base); sio->sp1_base &= ~1; printk (KERN_INFO "SuperIO: Serial port 1 at 0x%x\n", sio->sp1_base); - pci_read_config_word (pdev, SIO_SP2BAR, &sio->sp2_base); + pci_read_config_dword (pdev, SIO_SP2BAR, &sio->sp2_base); sio->sp2_base &= ~1; printk (KERN_INFO "SuperIO: Serial port 2 at 0x%x\n", sio->sp2_base); - pci_read_config_word (pdev, SIO_PPBAR, &sio->pp_base); + pci_read_config_dword (pdev, SIO_PPBAR, &sio->pp_base); sio->pp_base &= ~1; printk (KERN_INFO "SuperIO: Parallel port at 0x%x\n", sio->pp_base); - pci_read_config_word (pdev, SIO_FDCBAR, &sio->fdc_base); + pci_read_config_dword (pdev, SIO_FDCBAR, &sio->fdc_base); sio->fdc_base &= ~1; printk (KERN_INFO "SuperIO: Floppy controller at 0x%x\n", sio->fdc_base); - pci_read_config_word (pdev, SIO_ACPIBAR, &sio->acpi_base); + pci_read_config_dword (pdev, SIO_ACPIBAR, &sio->acpi_base); sio->acpi_base &= ~1; printk (KERN_INFO "SuperIO: ACPI at 0x%x\n", sio->acpi_base); @@ -192,24 +189,53 @@ superio_init(struct superio_device *sio) pci_read_config_word (pdev, PCI_COMMAND, &word); word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO; pci_write_config_word (pdev, PCI_COMMAND, word); + pci_set_master (pdev); + pci_enable_device(pdev); - /* Next project is programming the onboard interrupt - * controllers. PDC hasn't done this for us, since it's using - * polled I/O. + /* + * Next project is programming the onboard interrupt controllers. + * PDC hasn't done this for us, since it's using polled I/O. + * + * XXX Use dword writes to avoid bugs in Elroy or Suckyio Config + * space access. PCI is by nature a 32-bit bus and config + * space can be sensitive the that. */ - /* Set PIC interrupts to edge triggered */ - pci_write_config_byte (pdev, TRIGGER_1, 0x0); - pci_write_config_byte (pdev, TRIGGER_2, 0x0); - - /* Disable all interrupt routing */ - for (i = IR_LOW ; i < IR_HIGH ; i++) - pci_write_config_byte (pdev, i, 0x0); + /* 0x64 - 0x67 : + DMA Rtg 2 + DMA Rtg 3 + DMA Chan Ctl + TRIGGER_1 == 0x82 USB & IDE level triggered, rest to edge + */ + pci_write_config_dword (pdev, 0x64, 0x82000000U); + + /* 0x68 - 0x6b : + TRIGGER_2 == 0x00 all edge triggered (not used) + CFG_IR_SER == 0x43 SerPort1 = IRQ3, SerPort2 = IRQ4 + CFG_IR_PF == 0x65 ParPort = IRQ5, FloppyCtlr = IRQ6 + CFG_IR_IDE == 0x07 IDE1 = IRQ7, reserved + */ + pci_write_config_dword (pdev, TRIGGER_2, 0x07654300U); + + /* 0x6c - 0x6f : + CFG_IR_INTAB == 0x00 + CFG_IR_INTCD == 0x10 USB = IRQ1 + CFG_IR_PS2 == 0x00 + CFG_IR_FXBUS == 0x00 + */ + pci_write_config_dword (pdev, CFG_IR_INTAB, 0x00001000U); + + /* 0x70 - 0x73 : + CFG_IR_USB == 0x00 not used. USB is connected to INTD. + CFG_IR_ACPI == 0x00 not used. + DMA Priority == 0x4c88 Power on default value. NFC. + */ + pci_write_config_dword (pdev, CFG_IR_USB, 0x4c880000U); /* PIC1 Initialization Command Word register programming */ outb (0x11,IC_PIC1+0); /* ICW1: ICW4 write req | ICW1 */ - outb (0x00,IC_PIC1+1); /* ICW2: N/A */ + outb (0x00,IC_PIC1+1); /* ICW2: interrupt vector table - not used */ outb (0x04,IC_PIC1+1); /* ICW3: Cascade */ outb (0x01,IC_PIC1+1); /* ICW4: x86 mode */ @@ -228,19 +254,8 @@ superio_init(struct superio_device *sio) outb (0x68,IC_PIC1+0); /* OCW3: OCW3 select | ESMM | SMM */ /* Write master mask reg */ - outb (0xff,IC_PIC1+1); - /* Set up interrupt routing */ - - pci_write_config_byte (pdev, IR_USB, 0x10); /* USB on IRQ1 */ - pci_write_config_byte (pdev, IR_SER, 0x43); /* SP1 on IRQ3, SP2 on IRQ4 */ - pci_write_config_byte (pdev, IR_PFD, 0x65); /* PAR on IRQ5, FDC on IRQ6 */ - pci_write_config_byte (pdev, IR_IDE, 0x07); /* IDE1 on IRQ7 */ - - /* Set USB and IDE to level triggered interrupts, rest to edge */ - pci_write_config_byte (pdev, TRIGGER_1, 0x82); /* IRQ 1 and 7 */ - /* Setup USB power regulation */ outb(1, sio->acpi_base + USB_REG_CR); if (inb(sio->acpi_base + USB_REG_CR) & 1) @@ -248,20 +263,18 @@ superio_init(struct superio_device *sio) else printk(KERN_ERR "USB regulator not initialized!\n"); - pci_enable_device(pdev); - - if (request_irq(sio->iosapic_irq,superio_interrupt,SA_INTERRUPT, - "SuperIO",(void *)sio)) { + if (request_irq(pdev->irq, superio_interrupt, SA_INTERRUPT, + "SuperIO", (void *)sio)) { printk(KERN_ERR "SuperIO: could not get irq\n"); BUG(); return; } - sio->iosapic_irq_enabled = 1; - + sio->suckyio_irq_enabled = 1; } + static void superio_disable_irq(void *dev, int local_irq) { @@ -283,30 +296,21 @@ superio_disable_irq(void *dev, int local static void superio_enable_irq(void *dev, int local_irq) { - struct superio_device *sio = (struct superio_device *)dev; u8 r8; if ((local_irq < 1) || (local_irq == 2) || (local_irq > 7)) { - printk(KERN_ERR "SuperIO: Illegal irq number.\n"); + printk(KERN_ERR "SuperIO: Illegal irq number (%d).\n", local_irq); BUG(); return; } - /* - * It's possible that we haven't initialized the legacy IO - * function yet. If not, do it now. - */ - - if (!sio->iosapic_irq_enabled) - superio_init(sio); - /* Unmask interrupt */ - r8 = inb(IC_PIC1+1); r8 &= ~(1 << local_irq); outb (r8,IC_PIC1+1); } + static void superio_mask_irq(void *dev, int local_irq) { @@ -326,7 +330,7 @@ static struct irq_region_ops superio_irq .unmask_irq = superio_unmask_irq }; -#ifdef DEBUG_INIT +#ifdef DEBUG_SUPERIO_INIT static unsigned short expected_device[3] = { PCI_DEVICE_ID_NS_87415, PCI_DEVICE_ID_NS_87560_LIO, @@ -338,7 +342,7 @@ int superio_fixup_irq(struct pci_dev *pc { int local_irq; -#ifdef DEBUG_INIT +#ifdef DEBUG_SUPERIO_INIT int fn; fn = PCI_FUNC(pcidev->devfn); @@ -375,9 +379,10 @@ int superio_fixup_irq(struct pci_dev *pc local_irq = IDE_IRQ; break; case PCI_DEVICE_ID_NS_87560_LIO: /* Function 1 */ - sio_dev.lio_pdev = pcidev; /* save for later initialization */ + sio_dev.lio_pdev = pcidev; /* save for superio_init() */ return -1; case PCI_DEVICE_ID_NS_87560_USB: /* Function 2 */ + sio_dev.usb_pdev = pcidev; /* save for superio_init() */ local_irq = USB_IRQ; break; default: @@ -411,20 +416,29 @@ superio_serial_init(void) { #ifdef CONFIG_SERIAL_8250 int retval; + extern void serial8250_console_init(void); /* drivers/serial/8250.c */ if (!sio_dev.irq_region) return; /* superio not present */ - if (!sio_dev.iosapic_irq_enabled) - superio_init(&sio_dev); + if (!serial) { + printk(KERN_WARNING "SuperIO: Could not get memory for serial struct.\n"); + return; + } serial[0].iobase = sio_dev.sp1_base; - retval = early_serial_setup(&serial[0]); + serial[0].irq = sio_dev.irq_region->data.irqbase + SP1_IRQ; - if (retval < 0) + retval = early_serial_setup(&serial[0]); + if (retval < 0) { printk(KERN_WARNING "SuperIO: Register Serial #0 failed.\n"); + return; + } + + serial8250_console_init(); serial[1].iobase = sio_dev.sp2_base; + serial[1].irq = sio_dev.irq_region->data.irqbase + SP2_IRQ; retval = early_serial_setup(&serial[1]); if (retval < 0) @@ -432,30 +446,20 @@ superio_serial_init(void) #endif /* CONFIG_SERIAL_8250 */ } -EXPORT_SYMBOL(superio_serial_init); - -#ifdef CONFIG_PARPORT_PC -void __devinit +static void __devinit superio_parport_init(void) { - if (!sio_dev.irq_region) - return; /* superio not present */ - - if (!sio_dev.iosapic_irq_enabled) - superio_init(&sio_dev); - - if (!parport_pc_probe_port(sio_dev.pp_base, - 0 /*base_hi*/, - sio_dev.irq_region->data.irqbase + PAR_IRQ, - PARPORT_DMA_NONE /* dma */, - NULL /*struct pci_dev* */)) +#ifdef CONFIG_PARPORT_PC + if (!parport_pc_probe_port(sio_dev.pp_base, + 0 /*base_hi*/, + sio_dev.irq_region->data.irqbase + PAR_IRQ, + PARPORT_DMA_NONE /* dma */, + NULL /*struct pci_dev* */) ) printk(KERN_WARNING "SuperIO: Probing parallel port failed.\n"); -} - -EXPORT_SYMBOL(superio_parport_init); #endif /* CONFIG_PARPORT_PC */ +} int @@ -471,36 +475,35 @@ EXPORT_SYMBOL(superio_get_ide_irq); static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_id *id) { -#ifdef DEBUG_INIT - printk("superio_probe(%s) ven 0x%x dev 0x%x sv 0x%x sd 0x%x class 0x%x\n", + + /* + ** superio_probe(00:0e.0) ven 0x100b dev 0x2 sv 0x0 sd 0x0 class 0x1018a + ** superio_probe(00:0e.1) ven 0x100b dev 0xe sv 0x0 sd 0x0 class 0x68000 + ** superio_probe(00:0e.2) ven 0x100b dev 0x12 sv 0x0 sd 0x0 class 0xc0310 + */ + DBG_INIT("superio_probe(%s) ven 0x%x dev 0x%x sv 0x%x sd 0x%x class 0x%x\n", pci_name(dev), dev->vendor, dev->device, dev->subsystem_vendor, dev->subsystem_device, dev->class); -/* -** superio_probe(00:0e.0) ven 0x100b dev 0x2 sv 0x0 sd 0x0 class 0x1018a -** superio_probe(00:0e.1) ven 0x100b dev 0xe sv 0x0 sd 0x0 class 0x68000 -** superio_probe(00:0e.2) ven 0x100b dev 0x12 sv 0x0 sd 0x0 class 0xc0310 -*/ -#endif - /* superio_fixup_irq(dev); */ + superio_init(&sio_dev); - if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) { -#ifdef CONFIG_PARPORT_PC + if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) { /* Function 1 */ superio_parport_init(); -#endif -#ifdef CONFIG_SERIAL_8250 superio_serial_init(); -#endif - /* REVISIT : superio_fdc_init() ? */ + /* REVISIT XXX : superio_fdc_init() ? */ return 0; + } else if (dev->device == PCI_DEVICE_ID_NS_87415) { /* Function 0 */ + DBG_INIT("superio_probe: ignoring IDE 87415\n"); + } else if (dev->device == PCI_DEVICE_ID_NS_87560_USB) { /* Function 2 */ + DBG_INIT("superio_probe: ignoring USB OHCI controller\n"); } else { - /* don't claim this device; let whatever either driver - * do it - */ - return -1; + DBG_INIT("superio_probe: WTF? Fire Extinguisher?\n"); } + + /* Let appropriate other driver claim this device. */ + return -ENODEV; } static struct pci_device_id superio_tbl[] = { @@ -524,10 +527,6 @@ static void __exit superio_exit(void) pci_unregister_driver(&superio_driver); } -/* Make late initcall to ensure the serial and tty layers are initialised - * before we start superio. - * - * FIXME: does this break the superio console? - */ + module_init(superio_modinit); module_exit(superio_exit); Index: include/asm-parisc/pci.h =================================================================== RCS file: /var/cvs/linux-2.6/include/asm-parisc/pci.h,v retrieving revision 1.2 diff -u -p -r1.2 pci.h --- include/asm-parisc/pci.h 25 Sep 2003 01:07:21 -0000 1.2 +++ include/asm-parisc/pci.h 21 Dec 2003 03:35:55 -0000 @@ -55,6 +55,7 @@ struct pci_hba_data { struct resource io_space; /* PIOP */ struct resource lmmio_space; /* bus addresses < 4Gb */ struct resource elmmio_space; /* additional bus addresses < 4Gb */ + struct resource gmmio_space; /* bus addresses > 4Gb */ unsigned long lmmio_space_offset; /* CPU view - PCI view */ void * iommu; /* IOMMU this device is under */ /* REVISIT - spinlock to protect resources? */ Index: include/asm-parisc/pdc.h =================================================================== RCS file: /var/cvs/linux-2.6/include/asm-parisc/pdc.h,v retrieving revision 1.3 diff -u -p -r1.3 pdc.h --- include/asm-parisc/pdc.h 25 Sep 2003 01:07:21 -0000 1.3 +++ include/asm-parisc/pdc.h 21 Dec 2003 03:35:55 -0000 @@ -478,7 +478,11 @@ extern int pdc_type; #define PDC_TYPE_SYSTEM_MAP 1 /* 32-bit, but supports PDC_SYSTEM_MAP */ #define PDC_TYPE_SNAKE 2 /* Doesn't support SYSTEM_MAP */ -#define is_pdc_pat() (pdc_type == PDC_TYPE_PAT) +#ifdef CONFIG_PARISC64 +#define is_pdc_pat() (PDC_TYPE_PAT == pdc_type) +#else +#define is_pdc_pat() (0) +#endif struct pdc_chassis_info { /* for PDC_CHASSIS_INFO */ unsigned long actcnt; /* actual number of bytes returned */ Index: include/asm-parisc/superio.h =================================================================== RCS file: /var/cvs/linux-2.6/include/asm-parisc/superio.h,v retrieving revision 1.1 diff -u -p -r1.1 superio.h --- include/asm-parisc/superio.h 29 Jul 2003 17:02:04 -0000 1.1 +++ include/asm-parisc/superio.h 21 Dec 2003 03:35:55 -0000 @@ -1,25 +1,33 @@ #ifndef _PARISC_SUPERIO_H #define _PARISC_SUPERIO_H -/* Offsets to configuration and base address registers */ #define IC_PIC1 0x20 /* PCI I/O address of master 8259 */ #define IC_PIC2 0xA0 /* PCI I/O address of slave */ + +/* Config Space Offsets to configuration and base address registers */ #define SIO_CR 0x5A /* Configuration Register */ -#define SIO_ACPIBAR 0x88 /* ACPI BAR */ +#define SIO_ACPIBAR 0x88 /* ACPI BAR */ #define SIO_FDCBAR 0x90 /* Floppy Disk Controller BAR */ #define SIO_SP1BAR 0x94 /* Serial 1 BAR */ #define SIO_SP2BAR 0x98 /* Serial 2 BAR */ #define SIO_PPBAR 0x9C /* Parallel BAR */ -/* Interrupt triggers and routing */ #define TRIGGER_1 0x67 /* Edge/level trigger register 1 */ #define TRIGGER_2 0x68 /* Edge/level trigger register 2 */ -#define IR_SER 0x69 /* Serial 1 [0:3] and Serial 2 [4:7] */ -#define IR_PFD 0x6a /* Parallel [0:3] and Floppy [4:7] */ -#define IR_IDE 0x6b /* IDE1 [0:3] and IDE2 [4:7] */ -#define IR_USB 0x6d /* USB [4:7] */ -#define IR_LOW 0x69 /* Lowest interrupt routing reg */ -#define IR_HIGH 0x71 /* Highest interrupt routing reg */ + +/* Interrupt Routing Control registers */ +#define CFG_IR_SER 0x69 /* Serial 1 [0:3] and Serial 2 [4:7] */ +#define CFG_IR_PFD 0x6a /* Parallel [0:3] and Floppy [4:7] */ +#define CFG_IR_IDE 0x6b /* IDE1 [0:3] and IDE2 [4:7] */ +#define CFG_IR_INTAB 0x6c /* PCI INTA [0:3] and INT B [4:7] */ +#define CFG_IR_INTCD 0x6d /* PCI INTC [0:3] and INT D [4:7] */ +#define CFG_IR_PS2 0x6e /* PS/2 KBINT [0:3] and Mouse [4:7] */ +#define CFG_IR_FXBUS 0x6f /* FXIRQ[0] [0:3] and FXIRQ[1] [4:7] */ +#define CFG_IR_USB 0x70 /* FXIRQ[2] [0:3] and USB [4:7] */ +#define CFG_IR_ACPI 0x71 /* ACPI SCI [0:3] and reserved [4:7] */ + +#define CFG_IR_LOW CFG_IR_SER /* Lowest interrupt routing reg */ +#define CFG_IR_HIGH CFG_IR_ACPI /* Highest interrupt routing reg */ /* 8259 operational control words */ #define OCW2_EOI 0x20 /* Non-specific EOI */ @@ -42,15 +50,15 @@ #define SUPERIO_NIRQS 8 struct superio_device { - u16 fdc_base; - u16 sp1_base; - u16 sp2_base; - u16 pp_base; - u16 acpi_base; - int iosapic_irq; - int iosapic_irq_enabled; + u32 fdc_base; + u32 sp1_base; + u32 sp2_base; + u32 pp_base; + u32 acpi_base; + int suckyio_irq_enabled; struct irq_region *irq_region; - struct pci_dev *lio_pdev; /* pci device for legacy IO fn */ + struct pci_dev *lio_pdev; /* pci device for legacy IO (fn 1) */ + struct pci_dev *usb_pdev; /* pci device for USB (fn 2) */ }; /*