]> git.hungrycats.org Git - linux/commitdiff
[PATCH] PA-RISC driver update for 2.6.2
authorMatthew Wilcox <willy@debian.org>
Fri, 6 Feb 2004 07:07:25 +0000 (23:07 -0800)
committerDavid S. Miller <davem@kernel.bkbits.net>
Fri, 6 Feb 2004 07:07:25 +0000 (23:07 -0800)
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)

13 files changed:
drivers/parisc/Kconfig
drivers/parisc/ccio-dma.c
drivers/parisc/dino.c
drivers/parisc/eisa_eeprom.c
drivers/parisc/iosapic.c
drivers/parisc/iosapic_private.h
drivers/parisc/lba_pci.c
drivers/parisc/led.c
drivers/parisc/sba_iommu.c
drivers/parisc/superio.c
drivers/serial/mux.c
drivers/video/console/sticore.c
drivers/video/stifb.c

index 37aa2f69bfb49294d55dfa08f8e95fb992bed221..fa875ae1cac2b52dbfa15455aaaa064845632a95 100644 (file)
@@ -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 d88555b393a14f6781b834292d3111b809273039..696c3e1656544157bad4f74fa8d8945de231257a 100644 (file)
@@ -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;
index a2bfdfaacb8eb526776e65aa446fab1f5c83ebbd..0b28122303c5ba55ab3bc7a25a42d625fd3fc5be 100644 (file)
@@ -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);
index bda206c1393f1c3db13cbaa984e330f787457503..d16724dbe890c37ed4eb49311dc68b2fd490e700 100644 (file)
@@ -1,3 +1,24 @@
+/* 
+ *    EISA "eeprom" support routines
+ *
+ *    Copyright (C) 2001 Thomas Bogendoerfer <tsbogend 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
+ */
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
index 9eb6ada6d192c46ec0cc914f08c46ad3bcdb58b9..60466bd12a293c6c06674aa0933d6a05ed385384 100644 (file)
@@ -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);
 }
 
 
index e2d297b6a2105897bd3e4ecb1c6daaafda0d06fd..8eae695fa36a2e2345d9c337381058e1aebe27f9 100644 (file)
@@ -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 */
 };
 
 
index b1a1180db597c89f229577b94a98ede4db338c05..269265d448f060d2cd99a0c38eacbd1770cafc29 100644 (file)
@@ -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 */
index 612fb29ee5c96368ee71312100606a6a352fb878..7d497802b906d6a18fc9b0c05ae56a562d55b1cb 100644 (file)
@@ -3,7 +3,7 @@
  *
  *      (c) Copyright 2000 Red Hat Software
  *      (c) Copyright 2000 Helge Deller <hdeller@redhat.com>
- *      (c) Copyright 2001-2003 Helge Deller <deller@gmx.de>
+ *      (c) Copyright 2001-2004 Helge Deller <deller@gmx.de>
  *      (c) Copyright 2001 Randolph Chung <tausq@debian.org>
  *
  *      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;
 
index ce2412acf7d0d84cae6d1c3e568c3326a5c8503b..b756cf6f44b32eddf54cc0472c2dcf0b9c2c1fb7 100644 (file)
 
 #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);
 }
index 7673be9638f426de2c11076f7e945fc183c3e86d..0ff55afc43aaa0da59735ca9a4c5b1fb0daa109d 100644 (file)
@@ -9,7 +9,8 @@
  *     (C) Copyright 2000 Linuxcare Canada, Inc.
  *     (C) Copyright 2000 Martin K. Petersen <mkp@linuxcare.com>
  *     (C) Copyright 2000 Alex deVries <alex@linuxcare.com>
- *      (C) Copyright 2001 John Marvin <jsm@fc.hp.com>
+ *      (C) Copyright 2001 John Marvin <jsm fc hp com>
+ *      (C) Copyright 2003 Grant Grundler <grundler 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
 #include <asm/irq.h>
 #include <asm/superio.h>
 
-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);
index 7c789e0f5743f6d6e949cdc3a0f89b27ef1627a8..e4b2c2fec0bf04945f5aab76c6bf3660a00f0812 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/slab.h>
+#include <linux/delay.h> /* for udelay */
 #include <asm/io.h>
 #include <asm/parisc-device.h>
 
 #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);
index 7bbf41c3571711909181fb6981ccae2467bf4d8f..5d9a6e84c3259d005ee955f2f0cd9e3a4b155eef 100644 (file)
@@ -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++;
index 4694912daffa2953b25fdf5ea5e3213f5bce9e4a..9a1561503e185250efe69104d6eaf4158c14b74e 100644 (file)
@@ -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 <deller@gmx.de>
+ * Copyright (C) 2001-2004 Helge Deller <deller@gmx.de>
  * Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
  * 
  * Based on:
  */
 
 /* 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 <linux/config.h>
 #include <linux/module.h>
@@ -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++) {