Change how the MPIC/OpenPIC is configured at boot. Rather than scanning

for a magical PCI device location (that is sometimes wrong), we scan the
residual data for an MPIC, and if we find one, wire it up from there.
This will hopefully allow interrupts to work on the MPC750 and the
7025-F40. I suspect however the interrupt vector address on the 7025 will
still need some work.
This commit is contained in:
garbled 2006-06-29 17:16:59 +00:00
parent 56054d1bbb
commit 793a3b26d8
3 changed files with 105 additions and 55 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: intr.h,v 1.25 2006/05/08 17:08:34 garbled Exp $ */
/* $NetBSD: intr.h,v 1.26 2006/06/29 17:16:59 garbled Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -97,6 +97,7 @@ void do_pending_int(void);
void init_intr(void);
void init_intr_ivr(void);
void init_intr_openpic(void);
void openpic_init(unsigned char *);
void enable_intr(void);
void disable_intr(void);

View File

@ -1,4 +1,4 @@
/* $NetBSD: extintr.c,v 1.24 2006/06/27 23:26:13 garbled Exp $ */
/* $NetBSD: extintr.c,v 1.25 2006/06/29 17:16:59 garbled Exp $ */
/* $OpenBSD: isabus.c,v 1.12 1999/06/15 02:40:05 rahnds Exp $ */
/*-
@ -119,7 +119,7 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: extintr.c,v 1.24 2006/06/27 23:26:13 garbled Exp $");
__KERNEL_RCSID(0, "$NetBSD: extintr.c,v 1.25 2006/06/29 17:16:59 garbled Exp $");
#include "opt_openpic.h"
#include "pci.h"
@ -687,6 +687,11 @@ openpic_init(unsigned char *baseaddr)
openpic_base = baseaddr;
x = openpic_read(OPENPIC_FEATURE);
aprint_normal("OpenPIC Version 1.%d: "
"Supports %d CPUs and %d interrupt sources.\n",
x & 0xff, ((x & 0x1f00) >> 8) + 1, ((x & 0x07ff0000) >> 16) + 1);
openpic_set_priority(0, 0x0f);
/* disable all interrupts */
@ -716,57 +721,15 @@ openpic_init(unsigned char *baseaddr)
install_extint(ext_intr_openpic);
}
#endif /* OPENPIC */
void
init_intr(void)
{
#if defined(OPENPIC)
unsigned char *baseaddr = (unsigned char *)0xC0006800; /* XXX */
#if NPCI > 0
int i;
struct prep_pci_chipset pc;
pcitag_t tag;
pcireg_t id, address;
prep_pci_get_chipset_tag(&pc);
tag = pci_make_tag(&pc, 0, 13, 0);
id = pci_conf_read(&pc, tag, PCI_ID_REG);
if (PCI_VENDOR(id) == PCI_VENDOR_IBM
&& (PCI_PRODUCT(id) == PCI_PRODUCT_IBM_MPIC ||
PCI_PRODUCT(id) == PCI_PRODUCT_IBM_MPIC2)) {
address = pci_conf_read(&pc, tag, 0x10);
if ((address & PCI_MAPREG_TYPE_MASK) == PCI_MAPREG_TYPE_MEM) {
address &= PCI_MAPREG_MEM_ADDR_MASK;
/*
* PReP PCI memory space is from 0xc0000000 to
* 0xffffffff but machdep.c maps only 0xc0000000 to
* 0xcfffffff of PCI memory space. So look if the
* address offset is bigger then 0xfffffff. If it is
* we are outside the already mapped region and we need
* to add an additional mapping for the OpenPIC.
* The OpenPIC register window is always 256kB.
*/
if (address > 0xfffffff)
baseaddr = (unsigned char *) mapiodev(
PREP_BUS_SPACE_MEM | address, 0x40000);
else
baseaddr = (unsigned char *)
(PREP_BUS_SPACE_MEM | address);
} else if ((address & PCI_MAPREG_TYPE_MASK) ==
PCI_MAPREG_TYPE_IO) {
address &= PCI_MAPREG_IO_ADDR_MASK;
baseaddr = (unsigned char *) mapiodev(
PREP_BUS_SPACE_IO | address, 0x40000);
}
openpic_init(baseaddr);
return;
}
#endif /* NPCI */
openpic_base = 0;
#endif
i = find_platform_quirk(res->VitalProductData.PrintableModel);
if (i != -1)
if (platform_quirks[i].quirk & PLAT_QUIRK_ISA_HANDLER &&

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.62 2006/05/25 02:11:13 garbled Exp $ */
/* $NetBSD: machdep.c,v 1.63 2006/06/29 17:16:59 garbled Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@ -32,10 +32,11 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.62 2006/05/25 02:11:13 garbled Exp $");
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.63 2006/06/29 17:16:59 garbled Exp $");
#include "opt_compat_netbsd.h"
#include "opt_ddb.h"
#include "opt_openpic.h"
#include <sys/param.h>
#include <sys/buf.h>
@ -97,6 +98,7 @@ void dumpsys(void);
void strayintr(int);
int lcsplx(int);
void prep_bus_space_init(void);
static void prep_init(void);
char bootinfo[BOOTINFO_MAXSIZE];
char bootpath[256];
@ -248,20 +250,21 @@ cpu_startup(void)
panic("startup: no room for interrupt register");
/*
* Do common startup.
*/
oea_startup(res->VitalProductData.PrintableModel);
/*
* General prep setup using pnp residual. Also provides for
* external interrupt handler install
*/
init_intr();
prep_init();
/*
* Initialize soft interrupt framework.
*/
softintr__init();
/*
* Do common startup.
*/
oea_startup(res->VitalProductData.PrintableModel);
/*
* Now allow hardware interrupts.
*/
@ -452,3 +455,86 @@ prep_bus_space_init(void)
if (error)
panic("prep_bus_space_init: can't init isa mem tag");
}
#if defined(OPENPIC)
static int
setup_openpic(PPC_DEVICE *dev)
{
uint32_t l;
uint8_t *p;
void *v;
int tag, size, item;
unsigned char *baseaddr = NULL;
l = be32toh(dev->AllocatedOffset);
p = res->DevicePnPHeap + l;
/* look for the large vendor item that describes the MPIC's memory
* range */
for (; p[0] != END_TAG; p += size) {
struct _L4_Pack *pack = (void *)p;
struct _L4_PPCPack *pa = &pack->L4_Data.L4_PPCPack;
tag = *p;
v = p;
if (tag_type(p[0]) == PNP_SMALL) {
size = tag_small_count(tag) + 1;
continue;
}
size = (p[1] | (p[2] << 8)) + 3 /* tag + length */;
item = tag_large_item_name(tag);
if (item != LargeVendorItem || pa->Type != LV_GenericAddress)
continue;
/* otherwise, we have a memory packet */
if (pa->PPCData[0] == 1)
baseaddr = (unsigned char *)mapiodev(
le64dec(&pa->PPCData[4]) | PREP_BUS_SPACE_IO,
le64dec(&pa->PPCData[12]));
else if (pa->PPCData[0] == 2)
baseaddr = (unsigned char *)mapiodev(
le64dec(&pa->PPCData[4]) | PREP_BUS_SPACE_MEM,
le64dec(&pa->PPCData[12]));
if (baseaddr == NULL)
return 0;
openpic_init(baseaddr);
return 1;
}
return 0;
}
#endif /* OPENPIC */
/*
* There are a few things that need setting up early on in the prep
* architecture. Foremost of these is the MPIC (if present) and the
* l2 cache controller. This is a cut-down version of pnpbus_search()
* that looks for specific devices, and sets them up accordingly.
* This should also look for and wire up the interrupt vector.
*/
static void
prep_init()
{
PPC_DEVICE *ppc_dev;
int i, foundmpic;
uint32_t ndev;
ndev = be32toh(res->ActualNumDevices);
ppc_dev = res->Devices;
foundmpic = 0;
for (i = 0; i < ((ndev > MAX_DEVICES) ? MAX_DEVICES : ndev); i++) {
#if defined(OPENPIC)
if (ppc_dev[i].DeviceId.DevId == 0x244d000d) { /* MPIC */
foundmpic = setup_openpic(&ppc_dev[i]);
}
#else
;
#endif
}
if (!foundmpic)
init_intr();
}