From d925eab60387b18a46b036d8812c0b2166a70332 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 5 Feb 2004 23:07:25 -0800 Subject: [PATCH] [PATCH] PA-RISC driver update for 2.6.2 PA-RISC specific driver updates: - Stop pasting __FILE__ - Improve card-mode Dino support (James Bottomley) - Fix dev->bridge rename (James Bottomley) - iosapic/SBA/LBA cleanups (Grant Grundler) - Improve LED support (Helge Deller) - Fix mux driver (Ryan Bradetich) - Make STI framebuffer work on RDI PrecisionBook (Helge Deller) --- drivers/parisc/Kconfig | 3 + drivers/parisc/ccio-dma.c | 22 +-- drivers/parisc/dino.c | 89 ++++++++---- drivers/parisc/eisa_eeprom.c | 21 +++ drivers/parisc/iosapic.c | 154 ++++++++++----------- drivers/parisc/iosapic_private.h | 43 ++++-- drivers/parisc/lba_pci.c | 102 ++++++-------- drivers/parisc/led.c | 27 ++-- drivers/parisc/sba_iommu.c | 58 +++++--- drivers/parisc/superio.c | 231 +++++++++++++++---------------- drivers/serial/mux.c | 163 +++++++++++----------- drivers/video/console/sticore.c | 26 ++-- drivers/video/stifb.c | 83 +++++++++-- 13 files changed, 574 insertions(+), 448 deletions(-) diff --git a/drivers/parisc/Kconfig b/drivers/parisc/Kconfig index 37aa2f69bfb49..fa875ae1cac2b 100644 --- a/drivers/parisc/Kconfig +++ b/drivers/parisc/Kconfig @@ -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" diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index d88555b393a14..696c3e1656544 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -364,11 +364,11 @@ ccio_alloc_range(struct ioc *ioc, unsigned long pages_needed) CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 64); #endif } else { - panic(__FILE__ ": %s() Too many pages to map. pages_needed: %ld\n", - __FUNCTION__, pages_needed); + panic("%s: %s() Too many pages to map. pages_needed: %ld\n", + __FILE__, __FUNCTION__, pages_needed); } - panic(__FILE__ ": %s() I/O MMU is out of mapping resources.\n", + panic("%s: %s() I/O MMU is out of mapping resources.\n", __FILE__, __FUNCTION__); resource_found: @@ -441,7 +441,7 @@ ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped) CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 64); #endif } else { - panic(__FILE__ ":%s() Too many pages to unmap.\n", + panic("%s:%s() Too many pages to unmap.\n", __FILE__, __FUNCTION__); } } @@ -1447,7 +1447,8 @@ ccio_ioc_init(struct ioc *ioc) ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL, get_order(ioc->pdir_size)); if(NULL == ioc->pdir_base) { - panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__); + panic("%s:%s() could not allocate I/O Page Table\n", __FILE__, + __FUNCTION__); } memset(ioc->pdir_base, 0, ioc->pdir_size); @@ -1461,7 +1462,8 @@ ccio_ioc_init(struct ioc *ioc) ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL, get_order(ioc->res_size)); if(NULL == ioc->res_map) { - panic(__FILE__ ":%s() could not allocate resource map\n", __FUNCTION__); + panic("%s:%s() could not allocate resource map\n", __FILE__, + __FUNCTION__); } memset(ioc->res_map, 0, ioc->res_size); @@ -1627,11 +1629,11 @@ int ccio_request_resource(const struct parisc_device *dev, if (!ioc) { parent = &iomem_resource; - } else if ((ioc->mmio_region->start <= dev->hpa) && - (dev->hpa < ioc->mmio_region->end)) { + } else if ((ioc->mmio_region->start <= res->start) && + (res->end <= ioc->mmio_region->end)) { parent = ioc->mmio_region; - } else if (((ioc->mmio_region + 1)->start <= dev->hpa) && - (dev->hpa < (ioc->mmio_region + 1)->end)) { + } else if (((ioc->mmio_region + 1)->start <= res->start) && + (res->end <= (ioc->mmio_region + 1)->end)) { parent = ioc->mmio_region + 1; } else { return -EBUSY; diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index a2bfdfaacb8eb..0b28122303c5b 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -175,7 +175,7 @@ static int dino_current_bus = 0; static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { - struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->dev)); + struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge)); u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3); unsigned long base_addr = d->hba.base_addr; @@ -209,7 +209,7 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where, static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) { - struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->dev)); + struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge)); u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3); unsigned long base_addr = d->hba.base_addr; @@ -468,14 +468,14 @@ static void __init dino_card_setup(struct pci_bus *bus, unsigned long base_addr) { int i; - struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->dev)); + struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge)); struct resource *res; char name[128]; int size; res = &dino_dev->hba.lmmio_space; res->flags = IORESOURCE_MEM; - size = snprintf(name, sizeof(name), "Dino LMMIO (%s)", bus->dev->bus_id); + size = snprintf(name, sizeof(name), "Dino LMMIO (%s)", bus->bridge->bus_id); res->name = kmalloc(size+1, GFP_KERNEL); if(res->name) strcpy((char *)res->name, name); @@ -489,7 +489,7 @@ dino_card_setup(struct pci_bus *bus, unsigned long base_addr) struct list_head *ln, *tmp_ln; printk(KERN_ERR "Dino: cannot attach bus %s\n", - bus->dev->bus_id); + bus->bridge->bus_id); /* kill the bus, we can't do anything with it */ list_for_each_safe(ln, tmp_ln, &bus->devices) { struct pci_dev *dev = pci_dev_b(ln); @@ -560,11 +560,11 @@ dino_fixup_bus(struct pci_bus *bus) { struct list_head *ln; struct pci_dev *dev; - struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->dev)); + struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge)); int port_base = HBA_PORT_BASE(dino_dev->hba.hba_num); DBG(KERN_WARNING "%s(0x%p) bus %d sysdata 0x%p\n", - __FUNCTION__, bus, bus->secondary, bus->dev->platform_data); + __FUNCTION__, bus, bus->secondary, bus->bridge->platform_data); /* Firmware doesn't set up card-mode dino, so we have to */ if (is_card_dino(&dino_dev->hba.dev->id)) { @@ -572,15 +572,23 @@ dino_fixup_bus(struct pci_bus *bus) } else if(bus->parent == NULL) { /* must have a dino above it, reparent the resources * into the dino window */ + int i; + struct resource *res = &dino_dev->hba.lmmio_space; + bus->resource[0] = &(dino_dev->hba.io_space); - bus->resource[1] = &(dino_dev->hba.lmmio_space); + for(i = 0; i < DINO_MAX_LMMIO_RESOURCES; i++) { + if(res[i].flags == 0) + break; + bus->resource[i+1] = &res[i]; + } + } else if(bus->self) { int i; pci_read_bridge_bases(bus); - for(i = 0; i < PCI_NUM_RESOURCES; i++) { + for(i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) { if((bus->self->resource[i].flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0) continue; @@ -642,11 +650,10 @@ dino_fixup_bus(struct pci_bus *bus) * care about an expansion rom on parisc, since it * usually contains (x86) bios code) */ dev->resource[PCI_ROM_RESOURCE].flags = 0; - dev->resource[PCI_ROM_RESOURCE].start = 0; - dev->resource[PCI_ROM_RESOURCE].end = 0; if(dev->irq == 255) { +#define DINO_FIX_UNASSIGNED_INTERRUPTS #ifdef DINO_FIX_UNASSIGNED_INTERRUPTS /* This code tries to assign an unassigned @@ -660,7 +667,7 @@ dino_fixup_bus(struct pci_bus *bus) dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 1, &irq_pin); dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ; dino_cfg_write(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 1, dev->irq); - dev->irq += dino_dev->dino_region->data.irqbase + dev->irq += dino_dev->dino_region->data.irqbase; printk(KERN_WARNING "Device %s has undefined IRQ, setting to %d\n", dev->slot_name, irq_pin); #else dev->irq = 65535; @@ -741,9 +748,9 @@ dino_card_init(struct dino_device *dino_dev) static int __init dino_bridge_init(struct dino_device *dino_dev, const char *name) { - unsigned long io_addr, bpos; - int result; - struct resource *res; + unsigned long io_addr; + int result, i, count=0; + struct resource *res, *prevres = NULL; /* * Decoding IO_ADDR_EN only works for Built-in Dino * since PDC has already initialized this. @@ -755,21 +762,51 @@ dino_bridge_init(struct dino_device *dino_dev, const char *name) return -ENODEV; } - for (bpos = 0; (io_addr & (1 << bpos)) == 0; bpos++) - ; - res = &dino_dev->hba.lmmio_space; - res->flags = IORESOURCE_MEM; + for (i = 0; i < 32; i++) { + unsigned long start, end; + + if((io_addr & (1 << i)) == 0) + continue; - res->start = (unsigned long)(signed int)(0xf0000000 | (bpos << 23)); - res->end = res->start + 8 * 1024 * 1024 - 1; + start = (unsigned long)(signed int)(0xf0000000 | (i << 23)); + end = start + 8 * 1024 * 1024 - 1; - result = ccio_request_resource(dino_dev->hba.dev, res); - if (result < 0) { - printk(KERN_ERR "%s: failed to claim PCI Bus address space!\n", name); - return result; + DBG("DINO RANGE %d is at 0x%lx-0x%lx\n", count, + start, end); + + if(prevres && prevres->end + 1 == start) { + prevres->end = end; + } else { + if(count >= DINO_MAX_LMMIO_RESOURCES) { + printk(KERN_ERR "%s is out of resource windows for range %d (0x%lx-0x%lx)\n", name, count, start, end); + break; + } + prevres = res; + res->start = start; + res->end = end; + res->flags = IORESOURCE_MEM; + res->name = kmalloc(64, GFP_KERNEL); + if(res->name) + snprintf((char *)res->name, 64, "%s LMMIO %d", + name, count); + res++; + count++; + } } + res = &dino_dev->hba.lmmio_space; + + for(i = 0; i < DINO_MAX_LMMIO_RESOURCES; i++) { + if(res[i].flags == 0) + break; + + result = ccio_request_resource(dino_dev->hba.dev, &res[i]); + if (result < 0) { + printk(KERN_ERR "%s: failed to claim PCI Bus address space %d (0x%lx-0x%lx)!\n", name, i, res[i].start, res[i].end); + return result; + } + } return 0; } @@ -850,10 +887,8 @@ static int __init dino_common_init(struct parisc_device *dev, res = &dino_dev->hba.io_space; if (dev->id.hversion == 0x680 || is_card_dino(&dev->id)) { res->name = "Dino I/O Port"; - dino_dev->hba.lmmio_space.name = "Dino LMMIO"; } else { res->name = "Cujo I/O Port"; - dino_dev->hba.lmmio_space.name = "Cujo LMMIO"; } res->start = HBA_PORT_BASE(dino_dev->hba.hba_num); res->end = res->start + (HBA_PORT_SPACE_SIZE - 1); diff --git a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c index bda206c1393f1..d16724dbe890c 100644 --- a/drivers/parisc/eisa_eeprom.c +++ b/drivers/parisc/eisa_eeprom.c @@ -1,3 +1,24 @@ +/* + * EISA "eeprom" support routines + * + * Copyright (C) 2001 Thomas Bogendoerfer + * + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #include #include #include diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 9eb6ada6d192c..60466bd12a293 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -610,19 +610,19 @@ iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs) { 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 pci_dev *pcidev) 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 pci_dev *pcidev) } #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 pci_dev *pcidev) 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 pci_dev *pcidev) ** 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 *vi , u32 *dp0, u32 *dp1) 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 *vi, u32 *dp0, u32 *dp1) ** 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 *vi, u32 *dp0, u32 *dp1) 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 *vi, u32 *dp0, u32 *dp1) ** 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 shared IRQ lines on a PC. 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); } diff --git a/drivers/parisc/iosapic_private.h b/drivers/parisc/iosapic_private.h index e2d297b6a2105..8eae695fa36a2 100644 --- a/drivers/parisc/iosapic_private.h +++ b/drivers/parisc/iosapic_private.h @@ -1,3 +1,26 @@ +/* + * Private structs/constants for PARISC IOSAPIC support + * + * Copyright (C) 2000 Hewlett Packard (Grant Grundler) + * Copyright (C) 2000,2003 Grant Grundler (grundler at parisc-linux.org) + * Copyright (C) 2002 Matthew Wilcox (willy at parisc-linux.org) + * + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + /* ** This file is private to iosapic driver. ** If stuff needs to be used by another driver, move it to a common file. @@ -107,16 +130,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 */ }; diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index b1a1180db597c..269265d448f06 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -185,8 +185,6 @@ struct lba_device { void *iosapic_obj; #ifdef __LP64__ - unsigned long lmmio_base; /* PA_VIEW - fixup MEM addresses */ - unsigned long gmmio_base; /* PA_VIEW - Not used (yet) */ unsigned long iop_base; /* PA_VIEW - for IO port accessor funcs */ #endif @@ -508,7 +506,7 @@ lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size) static int lba_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) { - struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->dev)); + struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 tok = LBA_CFG_TOK(local_bus, devfn); @@ -518,7 +516,7 @@ static int lba_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int si with risk we will miss PCI bus errors. */ *data = lba_rd_cfg(d, tok, pos, size); DBG_CFG("%s(%x+%2x) -> 0x%x (a)\n", __FUNCTION__, tok, pos, *data); - return(*data == ~0UL); + return(*data == ~0U); } if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d))) @@ -592,7 +590,7 @@ lba_wr_cfg( struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size) static int lba_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data) { - struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->dev)); + struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 tok = LBA_CFG_TOK(local_bus,devfn); @@ -695,20 +693,23 @@ lba_fixup_bus(struct pci_bus *bus) { struct list_head *ln; #ifdef FBB_SUPPORT - u16 fbb_enable = PCI_STATUS_FAST_BACK; u16 status; #endif - struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->dev)); + struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge)); int lba_portbase = HBA_PORT_BASE(ldev->hba.hba_num); DBG("lba_fixup_bus(0x%p) bus %d sysdata 0x%p\n", - bus, bus->secondary, bus->dev->platform_data); + bus, bus->secondary, bus->bridge->platform_data); /* ** Properly Setup MMIO resources for this bus. ** pci_alloc_primary_bus() mangles this. */ - if (NULL == bus->self) { + if (bus->self) { + /* PCI-PCI Bridge */ + pci_read_bridge_bases(bus); + } else { + /* Host-PCI Bridge */ int err; DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n", @@ -725,59 +726,29 @@ lba_fixup_bus(struct pci_bus *bus) BUG(); lba_dump_res(&ioport_resource, 2); } + err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space)); if (err < 0) { BUG(); lba_dump_res(&iomem_resource, 2); } - bus->resource[0] = &(ldev->hba.io_space); - bus->resource[1] = &(ldev->hba.lmmio_space); - } else { - /* KLUGE ALERT! - ** PCI-PCI Bridge resource munging. - ** This hack should go away in the near future. - ** It's based on the Alpha port. - */ - int i; - u16 cmd; - - for (i = 0; i < 4; i++) { - bus->resource[i] = - &bus->self->resource[PCI_BRIDGE_RESOURCES+i]; - bus->resource[i]->name = bus->name; +#ifdef __LP64__ + if (ldev->hba.gmmio_space.flags) { + err = request_resource(&iomem_resource, &(ldev->hba.gmmio_space)); + if (err < 0) { + BUG(); + lba_dump_res(&iomem_resource, 2); + } + bus->resource[2] = &(ldev->hba.gmmio_space); } -#if 0 - bus->resource[0]->flags |= pci_bridge_check_io(bus->self); -#else - bus->resource[0]->flags |= IORESOURCE_IO; #endif - bus->resource[1]->flags |= IORESOURCE_MEM; - bus->resource[2]->flags = 0; /* Don't support prefetchable */ - bus->resource[3]->flags = 0; /* not used */ - - /* - ** If the PPB is enabled (ie already configured) then - ** just read those values. - */ - (void) pci_read_config_word(bus->self, PCI_COMMAND, &cmd); - if (cmd & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)) { - pci_read_bridge_bases(bus); - } else { - /* Not configured. - ** For now, propagate HBA limits to the bus; - ** PCI will adjust them later. - */ - bus->resource[0]->end = ldev->hba.io_space.end; - bus->resource[1]->end = ldev->hba.lmmio_space.end; - } - /* Turn off downstream PF memory address range by default */ - bus->resource[2]->start = 1024*1024; - bus->resource[2]->end = bus->resource[2]->start - 1; + /* advertize Host bridge resources to PCI bus */ + bus->resource[0] = &(ldev->hba.io_space); + bus->resource[1] = &(ldev->hba.lmmio_space); } - list_for_each(ln, &bus->devices) { int i; struct pci_dev *dev = pci_dev_b(ln); @@ -785,7 +756,7 @@ lba_fixup_bus(struct pci_bus *bus) DBG("lba_fixup_bus() %s\n", pci_name(dev)); /* Virtualize Device/Bridge Resources. */ - for (i = 0; i < PCI_NUM_RESOURCES; i++) { + for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) { struct resource *res = &dev->resource[i]; /* If resource not allocated - skip it */ @@ -817,7 +788,7 @@ lba_fixup_bus(struct pci_bus *bus) ** No one on the bus can be allowed to use them. */ (void) pci_read_config_word(dev, PCI_STATUS, &status); - fbb_enable &= status; + bus->bridge_ctl &= ~(status & PCI_STATUS_FAST_BACK); #endif #ifdef __LP64__ @@ -1069,6 +1040,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) lba_dev->hba.bus_num.start = p->start; lba_dev->hba.bus_num.end = p->end; break; + case PAT_LMMIO: /* used to fix up pre-initialized MEM BARs */ lba_dev->hba.lmmio_space_offset = p->start - io->start; @@ -1080,23 +1052,28 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) r->flags = IORESOURCE_MEM; r->parent = r->sibling = r->child = NULL; break; + case PAT_GMMIO: - printk(KERN_WARNING MODULE_NAME - " range[%d] : ignoring GMMIO (0x%lx)\n", - i, p->start); - lba_dev->gmmio_base = p->start; + /* MMIO space > 4GB phys addr; for 64-bit BAR */ + r = &(lba_dev->hba.gmmio_space); + r->name = "LBA GMMIO"; + r->start = p->start; + r->end = p->end; + r->flags = IORESOURCE_MEM; + r->parent = r->sibling = r->child = NULL; break; + case PAT_NPIOP: printk(KERN_WARNING MODULE_NAME " range[%d] : ignoring NPIOP (0x%lx)\n", i, p->start); break; + case PAT_PIOP: /* ** Postable I/O port space is per PCI host adapter. + ** base of 64MB PIOP region */ - - /* save base of 64MB PIOP region */ lba_dev->iop_base = p->start; r = &(lba_dev->hba.io_space); @@ -1106,6 +1083,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) r->flags = IORESOURCE_IO; r->parent = r->sibling = r->child = NULL; break; + default: printk(KERN_WARNING MODULE_NAME " range[%d] : unknown pat range type (0x%lx)\n", @@ -1259,7 +1237,11 @@ lba_hw_init(struct lba_device *d) #endif /* DEBUG_LBA_PAT */ #ifdef __LP64__ -#warning FIXME add support for PDC_PAT_IO "Get slot status" - OLAR support +/* + * FIXME add support for PDC_PAT_IO "Get slot status" - OLAR support + * Only N-Class and up can really make use of Get slot status. + * maybe L-class too but I've never played with it there. + */ #endif /* PDC_PAT_BUG: exhibited in rev 40.48 on L2000 */ diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 612fb29ee5c96..7d497802b906d 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -3,7 +3,7 @@ * * (c) Copyright 2000 Red Hat Software * (c) Copyright 2000 Helge Deller - * (c) Copyright 2001-2003 Helge Deller + * (c) Copyright 2001-2004 Helge Deller * (c) Copyright 2001 Randolph Chung * * This program is free software; you can redistribute it and/or modify @@ -56,6 +56,7 @@ static int led_heartbeat = 1; static int led_diskio = 1; static int led_lanrxtx = 1; static char lcd_text[32]; +static char lcd_text_default[] = "Linux " UTS_RELEASE; #if 0 #define DPRINTK(x) printk x @@ -196,19 +197,11 @@ static int led_proc_write(struct file *file, const char *buf, break; case LED_HASLCD: + while (*cur && cur[strlen(cur)-1] == '\n') + cur[strlen(cur)-1] = 0; if (*cur == 0) - { - /* reset to default */ - lcd_print("Linux " UTS_RELEASE); - } - else - { - /* chop off trailing \n.. if the user gives multiple - * \n then it's all their fault.. */ - if (*cur && cur[strlen(cur)-1] == '\n') - cur[strlen(cur)-1] = 0; - lcd_print(cur); - } + cur = lcd_text_default; + lcd_print(cur); break; default: return 0; @@ -438,11 +431,7 @@ static __inline__ int led_get_diskio_activity(void) #define HEARTBEAT_2ND_RANGE_START (HZ*22/100) #define HEARTBEAT_2ND_RANGE_END (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN) -#if HZ==100 - #define NORMALIZED_COUNT(count) (count) -#else - #define NORMALIZED_COUNT(count) (count/(HZ/100)) -#endif +#define NORMALIZED_COUNT(count) (count/(HZ/100)) static void led_tasklet_func(unsigned long unused) { @@ -567,7 +556,7 @@ int __init register_led_driver(int model, char *cmd_reg, char *data_reg) printk(KERN_INFO "LCD display at %p,%p registered\n", LCD_CMD_REG , LCD_DATA_REG); led_func_ptr = led_LCD_driver; - lcd_print( "Linux " UTS_RELEASE ); + lcd_print( lcd_text_default ); led_type = LED_HASLCD; break; diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index ce2412acf7d0d..b756cf6f44b32 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -44,6 +44,11 @@ #define MODULE_NAME "SBA" +#ifdef CONFIG_PROC_FS +/* depends on proc fs support. But costs CPU performance */ +#undef SBA_COLLECT_STATS +#endif + /* ** The number of debug flags is a clue - this code is fragile. ** Don't even think about messing with it unless you have @@ -217,7 +222,7 @@ struct ioc { } saved[DELAYED_RESOURCE_CNT]; #endif -#ifdef CONFIG_PROC_FS +#ifdef SBA_COLLECT_STATS #define SBA_SEARCH_SAMPLE 0x100 unsigned long avg_search[SBA_SEARCH_SAMPLE]; unsigned long avg_idx; /* current index into avg_search */ @@ -560,7 +565,7 @@ static int sba_alloc_range(struct ioc *ioc, size_t size) { unsigned int pages_needed = size >> IOVP_SHIFT; -#ifdef CONFIG_PROC_FS +#ifdef SBA_COLLECT_STATS unsigned long cr_start = mfctl(16); #endif unsigned long pide; @@ -579,7 +584,8 @@ sba_alloc_range(struct ioc *ioc, size_t size) if (pide >= (ioc->res_size << 3)) { pide = sba_search_bitmap(ioc, pages_needed); if (pide >= (ioc->res_size << 3)) - panic(__FILE__ ": I/O MMU @ %lx is out of mapping resources\n", ioc->ioc_hpa); + panic("%s: I/O MMU @ %lx is out of mapping resources\n", + __FILE__, ioc->ioc_hpa); } #ifdef ASSERT_PDIR_SANITY @@ -594,7 +600,7 @@ sba_alloc_range(struct ioc *ioc, size_t size) (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map), ioc->res_bitshift ); -#ifdef CONFIG_PROC_FS +#ifdef SBA_COLLECT_STATS { unsigned long cr_end = mfctl(16); unsigned long tmp = cr_end - cr_start; @@ -636,7 +642,7 @@ sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size) __FUNCTION__, (uint) iova, size, bits_not_wanted, m, pide, res_ptr, *res_ptr); -#ifdef CONFIG_PROC_FS +#ifdef SBA_COLLECT_STATS ioc->used_pages -= bits_not_wanted; #endif @@ -854,7 +860,7 @@ sba_map_single(struct device *dev, void *addr, size_t size, sba_check_pdir(ioc,"Check before sba_map_single()"); #endif -#ifdef CONFIG_PROC_FS +#ifdef SBA_COLLECT_STATS ioc->msingle_calls++; ioc->msingle_pages += size >> IOVP_SHIFT; #endif @@ -929,7 +935,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, spin_lock_irqsave(&ioc->res_lock, flags); -#ifdef CONFIG_PROC_FS +#ifdef SBA_COLLECT_STATS ioc->usingle_calls++; ioc->usingle_pages += size >> IOVP_SHIFT; #endif @@ -1057,7 +1063,7 @@ sba_fill_pdir( printk(KERN_DEBUG " %2d : %08lx/%05x %p/%05x\n", nents, (unsigned long) sg_dma_address(startsg), cnt, - sg_virt_address(startsg), startsg->length + sg_virt_addr(startsg), startsg->length ); #else DBG_RUN_SG(" %d : %08lx/%05x %p/%05x\n", @@ -1093,7 +1099,7 @@ sba_fill_pdir( cnt += dma_offset; dma_offset=0; /* only want offset on first chunk */ cnt = ROUNDUP(cnt, IOVP_SIZE); -#ifdef CONFIG_PROC_FS +#ifdef SBA_COLLECT_STATS ioc->msg_pages += cnt >> IOVP_SHIFT; #endif do { @@ -1300,7 +1306,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, } #endif -#ifdef CONFIG_PROC_FS +#ifdef SBA_COLLECT_STATS ioc->msg_calls++; #endif @@ -1365,7 +1371,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, ioc = GET_IOC(dev); ASSERT(ioc); -#ifdef CONFIG_PROC_FS +#ifdef SBA_COLLECT_STATS ioc->usg_calls++; #endif @@ -1378,7 +1384,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, while (sg_dma_len(sglist) && nents--) { sba_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction); -#ifdef CONFIG_PROC_FS +#ifdef SBA_COLLECT_STATS ioc->usg_pages += ((sg_dma_address(sglist) & ~IOVP_MASK) + sg_dma_len(sglist) + IOVP_SIZE - 1) >> PAGE_SHIFT; ioc->usingle_calls--; /* kluge since call is unmap_sg() */ #endif @@ -1680,6 +1686,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); @@ -1766,7 +1787,8 @@ sba_common_init(struct sba_device *sba_dev) if (NULL == sba_dev->ioc[i].res_map) { - panic(__FILE__ ":%s() could not allocate resource map\n", __FUNCTION__ ); + panic("%s:%s() could not allocate resource map\n", + __FILE__, __FUNCTION__ ); } memset(sba_dev->ioc[i].res_map, 0, res_size); @@ -1829,7 +1851,9 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len) struct sba_device *sba_dev = sba_list; struct ioc *ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */ int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ +#ifdef SBA_COLLECT_STATS unsigned long i = 0, avg = 0, min, max; +#endif sprintf(buf, "%s rev %d.%d\n", sba_dev->name, @@ -1841,12 +1865,13 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len) (int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ total_pages); + sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", + buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ + +#ifdef SBA_COLLECT_STATS sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf, total_pages - ioc->used_pages, ioc->used_pages, (int) (ioc->used_pages * 100 / total_pages)); - - sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", - buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ min = max = ioc->avg_search[0]; for (i = 0; i < SBA_SEARCH_SAMPLE; i++) { @@ -1876,6 +1901,7 @@ static int sba_proc_info(char *buf, char **start, off_t offset, int len) sprintf(buf, "%spci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", buf, ioc->usg_calls, ioc->usg_pages, (int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); +#endif return strlen(buf); } diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c index 7673be9638f42..0ff55afc43aaa 100644 --- a/drivers/parisc/superio.c +++ b/drivers/parisc/superio.c @@ -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, struct pt_regs *regs) } /* 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 to 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_irq) 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_ops = { .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 *pcidev) { 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 *pcidev) 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); diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index 7c789e0f5743f..e4b2c2fec0bf0 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -24,6 +24,7 @@ #include #include #include +#include /* for udelay */ #include #include @@ -47,15 +48,17 @@ #define MUX_STATUS(status) ((status & 0xF000) == 0x8000) #define MUX_BREAK(status) ((status & 0xF000) == 0x2000) -#define UART_NR 8 -struct mux_card { - struct uart_port ports[UART_NR]; - struct uart_driver drv; - struct mux_card *next; -}; - -static struct mux_card mux_card_head = { - .next = NULL, +#define MUX_NR 256 +static unsigned int port_cnt = 0; +static struct uart_port mux_ports[MUX_NR]; + +static struct uart_driver mux_driver = { + .owner = THIS_MODULE, + .driver_name = "ttyB", + .dev_name = "ttyB", + .major = MUX_MAJOR, + .minor = 0, + .nr = MUX_NR, }; static struct timer_list mux_timer; @@ -181,7 +184,7 @@ static void mux_write(struct uart_port *port) return; } - count = (port->fifosize >> 1) - UART_GET_FIFO_CNT(port); + count = (port->fifosize) - UART_GET_FIFO_CNT(port); do { UART_PUT_CHAR(port, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); @@ -191,6 +194,9 @@ static void mux_write(struct uart_port *port) } while(--count > 0); + while(UART_GET_FIFO_CNT(port)) + udelay(1); + if(uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); @@ -361,28 +367,46 @@ static int mux_verify_port(struct uart_port *port, struct serial_struct *ser) static void mux_poll(unsigned long unused) { int i; - struct mux_card *card = &mux_card_head; - while(card) { - for(i = 0; i < UART_NR; ++i) { - if(!card->ports[i].info) - continue; + for(i = 0; i < port_cnt; ++i) { + if(!mux_ports[i].info) + continue; - mux_read(&card->ports[i]); - mux_write(&card->ports[i]); - } - card = card->next; + mux_read(&mux_ports[i]); + mux_write(&mux_ports[i]); } + mod_timer(&mux_timer, jiffies + MUX_POLL_DELAY); } #ifdef CONFIG_SERIAL_MUX_CONSOLE +static void mux_console_write(struct console *co, const char *s, unsigned count) +{ + while(count--) + pdc_iodc_putc(*s++); +} + +static int mux_console_setup(struct console *co, char *options) +{ + return 0; +} + +struct tty_driver *mux_console_device(struct console *co, int *index) +{ + *index = co->index; + return mux_driver.tty_driver; +} + static struct console mux_console = { .name = "ttyB", - .flags = CON_PRINTBUFFER, + .write = mux_console_write, + .device = mux_console_device, + .setup = mux_console_setup, + .flags = CON_BOOT|CON_PRINTBUFFER|CON_ENABLED, .index = 0, }; + #define MUX_CONSOLE &mux_console #else #define MUX_CONSOLE NULL @@ -416,77 +440,53 @@ static struct uart_ops mux_pops = { */ static int __init mux_probe(struct parisc_device *dev) { - int i, j, ret, ports, port_cnt = 0; - u8 iodc_data[8]; + int i, status, ports; + u8 iodc_data[32]; unsigned long bytecnt; struct uart_port *port; - struct mux_card *card = &mux_card_head; - ret = pdc_iodc_read(&bytecnt, dev->hpa, 0, iodc_data, 8); - if(ret != PDC_OK) { + status = pdc_iodc_read(&bytecnt, dev->hpa, 0, iodc_data, 32); + if(status != PDC_OK) { printk(KERN_ERR "Serial mux: Unable to read IODC.\n"); return 1; } ports = GET_MUX_PORTS(iodc_data); - printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.2\n", - ports); - - if(!card->drv.nr) { - init_timer(&mux_timer); - mux_timer.function = mux_poll; - } else { - port_cnt += UART_NR; - while(card->next) { - card = card->next; - port_cnt += UART_NR; - } - } - - for(i = 0; i < ports / UART_NR; ++i) { - if(card->drv.nr) { - card->next = kmalloc(sizeof(struct mux_card), GFP_KERNEL); - if(!card->next) { - printk(KERN_ERR "Serial mux: Unable to allocate memory.\n"); - return 1; - } - memset(card->next, '\0', sizeof(struct mux_card)); - card = card->next; - } + printk(KERN_INFO "Serial mux driver (%d ports) Revision: 0.3\n", ports); - card->drv.owner = THIS_MODULE; - card->drv.driver_name = "ttyB"; - card->drv.dev_name = "ttyB"; - card->drv.major = MUX_MAJOR; - card->drv.minor = port_cnt; - card->drv.nr = UART_NR; - card->drv.cons = MUX_CONSOLE; + if(!port_cnt) { + mux_driver.cons = MUX_CONSOLE; - ret = uart_register_driver(&card->drv); - if(ret) { + status = uart_register_driver(&mux_driver); + if(status) { printk(KERN_ERR "Serial mux: Unable to register driver.\n"); return 1; } - for(j = 0; j < UART_NR; ++j) { - port = &card->ports[j]; - - port->iobase = 0; - port->mapbase = dev->hpa + MUX_OFFSET + (j * MUX_LINE_OFFSET); - port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET); - port->iotype = SERIAL_IO_MEM; - port->type = PORT_MUX; - port->irq = SERIAL_IRQ_NONE; - port->uartclk = 0; - port->fifosize = MUX_FIFO_SIZE; - port->ops = &mux_pops; - port->flags = UPF_BOOT_AUTOCONF; - port->line = j; - ret = uart_add_one_port(&card->drv, port); - BUG_ON(ret); - } - port_cnt += UART_NR; + init_timer(&mux_timer); + mux_timer.function = mux_poll; + } + + for(i = 0; i < ports; ++i, ++port_cnt) { + port = &mux_ports[port_cnt]; + port->iobase = 0; + port->mapbase = dev->hpa + MUX_OFFSET + (i * MUX_LINE_OFFSET); + port->membase = ioremap(port->mapbase, MUX_LINE_OFFSET); + port->iotype = SERIAL_IO_MEM; + port->type = PORT_MUX; + port->irq = SERIAL_IRQ_NONE; + port->uartclk = 0; + port->fifosize = MUX_FIFO_SIZE; + port->ops = &mux_pops; + port->flags = UPF_BOOT_AUTOCONF; + port->line = port_cnt; + status = uart_add_one_port(&mux_driver, port); + BUG_ON(status); } + +#ifdef CONFIG_SERIAL_MUX_CONSOLE + register_console(&mux_console); +#endif return 0; } @@ -497,7 +497,7 @@ static struct parisc_device_id mux_tbl[] = { MODULE_DEVICE_TABLE(parisc, mux_tbl); -static struct parisc_driver mux_driver = { +static struct parisc_driver serial_mux_driver = { .name = "Serial MUX", .id_table = mux_tbl, .probe = mux_probe, @@ -510,7 +510,7 @@ static struct parisc_driver mux_driver = { */ static int __init mux_init(void) { - return register_parisc_driver(&mux_driver); + return register_parisc_driver(&serial_mux_driver); } /** @@ -521,13 +521,12 @@ static int __init mux_init(void) static void __exit mux_exit(void) { int i; - struct mux_card *card = &mux_card_head; - for (i = 0; i < UART_NR; i++) { - uart_remove_one_port(&card->drv, &card->ports[i]); + for (i = 0; i < port_cnt; i++) { + uart_remove_one_port(&mux_driver, &mux_ports[i]); } - uart_unregister_driver(&card->drv); + uart_unregister_driver(&mux_driver); } module_init(mux_init); diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index 7bbf41c357171..5d9a6e84c3259 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -588,18 +588,18 @@ sti_select_font(struct sti_cooked_rom *rom, static void __init sti_dump_rom(struct sti_rom *rom) { - printk(KERN_INFO "STI id %04x-%04x, conforms to spec rev. %d.%02x\n", + printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n", rom->graphics_id[0], rom->graphics_id[1], rom->revno[0] >> 4, rom->revno[0] & 0x0f); - DPRINTK((" supports %d monitors\n", rom->num_mons)); - DPRINTK((" font start %08x\n", rom->font_start)); - DPRINTK((" region list %08x\n", rom->region_list)); - DPRINTK((" init_graph %08x\n", rom->init_graph)); - DPRINTK((" bus support %02x\n", rom->bus_support)); - DPRINTK((" ext bus support %02x\n", rom->ext_bus_support)); - DPRINTK((" alternate code type %d\n", rom->alt_code_type)); + DPRINTK((" supports %d monitors\n", rom->num_mons)); + DPRINTK((" font start %08x\n", rom->font_start)); + DPRINTK((" region list %08x\n", rom->region_list)); + DPRINTK((" init_graph %08x\n", rom->init_graph)); + DPRINTK((" bus support %02x\n", rom->bus_support)); + DPRINTK((" ext bus support %02x\n", rom->ext_bus_support)); + DPRINTK((" alternate code type %d\n", rom->alt_code_type)); } @@ -869,14 +869,14 @@ test_rom: ok = 0; if ((sig & 0xff) == 0x01) { - printk(KERN_INFO "STI byte mode ROM at %08lx, hpa at %08lx\n", - address, hpa); + DPRINTK((" byte mode ROM at %08lx, hpa at %08lx\n", + address, hpa)); ok = sti_read_rom(0, sti, address); } if ((sig & 0xffff) == 0x0303) { - printk(KERN_INFO "STI word mode ROM at %08lx, hpa at %08lx\n", - address, hpa); + DPRINTK((" word mode ROM at %08lx, hpa at %08lx\n", + address, hpa)); ok = sti_read_rom(1, sti, address); } @@ -903,7 +903,7 @@ test_rom: sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request); sti_dump_outptr(sti); - printk(KERN_INFO "STI device: %s\n", sti->outptr.dev_name ); + printk(KERN_INFO " graphics card name: %s\n", sti->outptr.dev_name ); sti_roms[num_sti_roms] = sti; num_sti_roms++; diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 4694912daffa2..9a1561503e185 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -3,7 +3,7 @@ * Low level Frame buffer driver for HP workstations with * STI (standard text interface) video firmware. * - * Copyright (C) 2001-2002 Helge Deller + * Copyright (C) 2001-2004 Helge Deller * Portions Copyright (C) 2001 Thomas Bogendoerfer * * Based on: @@ -39,10 +39,10 @@ */ /* TODO: - * - remove the static fb_info to support multiple cards * - 1bpp mode is completely untested * - add support for h/w acceleration * - add hardware cursor + * - automatically disable double buffering (e.g. on RDI precisionbook laptop) */ @@ -51,6 +51,8 @@ * #undef FALLBACK_TO_1BPP to reject support for unsupported cards */ #undef FALLBACK_TO_1BPP +#undef DEBUG_STIFB_REGS /* debug sti register accesses */ + #include #include @@ -154,8 +156,27 @@ static int __initdata stifb_force_bpp[MAX_STI_ROMS]; #define READ_BYTE(fb,reg) __raw_readb((fb)->info.fix.mmio_start + (reg)) #define READ_WORD(fb,reg) __raw_readl((fb)->info.fix.mmio_start + (reg)) -#define WRITE_BYTE(value,fb,reg) __raw_writeb((value),(fb)->info.fix.mmio_start + (reg)) -#define WRITE_WORD(value,fb,reg) __raw_writel((value),(fb)->info.fix.mmio_start + (reg)) + + +#ifndef DEBUG_STIFB_REGS +# define DEBUG_OFF() +# define DEBUG_ON() +# define WRITE_BYTE(value,fb,reg) __raw_writeb((value),(fb)->info.fix.mmio_start + (reg)) +# define WRITE_WORD(value,fb,reg) __raw_writel((value),(fb)->info.fix.mmio_start + (reg)) +#else + static int debug_on = 1; +# define DEBUG_OFF() debug_on=0 +# define DEBUG_ON() debug_on=1 +# define WRITE_BYTE(value,fb,reg) do { if (debug_on) \ + printk(KERN_DEBUG "%30s: WRITE_BYTE(0x%06x) = 0x%02x (old=0x%02x)\n", \ + __FUNCTION__, reg, value, READ_BYTE(fb,reg)); \ + __raw_writeb((value),(fb)->info.fix.mmio_start + (reg)); } while (0) +# define WRITE_WORD(value,fb,reg) do { if (debug_on) \ + printk(KERN_DEBUG "%30s: WRITE_WORD(0x%06x) = 0x%08x (old=0x%08x)\n", \ + __FUNCTION__, reg, value, READ_WORD(fb,reg)); \ + __raw_writel((value),(fb)->info.fix.mmio_start + (reg)); } while (0) +#endif /* DEBUG_STIFB_REGS */ + #define ENABLE 1 /* for enabling/disabling screen */ #define DISABLE 0 @@ -390,7 +411,7 @@ ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) WRITE_WORD(val, fb, REG_6) #define NGLE_LONG_FB_ADDRESS(fbaddrbase, x, y) ( \ - (u32) (fbaddrbase) + \ + (u32) (fbaddrbase) + \ ( (unsigned int) ( (y) << 13 ) | \ (unsigned int) ( (x) << 2 ) ) \ ) @@ -449,6 +470,13 @@ SETUP_ATTR_ACCESS(struct stifb_info *fb, unsigned BufferNumber) static void SET_ATTR_SIZE(struct stifb_info *fb, int width, int height) { + /* REG_6 seems to have special values when run on a + RDI precisionbook parisc laptop (INTERNAL_EG_DX1024 or + INTERNAL_EG_X1024). The values are: + 0x2f0: internal (LCD) & external display enabled + 0x2a0: external display only + 0x000: zero on standard artist graphic cards + */ WRITE_WORD(0x00000000, fb, REG_6); WRITE_WORD((width<<16) | height, fb, REG_9); WRITE_WORD(0x05000000, fb, REG_6); @@ -730,7 +758,7 @@ hyperResetPlanes(struct stifb_info *fb, int enable) controlPlaneReg = 0x00000F00; /* 0x00000100 should be enought, but lets clear all 4 bits */ switch (enable) { - case 1: /* ENABLE */ + case ENABLE: /* clear screen */ if (IS_24_DEVICE(fb)) ngleDepth24_ClearImagePlanes(fb); @@ -750,7 +778,7 @@ hyperResetPlanes(struct stifb_info *fb, int enable) hyperUndoITE(fb); break; - case 0: /* DISABLE */ + case DISABLE: /* clear screen */ if (IS_24_DEVICE(fb)) ngleDepth24_ClearImagePlanes(fb); @@ -974,6 +1002,8 @@ stifb_setcolreg(u_int regno, u_int red, u_int green, green >>= 8; blue >>= 8; + DEBUG_OFF(); + START_IMAGE_COLORMAP_ACCESS(fb); if (fb->info.var.grayscale) { @@ -1005,6 +1035,8 @@ stifb_setcolreg(u_int regno, u_int red, u_int green, FINISH_IMAGE_COLORMAP_ACCESS(fb); } + DEBUG_ON(); + return 0; } @@ -1144,17 +1176,28 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp) /* only supported cards are allowed */ switch (fb->id) { + case CRT_ID_VISUALIZE_EG: + /* look for a double buffering device like e.g. the + "INTERNAL_EG_DX1024" in the RDI precisionbook laptop + which won't work. The same device in non-double + buffering mode returns "INTERNAL_EG_X1024". */ + if (strstr(sti->outptr.dev_name, "EG_DX")) { + printk(KERN_WARNING + "stifb: ignoring '%s'. Disable double buffering in IPL menu.\n", + sti->outptr.dev_name); + goto out_err0; + } + /* fall though */ case S9000_ID_ARTIST: case S9000_ID_HCRX: case S9000_ID_TIMBER: case S9000_ID_A1659A: case S9000_ID_A1439A: - case CRT_ID_VISUALIZE_EG: break; default: - printk(KERN_WARNING "stifb: Unsupported gfx card id 0x%08x\n", - fb->id); - goto out_err1; + printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n", + sti->outptr.dev_name, fb->id); + goto out_err0; } /* default to 8 bpp on most graphic chips */ @@ -1232,7 +1275,7 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp) "stifb: Unsupported graphics card (id=0x%08x) " "- skipping.\n", fb->id); - goto out_err1; + goto out_err0; #endif } @@ -1306,12 +1349,13 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp) sti->info = info; /* save for unregister_framebuffer() */ printk(KERN_INFO - "fb%d: %s %dx%d-%d frame buffer device, id: %04x, mmio: 0x%04lx\n", + "fb%d: %s %dx%d-%d frame buffer device, %s, id: %04x, mmio: 0x%04lx\n", fb->info.node, fix->id, var->xres, var->yres, var->bits_per_pixel, + sti->outptr.dev_name, fb->id, fix->mmio_start); @@ -1324,16 +1368,24 @@ out_err2: release_mem_region(fix->smem_start, fix->smem_len); out_err1: fb_dealloc_cmap(&info->cmap); +out_err0: kfree(fb); return -ENXIO; } +static int stifb_disabled __initdata; + int __init stifb_init(void) { struct sti_struct *sti; int i; + if (stifb_disabled) { + printk(KERN_INFO "stifb: disabled by \"stifb=off\" kernel parameter\n"); + return -ENXIO; + } + for (i = 1; i < MAX_STI_ROMS; i++) { sti = sti_get_rom(i); if (!sti) @@ -1379,6 +1431,11 @@ stifb_setup(char *options) if (!options || !*options) return 0; + if (strncmp(options, "off", 3) == 0) { + stifb_disabled = 1; + options += 3; + } + if (strncmp(options, "bpp", 3) == 0) { options += 3; for (i = 0; i < MAX_STI_ROMS; i++) { -- 2.53.0