aboutsummaryrefslogtreecommitdiff
path: root/drivers/parisc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/parisc
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/parisc')
-rw-r--r--drivers/parisc/Kconfig169
-rw-r--r--drivers/parisc/Makefile27
-rw-r--r--drivers/parisc/README.dino28
-rw-r--r--drivers/parisc/asp.c132
-rw-r--r--drivers/parisc/ccio-dma.c1593
-rw-r--r--drivers/parisc/ccio-rm-dma.c201
-rw-r--r--drivers/parisc/dino.c1044
-rw-r--r--drivers/parisc/eisa.c464
-rw-r--r--drivers/parisc/eisa_eeprom.c134
-rw-r--r--drivers/parisc/eisa_enumerator.c521
-rw-r--r--drivers/parisc/gsc.c245
-rw-r--r--drivers/parisc/gsc.h47
-rw-r--r--drivers/parisc/hppb.c109
-rw-r--r--drivers/parisc/iommu-helpers.h171
-rw-r--r--drivers/parisc/iosapic.c921
-rw-r--r--drivers/parisc/iosapic_private.h188
-rw-r--r--drivers/parisc/lasi.c240
-rw-r--r--drivers/parisc/lba_pci.c1649
-rw-r--r--drivers/parisc/led.c760
-rw-r--r--drivers/parisc/pdc_stable.c735
-rw-r--r--drivers/parisc/power.c278
-rw-r--r--drivers/parisc/sba_iommu.c2165
-rw-r--r--drivers/parisc/superio.c508
-rw-r--r--drivers/parisc/wax.c140
24 files changed, 12469 insertions, 0 deletions
diff --git a/drivers/parisc/Kconfig b/drivers/parisc/Kconfig
new file mode 100644
index 00000000000..3f5de867acd
--- /dev/null
+++ b/drivers/parisc/Kconfig
@@ -0,0 +1,169 @@
+menu "Bus options (PCI, PCMCIA, EISA, GSC, ISA)"
+
+config GSC
+ bool "VSC/GSC/HSC bus support"
+ default y
+ help
+ The VSC, GSC and HSC busses were used from the earliest 700-series
+ workstations up to and including the C360/J2240 workstations. They
+ were also used in servers from the E-class to the K-class. They
+ are not found in B1000, C3000, J5000, A500, L1000, N4000 and upwards.
+ If in doubt, say "Y".
+
+config HPPB
+ bool "HP-PB bus support"
+ depends on GSC
+ help
+ The HP-PB bus was used in the Nova class and K-class servers.
+ If in doubt, say "Y"
+
+config IOMMU_CCIO
+ bool "U2/Uturn I/O MMU"
+ depends on GSC
+ help
+ Say Y here to enable DMA management routines for the first
+ generation of PA-RISC cache-coherent machines. Programs the
+ U2/Uturn chip in "Virtual Mode" and use the I/O MMU.
+
+config GSC_LASI
+ bool "Lasi I/O support"
+ depends on GSC
+ help
+ Say Y here to support the Lasi multifunction chip found in
+ many PA-RISC workstations & servers. It includes interfaces
+ for a parallel port, serial port, NCR 53c710 SCSI, Apricot
+ Ethernet, Harmony audio, PS/2 keyboard & mouse, ISDN, telephony
+ and floppy. Note that you must still enable all the individual
+ drivers for these chips.
+
+config GSC_WAX
+ bool "Wax I/O support"
+ depends on GSC
+ help
+ Say Y here to support the Wax multifunction chip found in some
+ older systems, including B/C/D/R class and 715/64, 715/80 and
+ 715/100. Wax includes an EISA adapter, a serial port (not always
+ used), a HIL interface chip and is also known to be used as the
+ GSC bridge for an X.25 GSC card.
+
+config EISA
+ bool "EISA support"
+ depends on GSC
+ help
+ Say Y here if you have an EISA bus in your machine. This code
+ supports both the Mongoose & Wax EISA adapters. It is sadly
+ incomplete and lacks support for card-to-host DMA.
+
+source "drivers/eisa/Kconfig"
+
+config ISA
+ bool "ISA support"
+ depends on EISA
+ help
+ If you want to plug an ISA card into your EISA bus, say Y here.
+ Most people should say N.
+
+config PCI
+ bool "PCI support"
+ help
+ All recent HP machines have PCI slots, and you should say Y here
+ if you have a recent machine. If you are convinced you do not have
+ PCI slots in your machine (eg a 712), then you may say "N" here.
+ Beware that some GSC cards have a Dino onboard and PCI inside them,
+ so it may be safest to say "Y" anyway.
+
+source "drivers/pci/Kconfig"
+
+config GSC_DINO
+ bool "GSCtoPCI/Dino PCI support"
+ depends on PCI && GSC
+ help
+ Say Y here to support the Dino & Cujo GSC to PCI bridges found in
+ machines from the B132 to the C360, the J2240 and the A180. Some
+ GSC/HSC cards (eg gigabit & dual 100 Mbit Ethernet) have a Dino on
+ the card, and you also need to say Y here if you have such a card.
+ Note that Dino also supplies one of the serial ports on certain
+ machines. If in doubt, say Y.
+
+config PCI_LBA
+ bool "LBA/Elroy PCI support"
+ depends on PCI
+ help
+ Say Y here to support the Elroy PCI Lower Bus Adapter. This is
+ present on B, C, J, L and N-class machines with 4-digit model
+ numbers and the A400/A500.
+
+config IOSAPIC
+ bool
+ depends on PCI_LBA
+ default PCI_LBA
+
+config IOMMU_SBA
+ bool
+ depends on PCI_LBA
+ default PCI_LBA
+
+#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.
+
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/hotplug/Kconfig"
+
+endmenu
+
+menu "PA-RISC specific drivers"
+
+config SUPERIO
+ bool "SuperIO (SuckyIO) support"
+ depends on PCI_LBA
+ default y
+ help
+ Say Y here to support the SuperIO chip found in Bxxxx, C3xxx and
+ J5xxx+ machines. This enables IDE, Floppy, Parallel Port, and
+ Serial port on those machines.
+
+config CHASSIS_LCD_LED
+ bool "Chassis LCD and LED support"
+ default y
+ help
+ Say Y here if you want to enable support for the Heartbeat,
+ Disk/Network activities LEDs on some PA-RISC machines,
+ or support for the LCD that can be found on recent material.
+
+ This has nothing to do with LED State support for A and E class.
+
+ If unsure, say Y.
+
+config PDC_CHASSIS
+ bool "PDC chassis State Panel support"
+ default y
+ help
+ Say Y here if you want to enable support for the LED State front
+ panel as found on E class, and support for the GSP Virtual Front
+ Panel (LED State and message logging) as found on high end
+ servers such as A, L and N-class.
+
+ This has nothing to do with Chassis LCD and LED support.
+
+ If unsure, say Y.
+
+config PDC_STABLE
+ tristate "PDC Stable Storage support"
+ depends on SYSFS
+ default y
+ help
+ Say Y here if you want to enable support for accessing Stable Storage
+ variables (PDC non volatile variables such as Primary Boot Path,
+ Console Path, Autoboot, Autosearch, etc) through SysFS.
+
+ If unsure, say Y.
+
+ To compile this driver as a module, choose M here.
+ The module will be called pdc_stable.
+
+endmenu
diff --git a/drivers/parisc/Makefile b/drivers/parisc/Makefile
new file mode 100644
index 00000000000..f95cab57133
--- /dev/null
+++ b/drivers/parisc/Makefile
@@ -0,0 +1,27 @@
+#
+# Makefile for most of the non-PCI devices in PA-RISC machines
+#
+
+# I/O SAPIC is also on IA64 platforms.
+# The two could be merged into a common source some day.
+obj-$(CONFIG_IOSAPIC) += iosapic.o
+obj-$(CONFIG_IOMMU_SBA) += sba_iommu.o
+obj-$(CONFIG_PCI_LBA) += lba_pci.o
+
+# Only use one of them: ccio-rm-dma is for PCX-W systems *only*
+# obj-$(CONFIG_IOMMU_CCIO) += ccio-rm-dma.o
+obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o
+
+obj-$(CONFIG_GSC) += gsc.o
+
+obj-$(CONFIG_HPPB) += hppb.o
+obj-$(CONFIG_GSC_DINO) += dino.o
+obj-$(CONFIG_GSC_LASI) += lasi.o asp.o
+obj-$(CONFIG_GSC_WAX) += wax.o
+obj-$(CONFIG_EISA) += eisa.o eisa_enumerator.o eisa_eeprom.o
+
+obj-$(CONFIG_SUPERIO) += superio.o
+obj-$(CONFIG_CHASSIS_LCD_LED) += led.o
+obj-$(CONFIG_PDC_STABLE) += pdc_stable.o
+obj-y += power.o
+
diff --git a/drivers/parisc/README.dino b/drivers/parisc/README.dino
new file mode 100644
index 00000000000..097324f34bb
--- /dev/null
+++ b/drivers/parisc/README.dino
@@ -0,0 +1,28 @@
+/*
+** HP VISUALIZE Workstation PCI Bus Defect
+**
+** "HP has discovered a potential system defect that can affect
+** the behavior of five models of HP VISUALIZE workstations when
+** equipped with third-party or customer-installed PCI I/O expansion
+** cards. The defect is limited to the HP C180, C160, C160L, B160L,
+** and B132L VISUALIZE workstations, and will only be encountered
+** when data is transmitted through PCI I/O expansion cards on the
+** PCI bus. HP-supplied graphics cards that utilize the PCI bus are
+** not affected."
+**
+** REVISIT: "go/pci_defect" link below is stale.
+** HP Internal can use <http://hpfcdma.fc.hp.com:80/Dino/>
+**
+** Product First Good Serial Number
+** C200/C240 (US) US67350000
+**B132L+/B180 (US) US67390000
+** C200 (Europe) 3713G01000
+** B180L (Europe) 3720G01000
+**
+** Note that many boards were fixed/replaced under a free replacement
+** program. Assume a machine is only "suspect" until proven otherwise.
+**
+** "The pci_check program will also be available as application
+** patch PHSS_12295"
+*/
+
diff --git a/drivers/parisc/asp.c b/drivers/parisc/asp.c
new file mode 100644
index 00000000000..38860996713
--- /dev/null
+++ b/drivers/parisc/asp.c
@@ -0,0 +1,132 @@
+/*
+ * ASP Device Driver
+ *
+ * (c) Copyright 2000 The Puffin Group Inc.
+ *
+ * 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.
+ *
+ * by Helge Deller <deller@gmx.de>
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/led.h>
+
+#include "gsc.h"
+
+#define ASP_GSC_IRQ 3 /* hardcoded interrupt for GSC */
+
+#define ASP_VER_OFFSET 0x20 /* offset of ASP version */
+
+#define ASP_LED_ADDR 0xf0800020
+
+#define VIPER_INT_WORD 0xFFFBF088 /* addr of viper interrupt word */
+
+static struct gsc_asic asp;
+
+static void asp_choose_irq(struct parisc_device *dev, void *ctrl)
+{
+ int irq;
+
+ switch (dev->id.sversion) {
+ case 0x71: irq = 9; break; /* SCSI */
+ case 0x72: irq = 8; break; /* LAN */
+ case 0x73: irq = 1; break; /* HIL */
+ case 0x74: irq = 7; break; /* Centronics */
+ case 0x75: irq = (dev->hw_path == 4) ? 5 : 6; break; /* RS232 */
+ case 0x76: irq = 10; break; /* EISA BA */
+ case 0x77: irq = 11; break; /* Graphics1 */
+ case 0x7a: irq = 13; break; /* Audio (Bushmaster) */
+ case 0x7b: irq = 13; break; /* Audio (Scorpio) */
+ case 0x7c: irq = 3; break; /* FW SCSI */
+ case 0x7d: irq = 4; break; /* FDDI */
+ case 0x7f: irq = 13; break; /* Audio (Outfield) */
+ default: return; /* Unknown */
+ }
+
+ gsc_asic_assign_irq(ctrl, irq, &dev->irq);
+
+ switch (dev->id.sversion) {
+ case 0x73: irq = 2; break; /* i8042 High-priority */
+ case 0x76: irq = 0; break; /* EISA BA */
+ default: return; /* Other */
+ }
+
+ gsc_asic_assign_irq(ctrl, irq, &dev->aux_irq);
+}
+
+/* There are two register ranges we're interested in. Interrupt /
+ * Status / LED are at 0xf080xxxx and Asp special registers are at
+ * 0xf082fxxx. PDC only tells us that Asp is at 0xf082f000, so for
+ * the purposes of interrupt handling, we have to tell other bits of
+ * the kernel to look at the other registers.
+ */
+#define ASP_INTERRUPT_ADDR 0xf0800000
+
+int __init
+asp_init_chip(struct parisc_device *dev)
+{
+ struct gsc_irq gsc_irq;
+ int ret;
+
+ asp.version = gsc_readb(dev->hpa + ASP_VER_OFFSET) & 0xf;
+ asp.name = (asp.version == 1) ? "Asp" : "Cutoff";
+ asp.hpa = ASP_INTERRUPT_ADDR;
+
+ printk(KERN_INFO "%s version %d at 0x%lx found.\n",
+ asp.name, asp.version, dev->hpa);
+
+ /* the IRQ ASP should use */
+ ret = -EBUSY;
+ dev->irq = gsc_claim_irq(&gsc_irq, ASP_GSC_IRQ);
+ if (dev->irq < 0) {
+ printk(KERN_ERR "%s(): cannot get GSC irq\n", __FUNCTION__);
+ goto out;
+ }
+
+ asp.eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
+
+ ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "asp", &asp);
+ if (ret < 0)
+ goto out;
+
+ /* Program VIPER to interrupt on the ASP irq */
+ gsc_writel((1 << (31 - ASP_GSC_IRQ)),VIPER_INT_WORD);
+
+ /* Done init'ing, register this driver */
+ ret = gsc_common_setup(dev, &asp);
+ if (ret)
+ goto out;
+
+ gsc_fixup_irqs(dev, &asp, asp_choose_irq);
+ /* Mongoose is a sibling of Asp, not a child... */
+ gsc_fixup_irqs(parisc_parent(dev), &asp, asp_choose_irq);
+
+ /* initialize the chassis LEDs */
+#ifdef CONFIG_CHASSIS_LCD_LED
+ register_led_driver(DISPLAY_MODEL_OLD_ASP, LED_CMD_REG_NONE,
+ ASP_LED_ADDR);
+#endif
+
+ out:
+ return ret;
+}
+
+static struct parisc_device_id asp_tbl[] = {
+ { HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00070 },
+ { 0, }
+};
+
+struct parisc_driver asp_driver = {
+ .name = "Asp",
+ .id_table = asp_tbl,
+ .probe = asp_init_chip,
+};
diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
new file mode 100644
index 00000000000..0e98a9d9834
--- /dev/null
+++ b/drivers/parisc/ccio-dma.c
@@ -0,0 +1,1593 @@
+/*
+** ccio-dma.c:
+** DMA management routines for first generation cache-coherent machines.
+** Program U2/Uturn in "Virtual Mode" and use the I/O MMU.
+**
+** (c) Copyright 2000 Grant Grundler
+** (c) Copyright 2000 Ryan Bradetich
+** (c) Copyright 2000 Hewlett-Packard Company
+**
+** 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.
+**
+**
+** "Real Mode" operation refers to U2/Uturn chip operation.
+** U2/Uturn were designed to perform coherency checks w/o using
+** the I/O MMU - basically what x86 does.
+**
+** Philipp Rumpf has a "Real Mode" driver for PCX-W machines at:
+** CVSROOT=:pserver:anonymous@198.186.203.37:/cvsroot/linux-parisc
+** cvs -z3 co linux/arch/parisc/kernel/dma-rm.c
+**
+** I've rewritten his code to work under TPG's tree. See ccio-rm-dma.c.
+**
+** Drawbacks of using Real Mode are:
+** o outbound DMA is slower - U2 won't prefetch data (GSC+ XQL signal).
+** o Inbound DMA less efficient - U2 can't use DMA_FAST attribute.
+** o Ability to do scatter/gather in HW is lost.
+** o Doesn't work under PCX-U/U+ machines since they didn't follow
+** the coherency design originally worked out. Only PCX-W does.
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/reboot.h>
+
+#include <asm/byteorder.h>
+#include <asm/cache.h> /* for L1_CACHE_BYTES */
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/hardware.h> /* for register_module() */
+#include <asm/parisc-device.h>
+
+/*
+** Choose "ccio" since that's what HP-UX calls it.
+** Make it easier for folks to migrate from one to the other :^)
+*/
+#define MODULE_NAME "ccio"
+
+#undef DEBUG_CCIO_RES
+#undef DEBUG_CCIO_RUN
+#undef DEBUG_CCIO_INIT
+#undef DEBUG_CCIO_RUN_SG
+
+#ifdef CONFIG_PROC_FS
+/*
+ * CCIO_SEARCH_TIME can help measure how fast the bitmap search is.
+ * impacts performance though - ditch it if you don't use it.
+ */
+#define CCIO_SEARCH_TIME
+#undef CCIO_MAP_STATS
+#else
+#undef CCIO_SEARCH_TIME
+#undef CCIO_MAP_STATS
+#endif
+
+#include <linux/proc_fs.h>
+#include <asm/runway.h> /* for proc_runway_root */
+
+#ifdef DEBUG_CCIO_INIT
+#define DBG_INIT(x...) printk(x)
+#else
+#define DBG_INIT(x...)
+#endif
+
+#ifdef DEBUG_CCIO_RUN
+#define DBG_RUN(x...) printk(x)
+#else
+#define DBG_RUN(x...)
+#endif
+
+#ifdef DEBUG_CCIO_RES
+#define DBG_RES(x...) printk(x)
+#else
+#define DBG_RES(x...)
+#endif
+
+#ifdef DEBUG_CCIO_RUN_SG
+#define DBG_RUN_SG(x...) printk(x)
+#else
+#define DBG_RUN_SG(x...)
+#endif
+
+#define CCIO_INLINE /* inline */
+#define WRITE_U32(value, addr) gsc_writel(value, (u32 *)(addr))
+#define READ_U32(addr) gsc_readl((u32 *)(addr))
+
+#define U2_IOA_RUNWAY 0x580
+#define U2_BC_GSC 0x501
+#define UTURN_IOA_RUNWAY 0x581
+#define UTURN_BC_GSC 0x502
+
+#define IOA_NORMAL_MODE 0x00020080 /* IO_CONTROL to turn on CCIO */
+#define CMD_TLB_DIRECT_WRITE 35 /* IO_COMMAND for I/O TLB Writes */
+#define CMD_TLB_PURGE 33 /* IO_COMMAND to Purge I/O TLB entry */
+
+struct ioa_registers {
+ /* Runway Supervisory Set */
+ volatile int32_t unused1[12];
+ volatile uint32_t io_command; /* Offset 12 */
+ volatile uint32_t io_status; /* Offset 13 */
+ volatile uint32_t io_control; /* Offset 14 */
+ volatile int32_t unused2[1];
+
+ /* Runway Auxiliary Register Set */
+ volatile uint32_t io_err_resp; /* Offset 0 */
+ volatile uint32_t io_err_info; /* Offset 1 */
+ volatile uint32_t io_err_req; /* Offset 2 */
+ volatile uint32_t io_err_resp_hi; /* Offset 3 */
+ volatile uint32_t io_tlb_entry_m; /* Offset 4 */
+ volatile uint32_t io_tlb_entry_l; /* Offset 5 */
+ volatile uint32_t unused3[1];
+ volatile uint32_t io_pdir_base; /* Offset 7 */
+ volatile uint32_t io_io_low_hv; /* Offset 8 */
+ volatile uint32_t io_io_high_hv; /* Offset 9 */
+ volatile uint32_t unused4[1];
+ volatile uint32_t io_chain_id_mask; /* Offset 11 */
+ volatile uint32_t unused5[2];
+ volatile uint32_t io_io_low; /* Offset 14 */
+ volatile uint32_t io_io_high; /* Offset 15 */
+};
+
+/*
+** IOA Registers
+** -------------
+**
+** Runway IO_CONTROL Register (+0x38)
+**
+** The Runway IO_CONTROL register controls the forwarding of transactions.
+**
+** | 0 ... 13 | 14 15 | 16 ... 21 | 22 | 23 24 | 25 ... 31 |
+** | HV | TLB | reserved | HV | mode | reserved |
+**
+** o mode field indicates the address translation of transactions
+** forwarded from Runway to GSC+:
+** Mode Name Value Definition
+** Off (default) 0 Opaque to matching addresses.
+** Include 1 Transparent for matching addresses.
+** Peek 3 Map matching addresses.
+**
+** + "Off" mode: Runway transactions which match the I/O range
+** specified by the IO_IO_LOW/IO_IO_HIGH registers will be ignored.
+** + "Include" mode: all addresses within the I/O range specified
+** by the IO_IO_LOW and IO_IO_HIGH registers are transparently
+** forwarded. This is the I/O Adapter's normal operating mode.
+** + "Peek" mode: used during system configuration to initialize the
+** GSC+ bus. Runway Write_Shorts in the address range specified by
+** IO_IO_LOW and IO_IO_HIGH are forwarded through the I/O Adapter
+** *AND* the GSC+ address is remapped to the Broadcast Physical
+** Address space by setting the 14 high order address bits of the
+** 32 bit GSC+ address to ones.
+**
+** o TLB field affects transactions which are forwarded from GSC+ to Runway.
+** "Real" mode is the poweron default.
+**
+** TLB Mode Value Description
+** Real 0 No TLB translation. Address is directly mapped and the
+** virtual address is composed of selected physical bits.
+** Error 1 Software fills the TLB manually.
+** Normal 2 IOA fetches IO TLB misses from IO PDIR (in host memory).
+**
+**
+** IO_IO_LOW_HV +0x60 (HV dependent)
+** IO_IO_HIGH_HV +0x64 (HV dependent)
+** IO_IO_LOW +0x78 (Architected register)
+** IO_IO_HIGH +0x7c (Architected register)
+**
+** IO_IO_LOW and IO_IO_HIGH set the lower and upper bounds of the
+** I/O Adapter address space, respectively.
+**
+** 0 ... 7 | 8 ... 15 | 16 ... 31 |
+** 11111111 | 11111111 | address |
+**
+** Each LOW/HIGH pair describes a disjoint address space region.
+** (2 per GSC+ port). Each incoming Runway transaction address is compared
+** with both sets of LOW/HIGH registers. If the address is in the range
+** greater than or equal to IO_IO_LOW and less than IO_IO_HIGH the transaction
+** for forwarded to the respective GSC+ bus.
+** Specify IO_IO_LOW equal to or greater than IO_IO_HIGH to avoid specifying
+** an address space region.
+**
+** In order for a Runway address to reside within GSC+ extended address space:
+** Runway Address [0:7] must identically compare to 8'b11111111
+** Runway Address [8:11] must be equal to IO_IO_LOW(_HV)[16:19]
+** Runway Address [12:23] must be greater than or equal to
+** IO_IO_LOW(_HV)[20:31] and less than IO_IO_HIGH(_HV)[20:31].
+** Runway Address [24:39] is not used in the comparison.
+**
+** When the Runway transaction is forwarded to GSC+, the GSC+ address is
+** as follows:
+** GSC+ Address[0:3] 4'b1111
+** GSC+ Address[4:29] Runway Address[12:37]
+** GSC+ Address[30:31] 2'b00
+**
+** All 4 Low/High registers must be initialized (by PDC) once the lower bus
+** is interrogated and address space is defined. The operating system will
+** modify the architectural IO_IO_LOW and IO_IO_HIGH registers following
+** the PDC initialization. However, the hardware version dependent IO_IO_LOW
+** and IO_IO_HIGH registers should not be subsequently altered by the OS.
+**
+** Writes to both sets of registers will take effect immediately, bypassing
+** the queues, which ensures that subsequent Runway transactions are checked
+** against the updated bounds values. However reads are queued, introducing
+** the possibility of a read being bypassed by a subsequent write to the same
+** register. This sequence can be avoided by having software wait for read
+** returns before issuing subsequent writes.
+*/
+
+struct ioc {
+ struct ioa_registers *ioc_hpa; /* I/O MMU base address */
+ u8 *res_map; /* resource map, bit == pdir entry */
+ u64 *pdir_base; /* physical base address */
+ u32 pdir_size; /* bytes, function of IOV Space size */
+ u32 res_hint; /* next available IOVP -
+ circular search */
+ u32 res_size; /* size of resource map in bytes */
+ spinlock_t res_lock;
+
+#ifdef CCIO_SEARCH_TIME
+#define CCIO_SEARCH_SAMPLE 0x100
+ unsigned long avg_search[CCIO_SEARCH_SAMPLE];
+ unsigned long avg_idx; /* current index into avg_search */
+#endif
+#ifdef CCIO_MAP_STATS
+ unsigned long used_pages;
+ unsigned long msingle_calls;
+ unsigned long msingle_pages;
+ unsigned long msg_calls;
+ unsigned long msg_pages;
+ unsigned long usingle_calls;
+ unsigned long usingle_pages;
+ unsigned long usg_calls;
+ unsigned long usg_pages;
+#endif
+ unsigned short cujo20_bug;
+
+ /* STUFF We don't need in performance path */
+ u32 chainid_shift; /* specify bit location of chain_id */
+ struct ioc *next; /* Linked list of discovered iocs */
+ const char *name; /* device name from firmware */
+ unsigned int hw_path; /* the hardware path this ioc is associatd with */
+ struct pci_dev *fake_pci_dev; /* the fake pci_dev for non-pci devs */
+ struct resource mmio_region[2]; /* The "routed" MMIO regions */
+};
+
+static struct ioc *ioc_list;
+static int ioc_count;
+
+/**************************************************************
+*
+* I/O Pdir Resource Management
+*
+* Bits set in the resource map are in use.
+* Each bit can represent a number of pages.
+* LSbs represent lower addresses (IOVA's).
+*
+* This was was copied from sba_iommu.c. Don't try to unify
+* the two resource managers unless a way to have different
+* allocation policies is also adjusted. We'd like to avoid
+* I/O TLB thrashing by having resource allocation policy
+* match the I/O TLB replacement policy.
+*
+***************************************************************/
+#define IOVP_SIZE PAGE_SIZE
+#define IOVP_SHIFT PAGE_SHIFT
+#define IOVP_MASK PAGE_MASK
+
+/* Convert from IOVP to IOVA and vice versa. */
+#define CCIO_IOVA(iovp,offset) ((iovp) | (offset))
+#define CCIO_IOVP(iova) ((iova) & IOVP_MASK)
+
+#define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT)
+#define MKIOVP(pdir_idx) ((long)(pdir_idx) << IOVP_SHIFT)
+#define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset)
+#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1))
+
+/*
+** Don't worry about the 150% average search length on a miss.
+** If the search wraps around, and passes the res_hint, it will
+** cause the kernel to panic anyhow.
+*/
+#define CCIO_SEARCH_LOOP(ioc, res_idx, mask, size) \
+ for(; res_ptr < res_end; ++res_ptr) { \
+ if(0 == (*res_ptr & mask)) { \
+ *res_ptr |= mask; \
+ res_idx = (unsigned int)((unsigned long)res_ptr - (unsigned long)ioc->res_map); \
+ ioc->res_hint = res_idx + (size >> 3); \
+ goto resource_found; \
+ } \
+ }
+
+#define CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, size) \
+ u##size *res_ptr = (u##size *)&((ioc)->res_map[ioa->res_hint & ~((size >> 3) - 1)]); \
+ u##size *res_end = (u##size *)&(ioc)->res_map[ioa->res_size]; \
+ CCIO_SEARCH_LOOP(ioc, res_idx, mask, size); \
+ res_ptr = (u##size *)&(ioc)->res_map[0]; \
+ CCIO_SEARCH_LOOP(ioa, res_idx, mask, size);
+
+/*
+** Find available bit in this ioa's resource map.
+** Use a "circular" search:
+** o Most IOVA's are "temporary" - avg search time should be small.
+** o keep a history of what happened for debugging
+** o KISS.
+**
+** Perf optimizations:
+** o search for log2(size) bits at a time.
+** o search for available resource bits using byte/word/whatever.
+** o use different search for "large" (eg > 4 pages) or "very large"
+** (eg > 16 pages) mappings.
+*/
+
+/**
+ * ccio_alloc_range - Allocate pages in the ioc's resource map.
+ * @ioc: The I/O Controller.
+ * @pages_needed: The requested number of pages to be mapped into the
+ * I/O Pdir...
+ *
+ * This function searches the resource map of the ioc to locate a range
+ * of available pages for the requested size.
+ */
+static int
+ccio_alloc_range(struct ioc *ioc, size_t size)
+{
+ unsigned int pages_needed = size >> IOVP_SHIFT;
+ unsigned int res_idx;
+#ifdef CCIO_SEARCH_TIME
+ unsigned long cr_start = mfctl(16);
+#endif
+
+ BUG_ON(pages_needed == 0);
+ BUG_ON((pages_needed * IOVP_SIZE) > DMA_CHUNK_SIZE);
+
+ DBG_RES("%s() size: %d pages_needed %d\n",
+ __FUNCTION__, size, pages_needed);
+
+ /*
+ ** "seek and ye shall find"...praying never hurts either...
+ ** ggg sacrifices another 710 to the computer gods.
+ */
+
+ if (pages_needed <= 8) {
+ /*
+ * LAN traffic will not thrash the TLB IFF the same NIC
+ * uses 8 adjacent pages to map seperate payload data.
+ * ie the same byte in the resource bit map.
+ */
+#if 0
+ /* FIXME: bit search should shift it's way through
+ * an unsigned long - not byte at a time. As it is now,
+ * we effectively allocate this byte to this mapping.
+ */
+ unsigned long mask = ~(~0UL >> pages_needed);
+ CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 8);
+#else
+ CCIO_FIND_FREE_MAPPING(ioc, res_idx, 0xff, 8);
+#endif
+ } else if (pages_needed <= 16) {
+ CCIO_FIND_FREE_MAPPING(ioc, res_idx, 0xffff, 16);
+ } else if (pages_needed <= 32) {
+ CCIO_FIND_FREE_MAPPING(ioc, res_idx, ~(unsigned int)0, 32);
+#ifdef __LP64__
+ } else if (pages_needed <= 64) {
+ CCIO_FIND_FREE_MAPPING(ioc, res_idx, ~0UL, 64);
+#endif
+ } else {
+ panic("%s: %s() Too many pages to map. pages_needed: %u\n",
+ __FILE__, __FUNCTION__, pages_needed);
+ }
+
+ panic("%s: %s() I/O MMU is out of mapping resources.\n", __FILE__,
+ __FUNCTION__);
+
+resource_found:
+
+ DBG_RES("%s() res_idx %d res_hint: %d\n",
+ __FUNCTION__, res_idx, ioc->res_hint);
+
+#ifdef CCIO_SEARCH_TIME
+ {
+ unsigned long cr_end = mfctl(16);
+ unsigned long tmp = cr_end - cr_start;
+ /* check for roll over */
+ cr_start = (cr_end < cr_start) ? -(tmp) : (tmp);
+ }
+ ioc->avg_search[ioc->avg_idx++] = cr_start;
+ ioc->avg_idx &= CCIO_SEARCH_SAMPLE - 1;
+#endif
+#ifdef CCIO_MAP_STATS
+ ioc->used_pages += pages_needed;
+#endif
+ /*
+ ** return the bit address.
+ */
+ return res_idx << 3;
+}
+
+#define CCIO_FREE_MAPPINGS(ioc, res_idx, mask, size) \
+ u##size *res_ptr = (u##size *)&((ioc)->res_map[res_idx]); \
+ BUG_ON((*res_ptr & mask) != mask); \
+ *res_ptr &= ~(mask);
+
+/**
+ * ccio_free_range - Free pages from the ioc's resource map.
+ * @ioc: The I/O Controller.
+ * @iova: The I/O Virtual Address.
+ * @pages_mapped: The requested number of pages to be freed from the
+ * I/O Pdir.
+ *
+ * This function frees the resouces allocated for the iova.
+ */
+static void
+ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped)
+{
+ unsigned long iovp = CCIO_IOVP(iova);
+ unsigned int res_idx = PDIR_INDEX(iovp) >> 3;
+
+ BUG_ON(pages_mapped == 0);
+ BUG_ON((pages_mapped * IOVP_SIZE) > DMA_CHUNK_SIZE);
+ BUG_ON(pages_mapped > BITS_PER_LONG);
+
+ DBG_RES("%s(): res_idx: %d pages_mapped %d\n",
+ __FUNCTION__, res_idx, pages_mapped);
+
+#ifdef CCIO_MAP_STATS
+ ioc->used_pages -= pages_mapped;
+#endif
+
+ if(pages_mapped <= 8) {
+#if 0
+ /* see matching comments in alloc_range */
+ unsigned long mask = ~(~0UL >> pages_mapped);
+ CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 8);
+#else
+ CCIO_FREE_MAPPINGS(ioc, res_idx, 0xff, 8);
+#endif
+ } else if(pages_mapped <= 16) {
+ CCIO_FREE_MAPPINGS(ioc, res_idx, 0xffff, 16);
+ } else if(pages_mapped <= 32) {
+ CCIO_FREE_MAPPINGS(ioc, res_idx, ~(unsigned int)0, 32);
+#ifdef __LP64__
+ } else if(pages_mapped <= 64) {
+ CCIO_FREE_MAPPINGS(ioc, res_idx, ~0UL, 64);
+#endif
+ } else {
+ panic("%s:%s() Too many pages to unmap.\n", __FILE__,
+ __FUNCTION__);
+ }
+}
+
+/****************************************************************
+**
+** CCIO dma_ops support routines
+**
+*****************************************************************/
+
+typedef unsigned long space_t;
+#define KERNEL_SPACE 0
+
+/*
+** DMA "Page Type" and Hints
+** o if SAFE_DMA isn't set, mapping is for FAST_DMA. SAFE_DMA should be
+** set for subcacheline DMA transfers since we don't want to damage the
+** other part of a cacheline.
+** o SAFE_DMA must be set for "memory" allocated via pci_alloc_consistent().
+** This bit tells U2 to do R/M/W for partial cachelines. "Streaming"
+** data can avoid this if the mapping covers full cache lines.
+** o STOP_MOST is needed for atomicity across cachelines.
+** Apperently only "some EISA devices" need this.
+** Using CONFIG_ISA is hack. Only the IOA with EISA under it needs