[parisc-linux-cvs] Re: 2.6.9-rc2-pa9 Astro/Elroy LMMIO/ELMMIO range
reporting
Grant Grundler
grundler at parisc-linux.org
Sun Sep 26 18:31:20 MDT 2004
On Sun, Sep 26, 2004 at 05:56:46PM -0600, Grant Grundler wrote:
> Log message:
> 2.6.9-rc2-pa9 - fix Astro/Elroy LMMIO space reporting in /proc/iomem.
> Output in /proc/iomem include PCI bus number and "Extra LMMIO" range.
A much too long comment in lba_pci explains the key part of the changes.
Look for it below in the diff. I should probably it to a document
someplace but aren't quite sure where.
In a nut shell, MMIO ranges below 4GB (LMMIO) were not being reported
correctly. And "Extra" LMMIO ranges were not reported at all.
My c3k now correctly reports:
grundler at gggc3k:~$ cat /proc/iomem
00000000-3fffffff : System RAM
00000000-000009ff : PDC data (Page Zero)
00100000-00398fff : Kernel code
00399000-00507c07 : Kernel data
f05d0000-f05d0000 : lcd_data
f05d0008-f05d0008 : lcd_cmd
f4000000-f47fffff : PCI00 LMMIO
f4000000-f4001fff : sym53c8xx
f4002000-f4003fff : sym53c8xx
f4004000-f40043ff : sym53c8xx
f4005000-f40053ff : sym53c8xx
f4007000-f4007fff : ohci_hcd
f4008000-f40083ff : tulip
f4800000-f4ffffff : PCI01 LMMIO
f6000000-f67fffff : PCI02 LMMIO
f7000000-f77fffff : PCI03 LMMIO
f9000000-f9ffffff : PCI02 ELMMIO
fa000000-fbffffff : PCI03 ELMMIO
fa100000-fa4fffff : stifb mmio
fb000000-fb1fffff : stifb fb
fed00000-fed00fff : SBA
fed30000-fed30fff : lba
fed32000-fed32fff : lba
fed38000-fed38fff : lba
fed3c000-fed3cfff : lba
fef00000-feffffff : Astro Intr Ack
fff80000-fffaffff : Central Bus
fffa0000-fffa0fff : CPU
fffb0000-fffdffff : Local Broadcast
fffe0000-ffffffff : Global Broadcast
grundler at gggc3k:~$
This nicely matches the lspci output:
grundler at gggc3k:~$ lspci -vt
-+-[03]---02.0 Hewlett-Packard Company A4977A Visualize EG
+-[02]---03.0 3Dfx Interactive, Inc. Voodoo 2
+-[01]---05.0 3Com Corporation 3c905 100BaseTX [Boomerang]
\-[00]-+-0c.0 Digital Equipment Corporation DECchip 21142/43
+-0d.0 Analog Devices AD1889 sound chip
+-0e.0 National Semiconductor Corporation 87415/87560 IDE
+-0e.1 National Semiconductor Corporation 87560 Legacy I/O
+-0e.2 National Semiconductor Corporation USB Controller
+-0f.0 LSI Logic / Symbios Logic 53C896/897
\-0f.1 LSI Logic / Symbios Logic 53C896/897
(I don't have the Voodoo drivers loaded or I would expect
more stuff to show up as claimed resources under PCI02)
I have NOT tested 64-bit kernels on either a500 or c3k.
I will test 64-bit kernel on a500. If someone has spare cycles
and likes to try 64-bit on c3k (or something similar),
that would be great.
I also note that pa8800 does NOT boot because e1000 driver is broken.
System HPMCs during e1000 initialization. I'll work on this
after I commit another suckyio related patch.
Lastly, I left several large chunks of "dead" code in lba_pci.c.
I am pretty sure *some* of this code will be useful if/when anyone tries
to get MSI support working. I'm pretty sure (at least one c3k) the
distributed range registers (LMMIO BASE/MASK) are programmed wrong
and they *might* need to be reprogrammed.
They work for current use, but I'm worried about transactions mastered
on the PCI bus targeting 0xFxxx address will be routed wrong depending
on which rope originates the transaction and the target.
grant
Index: Makefile
===================================================================
RCS file: /var/cvs/linux-2.6/Makefile,v
retrieving revision 1.254
diff -u -p -r1.254 Makefile
--- Makefile 24 Sep 2004 15:57:40 -0000 1.254
+++ Makefile 26 Sep 2004 23:26:03 -0000
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 9
-EXTRAVERSION = -rc2-pa8
+EXTRAVERSION = -rc2-pa9
NAME=Zonked Quokka
# *DOCUMENTATION*
Index: drivers/parisc/lba_pci.c
===================================================================
RCS file: /var/cvs/linux-2.6/drivers/parisc/lba_pci.c,v
retrieving revision 1.12
diff -u -p -r1.12 lba_pci.c
--- drivers/parisc/lba_pci.c 4 Jun 2004 19:36:53 -0000 1.12
+++ drivers/parisc/lba_pci.c 26 Sep 2004 23:26:05 -0000
@@ -163,6 +163,7 @@
#define LBA_EIOS_BASE 0x0260 /* Extra I/O port space */
#define LBA_EIOS_MASK 0x0268
+#define LBA_GLOBAL_MASK 0x0270 /* Mercury only: Global Address Mask */
#define LBA_DMA_CTL 0x0278 /* firmware sets this */
#define LBA_IBASE 0x0300 /* SBA DMA support */
@@ -182,13 +183,21 @@
#define LBA_IOSAPIC_BASE 0x800 /* Offset of IRQ logic */
-/* non-postable I/O port space, densely packed */
#ifdef CONFIG_PARISC64
-#define LBA_ASTRO_PORT_BASE (0xfffffffffee00000UL)
+ /*
+ ** Sign extend all BAR values on "legacy" platforms.
+ ** "Sprockets" PDC (Forte/Allegro) initializes everything
+ ** for "legacy" 32-bit OS (HPUX 10.20).
+ ** Upper 32-bits of 64-bit BAR will be zero too.
+ */
+#define LBA_F_EXTEND (0xffffffff00000000UL)
#else
-#define LBA_ASTRO_PORT_BASE (0xfee00000UL)
+#define LBA_F_EXTEND (0UL)
#endif
+/* non-postable I/O port space, densely packed */
+#define LBA_PORT_BASE (LBA_F_EXTEND | 0xfee00000UL)
+
#define ELROY_HVERS 0x782
#define MERCURY_HVERS 0x783
#define QUICKSILVER_HVERS 0x784
@@ -283,8 +292,8 @@ static u32 lba_t32;
** Extract LBA (Rope) number from HPA
** REVISIT: 16 ropes for Stretch/Ike?
*/
-#define ROPES_PER_SBA 8
-#define LBA_NUM(x) ((((unsigned long) x) >> 13) & (ROPES_PER_SBA-1))
+#define ROPES_PER_IOC 8
+#define LBA_NUM(x) ((((unsigned long) x) >> 13) & (ROPES_PER_IOC-1))
static void
@@ -768,7 +777,7 @@ lba_fixup_bus(struct pci_bus *bus)
pci_read_bridge_bases(bus);
} else {
/* Host-PCI Bridge */
- int err;
+ int err, i;
DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
ldev->hba.io_space.name,
@@ -781,22 +790,31 @@ lba_fixup_bus(struct pci_bus *bus)
err = request_resource(&ioport_resource, &(ldev->hba.io_space));
if (err < 0) {
- BUG();
lba_dump_res(&ioport_resource, 2);
+ BUG();
+ }
+
+ err = request_resource(&iomem_resource, &(ldev->hba.elmmio_space));
+ if (err < 0) {
+ lba_dump_res(&iomem_resource, 2);
+ /* BUG(); */
}
err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
if (err < 0) {
- BUG();
+ /* FIXME overlaps with elmmio will fail here.
+ * Need to prune (or disable) the distributed range
+ */
lba_dump_res(&iomem_resource, 2);
}
#ifdef CONFIG_PARISC64
+ /* GMMIO is distributed range. Every LBA/Rope gets part it. */
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);
+ BUG();
}
bus->resource[2] = &(ldev->hba.gmmio_space);
}
@@ -805,6 +823,12 @@ lba_fixup_bus(struct pci_bus *bus)
/* advertize Host bridge resources to PCI bus */
bus->resource[0] = &(ldev->hba.io_space);
bus->resource[1] = &(ldev->hba.lmmio_space);
+ i=2;
+ if (ldev->hba.elmmio_space.start)
+ bus->resource[i++] = &(ldev->hba.elmmio_space);
+ if (ldev->hba.gmmio_space.start)
+ bus->resource[i++] = &(ldev->hba.gmmio_space);
+
}
list_for_each(ln, &bus->devices) {
@@ -918,7 +942,7 @@ struct pci_bios_ops lba_bios_ops = {
static u##size lba_astro_in##size (struct pci_hba_data *d, u16 addr) \
{ \
u##size t; \
- t = READ_REG##size(LBA_ASTRO_PORT_BASE + addr); \
+ t = READ_REG##size(LBA_PORT_BASE + addr); \
DBG_PORT(" 0x%x\n", t); \
return (t); \
}
@@ -960,7 +984,7 @@ static void lba_astro_out##size (struct
{ \
ASSERT(d != NULL); \
DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \
- WRITE_REG##size(val, LBA_ASTRO_PORT_BASE + addr); \
+ WRITE_REG##size(val, LBA_PORT_BASE + addr); \
if (LBA_DEV(d)->hw_rev < 3) \
lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \
}
@@ -1001,7 +1025,6 @@ static struct pci_port_ops lba_astro_por
static u##size lba_pat_in##size (struct pci_hba_data *l, u16 addr) \
{ \
u##size t; \
- ASSERT(bus != NULL); \
DBG_PORT("%s(0x%p, 0x%x) ->", __FUNCTION__, l, addr); \
t = READ_REG##size(PIOP_TO_GMMIO(LBA_DEV(l), addr)); \
DBG_PORT(" 0x%x\n", t); \
@@ -1018,7 +1041,6 @@ LBA_PORT_IN(32, 0)
static void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \
{ \
void *where = (void *) PIOP_TO_GMMIO(LBA_DEV(l), addr); \
- ASSERT(bus != NULL); \
DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \
WRITE_REG##size(val, where); \
/* flush the I/O down to the elroy at least */ \
@@ -1159,20 +1181,15 @@ static void
lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
{
struct resource *r;
- unsigned long rsize;
- int lba_num;
-
-#ifdef CONFIG_PARISC64
- /*
- ** Sign extend all BAR values on "legacy" platforms.
- ** "Sprockets" PDC (Forte/Allegro) initializes everything
- ** for "legacy" 32-bit OS (HPUX 10.20).
- ** Upper 32-bits of 64-bit BAR will be zero too.
- */
- lba_dev->hba.lmmio_space_offset = 0xffffffff00000000UL;
+#if 1
+ extern void sba_distributed_lmmio(struct parisc_device *, struct resource *);
+ extern void sba_directed_lmmio(struct parisc_device *, struct resource *);
#else
- lba_dev->hba.lmmio_space_offset = 0UL;
+ long mmio_mask;
#endif
+ int lba_num;
+
+ lba_dev->hba.lmmio_space_offset = LBA_F_EXTEND;
/*
** With "legacy" firmware, the lowest byte of FW_SCRATCH
@@ -1187,27 +1204,112 @@ lba_legacy_resources(struct parisc_devic
r->start = lba_num & 0xff;
r->end = (lba_num>>8) & 0xff;
- /* Set up local PCI Bus resources - we don't really need
- ** them for Legacy boxes but it's nice to see in /proc.
+#if 0
+ if (IS_MERCURY(pa_dev)) {
+ /* Global Address Mask describes relevant addr/mask bits */
+ mmio_mask = (long) READ_REG32(pa_dev->hpa + LBA_GLOBAL_MASK);
+ mmio_mask |= LBA_F_EXTEND;
+ } else
+ mmio_mask = ~1UL; /* clear enable bit */
+#endif
+
+ /* Set up local PCI Bus resources - we don't need them for
+ ** Legacy boxes but it's nice to see in /proc/iomem.
*/
r = &(lba_dev->hba.lmmio_space);
- r->name = "LBA PCI LMMIO";
- r->flags = IORESOURCE_MEM;
- /* Ignore "Range Enable" bit in the BASE register */
- r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev),
- ((long) READ_REG32(pa_dev->hpa + LBA_LMMIO_BASE)) & ~1UL);
- rsize = ~READ_REG32(pa_dev->hpa + LBA_LMMIO_MASK) + 1;
-
+ sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO",
+ (int) lba_dev->hba.bus_num.start);
+ r->name = &lba_dev->hba.lmmio_name[0];
+
+#if 1
+ /* We want the CPU -> IO routing of addresses.
+ * The SBA BASE/MASK registers control CPU -> IO routing.
+ * Ask SBA what is routed to this rope/LBA.
+ */
+ sba_distributed_lmmio(pa_dev, r);
+#else
/*
- ** Each rope only gets part of the distributed range.
- ** Adjust "window" for this rope
- */
- rsize /= ROPES_PER_SBA;
- r->start += rsize * LBA_NUM(pa_dev->hpa);
- r->end = r->start + rsize - 1 ;
+ * The LBA BASE/MASK registers control IO -> System routing.
+ *
+ * The following code works but doesn't get us what we want.
+ * Well, only because firmware (v5.0) on C3000 doesn't program
+ * the LBA BASE/MASE registers to be the exact inverse of
+ * the corresponding SBA registers. Other Astro/Pluto
+ * based platform firmware may do it right.
+ *
+ * Should someone want to mess with MSI, they may need to
+ * reprogram LBA BASE/MASK registers.
+ *
+ * Using the code below, /proc/iomem shows:
+ * ...
+ * f0000000-f0ffffff : PCI00 LMMIO
+ * f05d0000-f05d0000 : lcd_data
+ * f05d0008-f05d0008 : lcd_cmd
+ * f1000000-f1ffffff : PCI01 LMMIO
+ * f4000000-f4ffffff : PCI02 LMMIO
+ * f4000000-f4001fff : sym53c8xx
+ * f4002000-f4003fff : sym53c8xx
+ * f4004000-f40043ff : sym53c8xx
+ * f4005000-f40053ff : sym53c8xx
+ * f4007000-f4007fff : ohci_hcd
+ * f4008000-f40083ff : tulip
+ * f6000000-f6ffffff : PCI03 LMMIO
+ * f8000000-fbffffff : PCI00 ELMMIO
+ * fa100000-fa4fffff : stifb mmio
+ * fb000000-fb1fffff : stifb fb
+ *
+ * But everything listed under PCI02 actually lives under PCI00.
+ * This is clearly wrong.
+ *
+ * Asking SBA how things are routed tells the correct story:
+ * LMMIO_BASE/MASK/ROUTE f4000001 fc000000 00000000
+ * DIR0_BASE/MASK/ROUTE fa000001 fe000000 00000006
+ * DIR1_BASE/MASK/ROUTE f9000001 ff000000 00000004
+ * DIR2_BASE/MASK/ROUTE f0000000 fc000000 00000000
+ * DIR3_BASE/MASK/ROUTE f0000000 fc000000 00000000
+ *
+ * Which looks like this in /proc/iomem:
+ * f4000000-f47fffff : PCI00 LMMIO
+ * f4000000-f4001fff : sym53c8xx
+ * ...[deteled core devices - same as above]...
+ * f4008000-f40083ff : tulip
+ * f4800000-f4ffffff : PCI01 LMMIO
+ * f6000000-f67fffff : PCI02 LMMIO
+ * f7000000-f77fffff : PCI03 LMMIO
+ * f9000000-f9ffffff : PCI02 ELMMIO
+ * fa000000-fbffffff : PCI03 ELMMIO
+ * fa100000-fa4fffff : stifb mmio
+ * fb000000-fb1fffff : stifb fb
+ *
+ * ie all Built-in core are under now correctly under PCI00.
+ * The "PCI02 ELMMIO" directed range is for:
+ * +-[02]---03.0 3Dfx Interactive, Inc. Voodoo 2
+ *
+ * All is well now.
+ */
+ r->start = (long) READ_REG32(pa_dev->hpa + LBA_LMMIO_BASE);
+ if (r->start & 1) {
+ unsigned long rsize;
+
+ r->flags = IORESOURCE_MEM;
+ /* mmio_mask also clears Enable bit */
+ r->start &= mmio_mask;
+ r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), r->start);
+ rsize = ~ READ_REG32(pa_dev->hpa + LBA_LMMIO_MASK);
+
+ /*
+ ** Each rope only gets part of the distributed range.
+ ** Adjust "window" for this rope.
+ */
+ rsize /= ROPES_PER_IOC;
+ r->start += (rsize + 1) * LBA_NUM(pa_dev->hpa);
+ r->end = r->start + rsize;
+ } else {
+ r->end = r->start = 0; /* Not enabled. */
+ }
+#endif
/*
- ** XXX FIXME - ignore LBA_ELMMIO_BASE for now
** "Directed" ranges are used when the "distributed range" isn't
** sufficient for all devices below a given LBA. Typically devices
** like graphics cards or X25 may need a directed range when the
@@ -1216,35 +1318,38 @@ lba_legacy_resources(struct parisc_devic
**
** The main reason for ignoring it now frigging complications.
** Directed ranges may overlap (and have precedence) over
- ** distributed ranges. Ie a distributed range assigned to a unused
+ ** distributed ranges. Or a distributed range assigned to a unused
** rope may be used by a directed range on a different rope.
** Support for graphics devices may require fixing this
** since they may be assigned a directed range which overlaps
** an existing (but unused portion of) distributed range.
*/
r = &(lba_dev->hba.elmmio_space);
- r->name = "extra LBA PCI LMMIO";
- r->flags = IORESOURCE_MEM;
+ sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO",
+ (int) lba_dev->hba.bus_num.start);
+ r->name = &lba_dev->hba.elmmio_name[0];
+
+#if 1
+ /* See comment which precedes call to sba_directed_lmmio() */
+ sba_directed_lmmio(pa_dev, r);
+#else
r->start = READ_REG32(pa_dev->hpa + LBA_ELMMIO_BASE);
- r->end = 0;
- /* check Range Enable bit */
if (r->start & 1) {
- /* First baby step to getting Direct Ranges listed in /proc.
- ** AFAIK, only Sprockets PDC will setup a directed Range.
- */
-
- r->start &= ~1;
- r->end = r->start;
- r->end += ~READ_REG32(pa_dev->hpa + LBA_ELMMIO_MASK);
- printk(KERN_DEBUG "WARNING: Ignoring enabled ELMMIO BASE 0x%0lx SIZE 0x%lx\n",
- r->start,
- r->end + 1);
-
+ unsigned long rsize;
+ r->flags = IORESOURCE_MEM;
+ /* mmio_mask also clears Enable bit */
+ r->start &= mmio_mask;
+ r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), r->start);
+ rsize = READ_REG32(pa_dev->hpa + LBA_ELMMIO_MASK);
+ r->end = r->start + ~rsize;
}
+#endif
r = &(lba_dev->hba.io_space);
- r->name = "LBA PCI I/O Ports";
+ sprintf(lba_dev->hba.io_name, "PCI%02x Ports",
+ (int) lba_dev->hba.bus_num.start);
+ r->name = &lba_dev->hba.io_name[0];
r->flags = IORESOURCE_IO;
r->start = READ_REG32(pa_dev->hpa + LBA_IOS_BASE) & ~1L;
r->end = r->start + (READ_REG32(pa_dev->hpa + LBA_IOS_MASK) ^ (HBA_PORT_SPACE_SIZE - 1));
@@ -1481,6 +1586,7 @@ lba_driver_probe(struct parisc_device *d
is_pdc_pat() ? &pat_cfg_ops : &lba_cfg_ops,
NULL);
+ /* This is in lieu of calling pci_assign_unassigned_resources() */
if (is_pdc_pat()) {
/* assign resources to un-initialized devices */
DBG_PAT("LBA pci_bus_assign_resources()\n");
@@ -1493,6 +1599,8 @@ lba_driver_probe(struct parisc_device *d
lba_dump_res(&lba_dev->hba.lmmio_space, 2);
#endif
}
+ pci_enable_bridges(lba_bus);
+
/*
** Once PCI register ops has walked the bus, access to config
Index: drivers/parisc/sba_iommu.c
===================================================================
RCS file: /var/cvs/linux-2.6/drivers/parisc/sba_iommu.c,v
retrieving revision 1.13
diff -u -p -r1.13 sba_iommu.c
--- drivers/parisc/sba_iommu.c 5 Sep 2004 01:00:47 -0000 1.13
+++ drivers/parisc/sba_iommu.c 26 Sep 2004 23:26:05 -0000
@@ -112,6 +112,11 @@ extern struct proc_dir_entry * proc_mcki
#define SBA_INLINE __inline__
+#ifdef CONFIG_PARISC64
+#define SBA_F_EXTEND 0xffffffff00000000UL
+#else
+#define SBA_F_EXTEND 0UL
+#endif
/*
** The number of pdir entries to "free" before issueing
@@ -168,11 +173,21 @@ extern struct proc_dir_entry * proc_mcki
#define MAX_IOC 2 /* per Ike. Pluto/Astro only have 1. */
+#define ROPES_PER_IOC 8 /* per Ike half or Pluto/Astro */
+
/*
** Offsets into MBIB (Function 0 on Ike and hopefully Astro)
** Firmware programs this stuff. Don't touch it.
*/
+#define LMMIO_DIRECT0_BASE 0x300
+#define LMMIO_DIRECT0_MASK 0x308
+#define LMMIO_DIRECT0_ROUTE 0x310
+
+#define LMMIO_DIST_BASE 0x360
+#define LMMIO_DIST_MASK 0x368
+#define LMMIO_DIST_ROUTE 0x370
+
#define IOS_DIST_BASE 0x390
#define IOS_DIST_MASK 0x398
#define IOS_DIST_ROUTE 0x3A0
@@ -290,6 +305,9 @@ struct sba_device {
unsigned int flags; /* state/functionality enabled */
unsigned int hw_rev; /* HW revision of chip */
+ struct resource chip_resv; /* MMIO reserved for chip */
+ struct resource iommu_resv; /* MMIO reserved for iommu */
+
unsigned int num_ioc; /* number of on-board IOC's */
struct ioc ioc[MAX_IOC];
};
@@ -1697,19 +1715,51 @@ sba_hw_init(struct sba_device *sba_dev)
} /* if !PLUTO */
if (IS_ASTRO(sba_dev->iodc)) {
+ int err;
/* PAT_PDC (L-class) also reports the same goofy base */
sba_dev->ioc[0].ioc_hpa = ASTRO_IOC_OFFSET;
num_ioc = 1;
+
+ sba_dev->chip_resv.name = "Astro Intr Ack";
+ sba_dev->chip_resv.start = SBA_F_EXTEND | 0xfef00000UL;
+ sba_dev->chip_resv.end = SBA_F_EXTEND | (0xff000000UL - 1) ;
+ err = request_resource(&iomem_resource, &(sba_dev->chip_resv));
+ if (err < 0) {
+ BUG();
+ }
+
} else if (IS_PLUTO(sba_dev->iodc)) {
+ int err;
+
/* We use a negative value for IOC HPA so it gets
* corrected when we add it with IKE's IOC offset.
* Doesnt look clean, but fewer code.
*/
sba_dev->ioc[0].ioc_hpa = -PLUTO_IOC_OFFSET;
num_ioc = 1;
+
+ sba_dev->chip_resv.name = "Pluto Intr/PIOP/VGA";
+ sba_dev->chip_resv.start = SBA_F_EXTEND | 0xfee00000UL;
+ sba_dev->chip_resv.end = SBA_F_EXTEND | (0xff200000UL - 1);
+ err = request_resource(&iomem_resource, &(sba_dev->chip_resv));
+ if (err < 0) {
+ BUG();
+ }
+
+ sba_dev->iommu_resv.name = "IOVA Space";
+ sba_dev->iommu_resv.start = 0x40000000UL;
+ sba_dev->iommu_resv.end = 0x50000000UL - 1;
+ err = request_resource(&iomem_resource, &(sba_dev->iommu_resv));
+ if (err < 0) {
+ BUG();
+ }
+
} else {
+ /* IS_IKE (ie N-class, L3000, L1500) */
sba_dev->ioc[0].ioc_hpa = sba_dev->ioc[1].ioc_hpa = 0;
num_ioc = 2;
+
+ /* TODO - LOOKUP Ike/Stretch chipset mem map */
}
sba_dev->num_ioc = num_ioc;
@@ -1844,8 +1894,9 @@ static int sba_proc_info(char *buf, char
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 */
+ unsigned long i;
#ifdef SBA_COLLECT_STATS
- unsigned long i = 0, avg = 0, min, max;
+ unsigned long avg = 0, min, max;
#endif
sprintf(buf, "%s rev %d.%d\n",
@@ -1861,6 +1912,21 @@ static int sba_proc_info(char *buf, char
sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n",
buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */
+ sprintf(buf, "%sLMMIO_BASE/MASK/ROUTE %08x %08x %08x\n",
+ buf,
+ READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_BASE),
+ READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_MASK),
+ READ_REG32(sba_dev->sba_hpa + LMMIO_DIST_ROUTE)
+ );
+
+ for (i=0; i<4; i++)
+ sprintf(buf, "%sDIR%ld_BASE/MASK/ROUTE %08x %08x %08x\n",
+ buf, i,
+ READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_BASE + i*0x18),
+ READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_MASK + i*0x18),
+ READ_REG32(sba_dev->sba_hpa + LMMIO_DIRECT0_ROUTE + i*0x18)
+ );
+
#ifdef SBA_COLLECT_STATS
sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf,
total_pages - ioc->used_pages, ioc->used_pages,
@@ -2063,8 +2129,8 @@ void __init sba_init(void)
* sba_get_iommu - Assign the iommu pointer for the pci bus controller.
* @dev: The parisc device.
*
- * This function searches through the registerd IOMMU's and returns the
- * appropriate IOMMU data for the given parisc PCI controller.
+ * Returns the appropriate IOMMU data for the given parisc PCI controller.
+ * This is cached and used later for PCI DMA Mapping.
*/
void * sba_get_iommu(struct parisc_device *pci_hba)
{
@@ -2076,4 +2142,80 @@ void * sba_get_iommu(struct parisc_devic
BUG();
return &(sba->ioc[iocnum]);
+}
+
+
+/**
+ * sba_directed_lmmio - return first directed LMMIO range routed to rope
+ * @pa_dev: The parisc device.
+ * @r: resource PCI host controller wants start/end fields assigned.
+ *
+ * For the given parisc PCI controller, determine if any direct ranges
+ * are routed down the corresponding rope.
+ */
+void sba_directed_lmmio(struct parisc_device *pci_hba, struct resource *r)
+{
+ struct sba_device *sba = (struct sba_device *) pci_hba->parent->sysdata;
+ char t = pci_hba->parent->id.hw_type;
+ int i;
+ int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */
+
+ if ((t!=HPHW_IOA) && (t!=HPHW_BCPORT))
+ BUG();
+
+ r->start = r->end = 0;
+
+ /* Astro has 4 directed ranges. Not sure about Ike/Pluto/et al */
+ for (i=0; i<4; i++) {
+ int base, size;
+ unsigned long reg = sba->sba_hpa + i*0x18;
+
+ base = READ_REG32(reg + LMMIO_DIRECT0_BASE);
+ if ((base & 1) == 0)
+ continue; /* not enabled */
+
+ size = READ_REG32(reg + LMMIO_DIRECT0_ROUTE);
+
+ if ((size & (ROPES_PER_IOC-1)) != rope)
+ continue; /* directed down different rope */
+
+ r->start = (base & ~1UL) | SBA_F_EXTEND;
+ size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK);
+ r->end = r->start + size;
+ }
+}
+
+
+/**
+ * sba_distributed_lmmio - return portion of distributed LMMIO range
+ * @pa_dev: The parisc device.
+ * @r: resource PCI host controller wants start/end fields assigned.
+ *
+ * For the given parisc PCI controller, return portion of distributed LMMIO
+ * range. The distributed LMMIO is always present and it's just a question
+ * of the base address and size of the range.
+ */
+void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r )
+{
+ struct sba_device *sba = (struct sba_device *) pci_hba->parent->sysdata;
+ char t = pci_hba->parent->id.hw_type;
+ int base, size;
+ int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */
+
+ if ((t!=HPHW_IOA) && (t!=HPHW_BCPORT))
+ BUG();
+
+ r->start = r->end = 0;
+
+ base = READ_REG32(sba->sba_hpa + LMMIO_DIST_BASE);
+ if ((base & 1) == 0) {
+ BUG(); /* Gah! Distr Range wasn't enabled! */
+ return;
+ }
+
+ r->start = (base & ~1UL) | SBA_F_EXTEND;
+
+ size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC;
+ r->start += rope * (size + 1); /* adjust base for this rope */
+ r->end = r->start + size;
}
Index: include/asm-parisc/pci.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/pci.h,v
retrieving revision 1.9
diff -u -p -r1.9 pci.h
--- include/asm-parisc/pci.h 30 May 2004 18:57:24 -0000 1.9
+++ include/asm-parisc/pci.h 26 Sep 2004 23:26:06 -0000
@@ -35,6 +35,7 @@ struct pci_hba_data {
struct resource lmmio_space; /* bus addresses < 4Gb */
struct resource elmmio_space; /* additional bus addresses < 4Gb */
struct resource gmmio_space; /* bus addresses > 4Gb */
+
/* NOTE: Dino code assumes it can use *all* of the lmmio_space,
* elmmio_space and gmmio_space as a contiguous array of
* resources. This #define represents the array size */
@@ -43,6 +44,12 @@ struct pci_hba_data {
unsigned long lmmio_space_offset; /* CPU view - PCI view */
void * iommu; /* IOMMU this device is under */
/* REVISIT - spinlock to protect resources? */
+
+ #define HBA_NAME_SIZE 16
+ char io_name[HBA_NAME_SIZE];
+ char lmmio_name[HBA_NAME_SIZE];
+ char elmmio_name[HBA_NAME_SIZE];
+ char gmmio_name[HBA_NAME_SIZE];
};
#define HBA_DATA(d) ((struct pci_hba_data *) (d))
More information about the parisc-linux-cvs
mailing list