[parisc-linux-cvs] [PATCH] PCI LMMIO mapping
Bjorn Helgaas
bjorn_helgaas@hp.com
Wed, 12 Sep 2001 17:15:08 -0600
This is an aged, somewhat better tested, and somewhat cleaned up version
of the patch I posted earlier (5/21/01). It is most of what is required
to run on Superdome and should help on N-class as well.
I'd like to commit these changes soon, and I'd appreciate any comments.
- clean up CPU physical <-> PCI address mapping
- use current cell for iosapic_load_irt (allows non-zero cell number)
- rename mem_space to lmmio_space
- handle initrd loaded above mem= limit
- new map_pages() to unify page table setup
- new hardware HVERSIONs (Caribe W2, Caribe DNA, Allegro W+, Keystone &
Caribe memory)
- fix link errors when CONFIG_VT not defined
- correct a few typos (REDICULOUSLY_VERBOSE, Priviledged)
The first one is most important. For boxes with PAT firmware, we
previously did not ask firmware what the IO_VIEW range for a module
was, we could support only trivial mappings between the CPU physical
address range and the PCI address range. Larger machines like N-class
and Superdome use non-trivial mappings, and this limitation is a big
reason why we can't run on them yet.
The mapping is always linear (on 32-bit boxes, 64-bit boxes with
legacy firmware, and 64-bit boxes with PAT firmware), so I just added
an offset between the CPU view and the PCI view. For PAT firmware,
the offset is gotten from firmware; for others, it is hard-coded as it
was before. The new PCI_BUS_ADDR() and PCI_HOST_ADDR() macros apply
the offset to convert from CPU to PCI addresses and PCI to CPU
addresses, respectively.
Tested platforms:
Superdome (requires additional patches not included here)
A500
C3000 32-bit kernel
C3000 64-bit kernel
C3600 64-bit kernel (also requires add'l patches)
Index: arch/parisc/kernel/hardware.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/hardware.c,v
retrieving revision 1.25
diff -u -p -r1.25 hardware.c
--- hardware.c 2001/09/05 12:46:45 1.25
+++ hardware.c 2001/09/12 22:35:43
@@ -206,7 +206,7 @@ static struct hp_hardware hp_hardware_li
{HPHW_NPROC,0x5B8,0x4,0x91,"SPP2250 240 MHz"},
{HPHW_NPROC,0x5B9,0x4,0x81,"UL 1w U+/240 (350/550)"},
{HPHW_NPROC,0x5BA,0x4,0x91,"UL 2w U+/240 (350/550)"},
- {HPHW_NPROC,0x5BB,0x4,0x81,"AllegroHigh W "},
+ {HPHW_NPROC,0x5BB,0x4,0x81,"AllegroHigh W"},
{HPHW_NPROC,0x5BC,0x4,0x91,"AllegroLow W"},
{HPHW_NPROC,0x5BD,0x4,0x91,"Forte W 2-way"},
{HPHW_NPROC,0x5BE,0x4,0x91,"Prelude W"},
@@ -240,6 +240,7 @@ static struct hp_hardware hp_hardware_li
{HPHW_NPROC,0x5DA,0x4,0x91,"Marcato W+ DC-"},
{HPHW_NPROC,0x5DB,0x4,0x91,"Marcato W+"},
{HPHW_NPROC,0x5DE,0x4,0x81,"Piccolo W+"},
+ {HPHW_NPROC,0x5E7,0x4,0x91,"Caribe W2 800"},
{HPHW_NPROC,0x5FF,0x4,0x91,"Hitachi W"},
{HPHW_NPROC,0x600,0x4,0x81,"Gecko (712/60)"},
{HPHW_NPROC,0x601,0x4,0x81,"Gecko 80 (712/80)"},
@@ -574,6 +575,7 @@ static struct hp_hardware hp_hardware_li
{HPHW_CONSOLE, 0x01A, 0x0001F, 0x00, "Jason/Anole 64 Null Console"},
{HPHW_CONSOLE, 0x01B, 0x0001F, 0x00, "Jason/Anole 100 Null Console"},
{HPHW_FABRIC, 0x004, 0x000AA, 0x80, "Halfdome DNA Central Agent"},
+ {HPHW_FABRIC, 0x007, 0x000AA, 0x80, "Caribe DNA Central Agent"},
{HPHW_FABRIC, 0x004, 0x000AB, 0x00, "Halfdome TOGO Fabric Crossbar"},
{HPHW_FABRIC, 0x004, 0x000AC, 0x00, "Halfdome Sakura Fabric Router"},
{HPHW_FIO, 0x025, 0x0002E, 0x80, "Armyknife Optional X.25"},
@@ -1313,6 +1315,7 @@ static struct hp_hardware hp_hardware_li
{HPHW_MEMORY, 0x08B, 0x00009, 0x00, "Staccato L2 180 Memory"},
{HPHW_MEMORY, 0x090, 0x00009, 0x00, "Prelude SMC Memory"},
{HPHW_MEMORY, 0x091, 0x00009, 0x00, "Lego 360 Memory"},
+ {HPHW_MEMORY, 0x09C, 0x00009, 0x00, "Allegro W+ Memory"},
{HPHW_MEMORY, 0x7FF, 0x00009, 0x00, "NEC Aska memory"},
{HPHW_MEMORY, 0x800, 0x00009, 0x00, "Hitachi Tiny 64"},
{HPHW_MEMORY, 0x801, 0x00009, 0x00, "Hitachi Tiny 80"},
@@ -1324,10 +1327,12 @@ static struct hp_hardware hp_hardware_li
{HPHW_MEMORY, 0x095, 0x00009, 0x00, "Rhapsody 440 Memory"},
{HPHW_MEMORY, 0x096, 0x00009, 0x00, "Rhapsody 360 Memory"},
{HPHW_MEMORY, 0x097, 0x00009, 0x00, "Raven W 360 Memory"},
- {HPHW_MEMORY, 0x098, 0x00009, 0x00, "Halfdome W 440 Memory"},
+ {HPHW_MEMORY, 0x098, 0x00009, 0x00, "Halfdome W+ 552 Memory"},
{HPHW_MEMORY, 0x099, 0x00009, 0x00, "Rhapsody DC- 440 Memory"},
{HPHW_MEMORY, 0x09A, 0x00009, 0x00, "Rhapsody DC- 360 Memory"},
{HPHW_MEMORY, 0x09B, 0x00009, 0x00, "Crescendo Memory"},
+ {HPHW_MEMORY, 0x0A1, 0x00009, 0x00, "Keystone Memory"},
+ {HPHW_MEMORY, 0x0A8, 0x00009, 0x00, "Caribe W2 Memory"},
{HPHW_OTHER, 0x004, 0x00030, 0x00, "Master"},
{HPHW_OTHER, 0x004, 0x00034, 0x00, "Slave"},
{HPHW_OTHER, 0x004, 0x00038, 0x00, "EDU"},
Index: arch/parisc/kernel/inventory.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/inventory.c,v
retrieving revision 1.33
diff -u -p -r1.33 inventory.c
--- inventory.c 2001/08/30 16:48:58 1.33
+++ inventory.c 2001/09/12 22:35:43
@@ -171,6 +171,7 @@ void do_pagezero_memconfig(void)
static int pat_query_module(ulong pcell_loc, ulong mod_index)
{
pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
+ pdc_pat_cell_mod_maddr_block_t io_pdc_cell;
unsigned long bytecnt;
unsigned long temp; /* 64-bit scratch value */
long status; /* PDC return value status */
@@ -187,6 +188,9 @@ static int pat_query_module(ulong pcell_
temp = pa_pdc_cell.cba;
dev = alloc_pa_dev(PAT_GET_CBA(temp)); /* sets dev->hpa */
+ if (!dev) {
+ return PDC_RET_NE_MOD;
+ }
/*
** save parameters in the hp_device
@@ -236,13 +240,20 @@ static int pat_query_module(ulong pcell_
printk(KERN_DEBUG "PAT_ENTITY_LBA: ");
print_ranges:
+ pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,
+ IO_VIEW, &io_pdc_cell);
printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell.mod[1]);
for (i = 0; i < pa_pdc_cell.mod[1]; i++) {
printk(KERN_DEBUG
- " %ld: 0x%016lx 0x%016lx 0x%016lx\n",
+ " PA_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n",
i, pa_pdc_cell.mod[2 + i * 3], /* type */
pa_pdc_cell.mod[3 + i * 3], /* start */
pa_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */
+ printk(KERN_DEBUG
+ " IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n",
+ i, io_pdc_cell.mod[2 + i * 3], /* type */
+ io_pdc_cell.mod[3 + i * 3], /* start */
+ io_pdc_cell.mod[4 + i * 3]); /* finish (ie end) */
}
printk(KERN_DEBUG "\n");
break;
Index: arch/parisc/kernel/ioctl32.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/ioctl32.c,v
retrieving revision 1.6
diff -u -p -r1.6 ioctl32.c
--- ioctl32.c 2001/07/14 21:17:01 1.6
+++ ioctl32.c 2001/09/12 22:35:43
@@ -1395,6 +1395,7 @@ static int loop_status(unsigned int fd,
return err;
}
+#ifdef CONFIG_VT
extern int tty_ioctl(struct inode * inode, struct file * file, unsigned
int cmd, unsigned long arg);
static int vt_check(struct file *file)
@@ -1527,6 +1528,7 @@ static int do_unimap_ioctl(unsigned int
}
return 0;
}
+#endif
#if 0
static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned
long arg)
@@ -3382,11 +3384,13 @@ HANDLE_IOCTL(LOOP_SET_STATUS, loop_statu
HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)
#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
+#ifdef CONFIG_VT
HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl)
HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl)
HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl)
HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl)
HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl)
+#endif
HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl)
HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl)
HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl)
Index: arch/parisc/kernel/iosapic.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/iosapic.c,v
retrieving revision 1.28
diff -u -p -r1.28 iosapic.c
--- iosapic.c 2001/08/14 16:54:52 1.28
+++ iosapic.c 2001/09/12 22:35:44
@@ -338,7 +338,7 @@ iosapic_load_irt(unsigned long cell_num,
if (is_pdc_pat()) {
/* Use pat pdc routine to get interrupt routing table size */
- DBG("calling get_irt_size\n");
+ DBG("calling get_irt_size (cell %ld)\n", cell_num);
status = pdc_pat_get_irt_size(&num_entries, cell_num);
DBG("get_irt_size: %ld\n", status);
@@ -436,6 +436,8 @@ got_irt:
void __init
iosapic_init(void)
{
+ unsigned long cell = 0;
+
/* init global data */
iosapic_lock = SPIN_LOCK_UNLOCKED;
iosapic_list = (struct iosapic_info *) NULL;
@@ -443,10 +445,22 @@ iosapic_init(void)
DBG("iosapic_init()\n");
+#ifdef __LP64__
+ if (is_pdc_pat()) {
+ int status;
+ struct pdc_pat_cell_num cell_info;
+
+ status = pdc_pat_cell_get_number(&cell_info);
+ if (status == PDC_RET_OK) {
+ cell = cell_info.cell_num;
+ }
+ }
+#endif
+
/*
** get IRT for this cell.
*/
- irt_num_entry = iosapic_load_irt(0L, &irt_cell);
+ irt_num_entry = iosapic_load_irt(cell, &irt_cell);
if (0 == irt_num_entry)
irt_cell = NULL; /* old PDC w/o iosapic */
}
Index: arch/parisc/kernel/lba_pci.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/lba_pci.c,v
retrieving revision 1.35
diff -u -p -r1.35 lba_pci.c
--- lba_pci.c 2001/09/03 22:09:46 1.35
+++ lba_pci.c 2001/09/12 22:35:44
@@ -470,7 +470,7 @@ lba_device_present( u8 bus, u8 dfn, stru
static unsigned int
-lba_rd_cfg( struct lba_device *d, u32 tok, u8 reg, u32 size)
+lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size)
{
u32 data = ~0;
int error = 0;
@@ -530,7 +530,7 @@ static int lba_cfg_read##size (struct pc
\
if (LBA_SKIP_PROBE(d) && (!lba_device_present(dev->bus->secondary,
dev->devfn, d))) \
{ \
- DBG_CFG("%s(%s+%2x) -> -1 (b)\n", __FUNCTION__, dev->slot_name, pos,
*data); \
+ DBG_CFG("%s(%s+%2x) -> -1 (b)\n", __FUNCTION__, dev->slot_name, pos); \
/* either don't want to look or know device isn't present. */ \
*data = (u##size) -1; \
return(0); \
@@ -724,23 +724,23 @@ lba_fixup_bus(struct pci_bus *bus)
ldev->hba.io_space.start, ldev->hba.io_space.end,
(int) ldev->hba.io_space.flags);
DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
- ldev->hba.mem_space.name,
- ldev->hba.mem_space.start, ldev->hba.mem_space.end,
- (int) ldev->hba.mem_space.flags);
+ ldev->hba.lmmio_space.name,
+ ldev->hba.lmmio_space.start, ldev->hba.lmmio_space.end,
+ (int) ldev->hba.lmmio_space.flags);
err = request_resource(&ioport_resource, &(ldev->hba.io_space));
if (err < 0) {
BUG();
lba_dump_res(&ioport_resource, 2);
}
- err = request_resource(&iomem_resource, &(ldev->hba.mem_space));
+ 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.mem_space);
+ bus->resource[1] = &(ldev->hba.lmmio_space);
} else {
/* KLUGE ALERT!
** PCI-PCI Bridge resource munging.
@@ -750,7 +750,7 @@ lba_fixup_bus(struct pci_bus *bus)
int i;
u16 cmd;
- for(i=0; i<4; i++) {
+ for (i = 0; i < 4; i++) {
bus->resource[i] =
&bus->self->resource[PCI_BRIDGE_RESOURCES+i];
bus->resource[i]->name = bus->name;
@@ -777,7 +777,7 @@ lba_fixup_bus(struct pci_bus *bus)
** PCI will adjust them later.
*/
bus->resource[0]->end = ldev->hba.io_space.end;
- bus->resource[1]->end = ldev->hba.mem_space.end;
+ bus->resource[1]->end = ldev->hba.lmmio_space.end;
}
/* Turn off downstream PF memory address range by default */
@@ -790,6 +790,8 @@ lba_fixup_bus(struct pci_bus *bus)
int i;
struct pci_dev *dev = pci_dev_b(ln);
+ DBG("lba_fixup_bus() %s\n", dev->name);
+
/* Virtualize Device/Bridge Resources. */
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *res = &dev->resource[i];
@@ -799,14 +801,21 @@ lba_fixup_bus(struct pci_bus *bus)
continue;
if (res->flags & IORESOURCE_IO) {
+ DBG("lba_fixup_bus() I/O Ports [%lx/%lx] -> ",
+ res->start, res->end);
res->start |= lba_portbase;
res->end |= lba_portbase;
-#ifdef __LP64__
+ DBG("[%lx/%lx]\n", res->start, res->end);
} else if (res->flags & IORESOURCE_MEM) {
- /* "Globalize" PCI address */
- res->start |= ldev->lmmio_base;
- res->end |= ldev->lmmio_base;
-#endif
+ /*
+ ** Convert PCI (IO_VIEW) addresses to
+ ** processor (PA_VIEW) addresses
+ */
+ DBG("lba_fixup_bus() MMIO [%lx/%lx] -> ",
+ res->start, res->end);
+ res->start = PCI_HOST_ADDR(HBA_DATA(ldev), res->start);
+ res->end = PCI_HOST_ADDR(HBA_DATA(ldev), res->end);
+ DBG("[%lx/%lx]\n", res->start, res->end);
}
}
@@ -833,7 +842,7 @@ lba_fixup_bus(struct pci_bus *bus)
continue;
/* Adjust INTERRUPT_LINE for this dev */
- iosapic_fixup_irq(LBA_DEV(bus->sysdata)->iosapic_obj, dev);
+ iosapic_fixup_irq(ldev->iosapic_obj, dev);
}
#ifdef FBB_SUPPORT
@@ -890,8 +899,6 @@ struct pci_bios_ops lba_bios_ops = {
static u##size lba_astro_in##size (struct pci_hba_data *d, u16 addr) \
{ \
u##size t; \
- ASSERT(bus != NULL); \
- DBG_PORT("%s(0x%p, 0x%x) ->", __FUNCTION__, bus, addr); \
t = READ_REG##size(LBA_ASTRO_PORT_BASE + addr); \
DBG_PORT(" 0x%x\n", t); \
return (t); \
@@ -1026,10 +1033,8 @@ lba_pat_resources(struct parisc_device *
{
unsigned long bytecnt;
pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; /* PA_VIEW */
-#ifdef DONT_NEED_THIS_FOR_ASTRO
pdc_pat_cell_mod_maddr_block_t io_pdc_cell; /* IO_VIEW */
long io_count;
-#endif
long status; /* PDC return status */
long pa_count;
int i;
@@ -1039,11 +1044,9 @@ lba_pat_resources(struct parisc_device *
PA_VIEW, & pa_pdc_cell);
pa_count = pa_pdc_cell.mod[1];
-#ifdef DONT_NEED_THIS_FOR_ASTRO
status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc,
pa_dev->mod_index,
- IO_VIEW, & io_pdc_cell);
+ IO_VIEW, &io_pdc_cell);
io_count = io_pdc_cell.mod[1];
-#endif
/* We've already done this once for device discovery...*/
if (status != PDC_RET_OK) {
@@ -1062,10 +1065,11 @@ lba_pat_resources(struct parisc_device *
unsigned long type;
unsigned long start;
unsigned long end; /* aka finish */
- } *p;
+ } *p, *io;
struct resource *r;
p = (void *) &(pa_pdc_cell.mod[2+i*3]);
+ io = (void *) &(io_pdc_cell.mod[2+i*3]);
/* Convert the PAT range data to PCI "struct resource" */
switch(p->type & 0xff) {
@@ -1075,9 +1079,9 @@ lba_pat_resources(struct parisc_device *
break;
case PAT_LMMIO:
/* used to fix up pre-initialized MEM BARs */
- lba_dev->lmmio_base = p->start;
+ lba_dev->hba.lmmio_space_offset = p->start - io->start;
- r = &(lba_dev->hba.mem_space);
+ r = &(lba_dev->hba.lmmio_space);
r->name = "LBA LMMIO";
r->start = p->start;
r->end = p->end;
@@ -1127,13 +1131,17 @@ lba_legacy_resources(struct parisc_devic
struct resource *r;
unsigned long rsize;
int lba_num;
+
#ifdef __LP64__
/*
- ** Used to sign extend instead BAR values are only 32-bit.
- ** 64-bit BARs have the upper 32-bit's zero'd by firmware.
- ** "Sprockets" PDC initializes for 32-bit OS.
+ ** 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->lmmio_base = 0xffffffff00000000UL;
+ lba_dev->hba.lmmio_space_offset = 0xffffffff00000000UL;
+#else
+ lba_dev->hba.lmmio_space_offset = 0UL;
#endif
/*
@@ -1152,14 +1160,12 @@ lba_legacy_resources(struct parisc_devic
/* Set up local PCI Bus resources - we don't really need
** them for Legacy boxes but it's nice to see in /proc.
*/
- r = &(lba_dev->hba.mem_space);
+ 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 = ((long) READ_REG32(pa_dev->hpa + LBA_LMMIO_BASE)) & ~1UL;
-#ifdef __LP64__
- r->start |= 0xffffffff00000000UL; /* sign extend f-space */
-#endif
+ 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;
/*
@@ -1172,8 +1178,8 @@ lba_legacy_resources(struct parisc_devic
/*
** XXX FIXME - ignore LBA_ELMMIO_BASE for now
- ** "Directed" ranges are used when the "distrubuted range" isn't
- ** sufficient for all devices below given LBA. Typically devices
+ ** "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
** bus has multiple slots (ie multiple devices).
**
@@ -1292,7 +1298,7 @@ static void __init
lba_common_init(struct lba_device *lba_dev)
{
pci_bios = &lba_bios_ops;
- pcibios_register_hba((struct pci_hba_data *)lba_dev);
+ pcibios_register_hba(HBA_DATA(lba_dev));
lba_dev->lba_lock = SPIN_LOCK_UNLOCKED;
/*
@@ -1395,7 +1401,6 @@ lba_driver_callback(struct parisc_device
/* Go ask PDC PAT what resources this LBA has */
lba_pat_resources(dev, lba_dev);
-
} else
#endif
{
@@ -1411,7 +1416,7 @@ lba_driver_callback(struct parisc_device
** Walks PCI bus for us too.
*/
lba_bus = lba_dev->hba.hba_bus =
- pci_scan_bus( lba_dev->hba.bus_num.start, &lba_cfg_ops, (void *)
lba_dev);
+ pci_scan_bus(lba_dev->hba.bus_num.start, &lba_cfg_ops, (void *)
lba_dev);
#ifdef __LP64__
if (is_pdc_pat()) {
@@ -1423,7 +1428,7 @@ lba_driver_callback(struct parisc_device
DBG_PAT("\nLBA PIOP resource tree\n");
lba_dump_res(&lba_dev->hba.io_space, 2);
DBG_PAT("\nLBA LMMIO resource tree\n");
- lba_dump_res(&lba_dev->hba.mem_space, 2);
+ lba_dump_res(&lba_dev->hba.lmmio_space, 2);
#endif
}
#endif
Index: arch/parisc/kernel/pci.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/pci.c,v
retrieving revision 1.26
diff -u -p -r1.26 pci.c
--- pci.c 2001/08/24 15:02:39 1.26
+++ pci.c 2001/09/12 22:35:44
@@ -227,8 +227,7 @@ pcibios_update_resource(
if (res->flags & IORESOURCE_IO) {
barval = PCI_PORT_ADDR(res->start);
} else if (res->flags & IORESOURCE_MEM) {
- /* This should work for VCLASS too */
- barval = res->start & 0xffffffffUL;
+ barval = PCI_BUS_ADDR(HBA_DATA(dev->bus->sysdata), res->start);
} else {
panic("pcibios_update_resource() WTF? flags not IO or MEM");
}
@@ -339,6 +338,7 @@ void pcibios_fixup_pbus_ranges(
struct pbus_set_ranges_data *ranges
)
{
+ struct pci_hba_data *hba = HBA_DATA(bus->sysdata);
/*
** I/O space may see busnumbers here. Something
@@ -350,11 +350,9 @@ void pcibios_fixup_pbus_ranges(
ranges->io_start = PCI_PORT_ADDR(ranges->io_start);
ranges->io_end = PCI_PORT_ADDR(ranges->io_end);
-#ifdef __LP64__
/* Convert MMIO addr to PCI addr (undo global virtualization) */
- ranges->mem_start &= 0xffffffffUL;
- ranges->mem_end &= 0xffffffffUL;
-#endif
+ ranges->mem_start = PCI_BUS_ADDR(hba, ranges->mem_start);
+ ranges->mem_end = PCI_BUS_ADDR(hba, ranges->mem_end);
DBG_RES("pcibios_fixup_pbus_ranges(%02x, [%lx,%lx %lx,%lx])\n",
bus->number,
ranges->io_start, ranges->io_end,
@@ -364,9 +362,8 @@ void pcibios_fixup_pbus_ranges(
** if this resource isn't linked to a "parent", then it seems
** to be a child of the HBA - lets link it in.
*/
- pcibios_link_hba_resources(&((struct pci_hba_data
*)bus->sysdata)->io_space, bus->resource[0]);
-
- pcibios_link_hba_resources(&((struct pci_hba_data
*)bus->sysdata)->mem_space, bus->resource[1]);
+ pcibios_link_hba_resources(&hba->io_space, bus->resource[0]);
+ pcibios_link_hba_resources(&hba->lmmio_space, bus->resource[1]);
}
#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))
Index: arch/parisc/kernel/traps.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/traps.c,v
retrieving revision 1.52
diff -u -p -r1.52 traps.c
--- traps.c 2001/09/06 09:44:07 1.52
+++ traps.c 2001/09/12 22:35:44
@@ -102,7 +102,7 @@ void show_regs(struct pt_regs *regs)
printk("%s\n", buf);
}
-#if REDICULOUSLY_VERBOSE
+#if RIDICULOUSLY_VERBOSE
for (i = 0; i < 32; i += 2)
printk("%sFR%2d : %016lx FR%2d : %016lx", level, i,
regs->fr[i], i+1, regs->fr[i+1]);
@@ -359,11 +359,11 @@ void handle_interruption(int code, struc
goto give_sigill;
case 10:
- die_if_kernel("Priviledged operation - shouldn't happen!", regs, code);
+ die_if_kernel("Privileged operation - shouldn't happen!", regs, code);
si.si_code = ILL_PRVOPC;
goto give_sigill;
case 11:
- die_if_kernel("Priviledged register - shouldn't happen!", regs, code);
+ die_if_kernel("Privileged register - shouldn't happen!", regs, code);
si.si_code = ILL_PRVREG;
give_sigill:
si.si_signo = SIGILL;
Index: arch/parisc/mm/init.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/mm/init.c,v
retrieving revision 1.37
diff -u -p -r1.37 init.c
--- init.c 2001/09/06 09:44:09 1.37
+++ init.c 2001/09/12 22:35:44
@@ -336,10 +336,21 @@ static void __init setup_bootmem(void)
#endif
#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_end != 0) {
- printk(KERN_INFO "initrd: %08x-%08x\n", (int) initrd_start, (int)
initrd_end);
- initrd_below_start_ok = 1;
- reserve_bootmem_node(NODE_DATA(0),__pa(initrd_start), initrd_end -
initrd_start);
+ if (initrd_start) {
+ printk(KERN_INFO "initrd: %08x-%08x\n", initrd_start, initrd_end);
+ if (__pa(initrd_start) < mem_max) {
+ unsigned long initrd_reserve;
+
+ if (__pa(initrd_end) > mem_max) {
+ initrd_reserve = mem_max - __pa(initrd_start);
+ } else {
+ initrd_reserve = initrd_end - initrd_start;
+ }
+ initrd_below_start_ok = 1;
+ printk(KERN_INFO "initrd: reserving %08lx-%08lx (mem_max %08lx)\n",
__pa(initrd_start), __pa(initrd_start) + initrd_reserve, mem_max);
+
+ reserve_bootmem_node(NODE_DATA(0),__pa(initrd_start), initrd_reserve);
+ }
}
#endif
@@ -451,95 +462,86 @@ void set_pte_phys (unsigned long vaddr,
{
}
-/*
- * pagetable_init() sets up the page tables
- *
- * Note that gateway_init() places the Linux gateway page at page 0.
- * Since gateway pages cannot be dereferenced this has the desirable
- * side effect of trapping those pesky NULL-reference errors in the
- * kernel.
- */
-static void __init pagetable_init(void)
+static void __init map_pages(unsigned long start_vaddr, unsigned long
start_paddr, unsigned long size, pgprot_t pgprot)
{
pgd_t *pg_dir;
pmd_t *pmd;
pte_t *pg_table;
+ unsigned long end_paddr;
unsigned long start_pmd;
+ unsigned long start_pte;
unsigned long tmp1;
unsigned long tmp2;
unsigned long address;
unsigned long ro_start;
unsigned long ro_end;
unsigned long fv_addr;
+ unsigned long gw_addr;
int range;
- extern const unsigned long fault_vector_20;
+ extern const unsigned long fault_vector_20;
+ extern void * const linux_gateway_page;
ro_start = __pa((unsigned long)&_text);
ro_end = __pa((unsigned long)&data_start);
fv_addr = __pa((unsigned long)&fault_vector_20) & PAGE_MASK;
-
- /* Map each physical memory range to its kernel vaddr */
+ gw_addr = __pa((unsigned long)&linux_gateway_page) & PAGE_MASK;
- for (range = 0; range < npmem_ranges; range++) {
- unsigned long start_paddr;
- unsigned long end_paddr;
+ end_paddr = start_paddr + size;
- start_paddr = pmem_ranges[range].start_pfn << PAGE_SHIFT;
- end_paddr = start_paddr + (pmem_ranges[range].pages << PAGE_SHIFT);
+ pg_dir = pgd_offset_k(start_vaddr);
- pg_dir = pgd_offset_k(start_paddr + PAGE_OFFSET);
-
#if PTRS_PER_PMD == 1
- start_pmd = 0;
+ start_pmd = 0;
#else
- start_pmd = (((start_paddr + PAGE_OFFSET) >> PMD_SHIFT) & (PTRS_PER_PMD
- 1));
+ start_pmd = ((start_vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
#endif
+ start_pte = ((start_vaddr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
- address = start_paddr;
- while (address < end_paddr) {
+ address = start_paddr;
+ while (address < end_paddr) {
#if PTRS_PER_PMD == 1
- pmd = (pmd_t *)__pa(pg_dir);
+ pmd = (pmd_t *)__pa(pg_dir);
#else
- pmd = (pmd_t *) (PAGE_MASK & pgd_val(*pg_dir));
+ pmd = (pmd_t *) (PAGE_MASK & pgd_val(*pg_dir));
+
+ /*
+ * pmd is physical at this point
+ */
+
+ if (!pmd) {
+ pmd = (pmd_t *) alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE);
+ pmd = (pmd_t *) __pa(pmd);
+ }
+
+ pgd_val(*pg_dir) = _PAGE_TABLE | (unsigned long) pmd;
+#endif
+ pg_dir++;
+
+ /* now change pmd to kernel virtual addresses */
+
+ pmd = (pmd_t *)__va(pmd) + start_pmd;
+ for (tmp1 = start_pmd; tmp1 < PTRS_PER_PMD; tmp1++,pmd++) {
/*
- * pmd is physical at this point
+ * pg_table is physical at this point
*/
- if (!pmd) {
- pmd = (pmd_t *) alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE);
- pmd = (pmd_t *) __pa(pmd);
+ pg_table = (pte_t *) (PAGE_MASK & pmd_val(*pmd));
+ if (!pg_table) {
+ pg_table = (pte_t *)
+ alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE);
+ pg_table = (pte_t *) __pa(pg_table);
}
- pgd_val(*pg_dir) = _PAGE_TABLE | (unsigned long) pmd;
-#endif
- pg_dir++;
+ pmd_val(*pmd) = _PAGE_TABLE |
+ (unsigned long) pg_table;
- /* now change pmd to kernel virtual addresses */
+ /* now change pg_table to kernel virtual addresses */
- pmd = (pmd_t *)__va(pmd) + start_pmd;
- for (tmp1 = start_pmd; tmp1 < PTRS_PER_PMD; tmp1++,pmd++) {
+ pg_table = (pte_t *) __va(pg_table) + start_pte;
+ for (tmp2 = start_pte; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) {
+ pte_t pte;
- /*
- * pg_table is physical at this point
- */
-
- pg_table = (pte_t *) (PAGE_MASK & pmd_val(*pmd));
- if (!pg_table) {
- pg_table = (pte_t *)
- alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE);
- pg_table = (pte_t *) __pa(pg_table);
- }
-
- pmd_val(*pmd) = _PAGE_TABLE |
- (unsigned long) pg_table;
-
- /* now change pg_table to kernel virtual addresses */
-
- pg_table = (pte_t *) __va(pg_table);
- for (tmp2=0; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) {
- pte_t pte;
-
#if !defined(CONFIG_KWDB) && !defined(CONFIG_STI_CONSOLE)
#warning STI console should explicitly allocate executable pages but does
not
/* KWDB needs to write kernel text when setting break points.
@@ -547,28 +549,70 @@ static void __init pagetable_init(void)
** The right thing to do seems like KWDB modify only the pte which
** has a break point on it...otherwise we might mask worse bugs.
*/
- if (address >= ro_start && address < ro_end
- && address != fv_addr)
- pte = __mk_pte(address, PAGE_KERNEL_RO);
- else
+ /*
+ * Map the fault vector writable so we can
+ * write the HPMC checksum.
+ */
+ if (address >= ro_start && address < ro_end
+ && address != fv_addr
+ && address != gw_addr)
+ pte = __mk_pte(address, PAGE_KERNEL_RO);
+ else
#endif
- pte = __mk_pte(address, PAGE_KERNEL);
+ pte = __mk_pte(address, pgprot);
- if (address >= end_paddr)
- pte_val(pte) = 0;
-
- set_pte(pg_table, pte);
+ if (address >= end_paddr)
+ pte_val(pte) = 0;
- address += PAGE_SIZE;
- }
+ set_pte(pg_table, pte);
- if (address >= end_paddr)
- break;
+ address += PAGE_SIZE;
}
- start_pmd = 0;
+ start_pte = 0;
+
+ if (address >= end_paddr)
+ break;
}
+ start_pmd = 0;
}
+}
+
+/*
+ * pagetable_init() sets up the page tables
+ *
+ * Note that gateway_init() places the Linux gateway page at page 0.
+ * Since gateway pages cannot be dereferenced this has the desirable
+ * side effect of trapping those pesky NULL-reference errors in the
+ * kernel.
+ */
+static void __init pagetable_init(void)
+{
+ int range;
+
+ printk("pagetable_init\n");
+ /* Map each physical memory range to its kernel vaddr */
+
+ for (range = 0; range < npmem_ranges; range++) {
+ unsigned long start_paddr;
+ unsigned long end_paddr;
+ unsigned long size;
+
+ start_paddr = pmem_ranges[range].start_pfn << PAGE_SHIFT;
+ end_paddr = start_paddr + (pmem_ranges[range].pages << PAGE_SHIFT);
+ size = pmem_ranges[range].pages << PAGE_SHIFT;
+
+ map_pages(__va(start_paddr), start_paddr, size, PAGE_KERNEL);
+ }
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_end && initrd_end > mem_limit) {
+ printk("initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end);
+ map_pages(initrd_start, __pa(initrd_start),
+ initrd_end - initrd_start, PAGE_KERNEL);
+ }
+#endif
+
empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
memset(empty_zero_page, 0, PAGE_SIZE);
}
@@ -576,14 +620,9 @@ static void __init pagetable_init(void)
static void __init gateway_init(void)
{
unsigned long linux_gateway_page_addr;
- pgd_t *pg_dir;
- pmd_t *pmd;
- pte_t *pg_table_base;
- pte_t *pg_table;
/* FIXME: This is 'const' in order to trick the compiler
into not treating it as DP-relative data. */
extern void * const linux_gateway_page;
- pte_t pte;
linux_gateway_page_addr = LINUX_GATEWAY_ADDR & PAGE_MASK;
@@ -593,28 +632,9 @@ static void __init gateway_init(void)
* The Linux gateway page will reside in kernel space (on virtual
* page 0), so it doesn't need to be aliased into user space.
*/
-
- pg_dir = pgd_offset_k(linux_gateway_page_addr);
-
-#if (PTRS_PER_PMD != 1)
- if (pgd_none(*pg_dir)) {
- pmd_t *pmd_base;
- pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE);
- pgd_val(*pg_dir) = _PAGE_TABLE | __pa(pmd_base);
- }
-#endif
-
- pmd = pmd_offset(pg_dir,linux_gateway_page_addr);
- if (pmd_none(*pmd)) {
- pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
- pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base);
- }
-
- pg_table = pte_offset(pmd,linux_gateway_page_addr);
- pte = __mk_pte(__pa(&linux_gateway_page), PAGE_GATEWAY);
- set_pte(pg_table,pte);
- return;
+ map_pages(linux_gateway_page_addr, __pa(&linux_gateway_page),
+ PAGE_SIZE, PAGE_GATEWAY);
}
extern void flush_tlb_all_local(void);
Index: drivers/gsc/dino.c
===================================================================
RCS file: /home/cvs/parisc/linux/drivers/gsc/dino.c,v
retrieving revision 1.38
diff -u -p -r1.38 dino.c
--- dino.c 2001/08/31 06:02:17 1.38
+++ dino.c 2001/09/12 22:35:44
@@ -666,6 +666,7 @@ dino_card_init(struct dino_device *dino_
dino_dev->ioport_addr = 0x00001000; /* Make believe */
dino_dev->mmio_addr = 0xf0800000; /* FIXME: Make believe */
+ dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */
gsc_writel(0x00000000, dino_dev->hba.base_addr+DINO_DAMODE);
gsc_writel(0x00222222, dino_dev->hba.base_addr+DINO_PCIROR);
@@ -723,6 +724,7 @@ dino_bridge_init(struct dino_device *din
*/
dino_dev->mmio_addr = 0xf0000000 + (bpos << 23); /* bpos x 8MB */
dino_dev->ioport_addr = 0; /* not used for bridge mode */
+ dino_dev->hba.lmmio_space_offset = 0; /* CPU addrs == bus addrs */
}
static int __init
Index: include/asm-parisc/pci.h
===================================================================
RCS file: /home/cvs/parisc/linux/include/asm-parisc/pci.h,v
retrieving revision 1.29
diff -u -p -r1.29 pci.h
--- pci.h 2001/08/14 16:55:00 1.29
+++ pci.h 2001/09/12 22:35:45
@@ -3,9 +3,6 @@
#include <asm/scatterlist.h>
-#define MIN_PCI_PORT 0x000000
-#define MAX_PCI_PORT 0xffffff
-
/*
** HP PCI platforms generally support multiple bus adapters.
** (workstations 1-~4, servers 2-~32)
@@ -19,7 +16,7 @@
#define PCI_MAX_BUSSES 256
/* [soapbox on]
-** Who the hell can develope stuff without ASSERT or VASSERT?
+** Who the hell can develop stuff without ASSERT or VASSERT?
** No one understands all the modules across all platforms.
** For linux add another dimension - processor architectures.
**
@@ -56,11 +53,13 @@ struct pci_hba_data {
int hba_num; /* I/O port space access "key" */
struct resource bus_num; /* PCI bus numbers */
struct resource io_space; /* PIOP */
- struct resource mem_space; /* LMMIO */
- unsigned long mem_space_offset; /* VCLASS support */
+ struct resource lmmio_space; /* bus addresses < 4Gb */
+ unsigned long lmmio_space_offset; /* CPU view - PCI view */
/* REVISIT - spinlock to protect resources? */
};
+#define HBA_DATA(d) ((struct pci_hba_data *) (d))
+
/*
** We support 2^16 I/O ports per HBA. These are set up in the form
** 0xbbxxxx, where bb is the bus number and xxxx is the I/O port
@@ -73,6 +72,13 @@ struct pci_hba_data {
#define PCI_PORT_HBA(a) ((a) >> HBA_PORT_SPACE_BITS)
#define PCI_PORT_ADDR(a) ((a) & (HBA_PORT_SPACE_SIZE - 1))
+
+/*
+** Convert between PCI (IO_VIEW) addresses and processor (PA_VIEW)
addresses.
+** Note that we currently support only LMMIO.
+*/
+#define PCI_BUS_ADDR(hba,a) ((a) - hba->lmmio_space_offset)
+#define PCI_HOST_ADDR(hba,a) ((a) + hba->lmmio_space_offset)
/*
** KLUGE: linux/pci.h include asm/pci.h BEFORE declaring struct pci_bus