Add support for multiple PCI busses directly connected to the nexus.
This is only partially complete, but allows 450NX-based systems with more than one PCI bus to be used again. Submitted by: dfr
This commit is contained in:
parent
a4df7ffed9
commit
850013034a
@ -26,7 +26,7 @@
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: nexus.c,v 1.10 1999/05/18 20:48:41 peter Exp $
|
||||
* $Id: nexus.c,v 1.11 1999/05/30 10:50:57 dfr Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -75,6 +75,8 @@ static struct rman irq_rman, drq_rman, port_rman, mem_rman;
|
||||
|
||||
static int nexus_probe(device_t);
|
||||
static void nexus_print_child(device_t, device_t);
|
||||
static device_t nexus_add_child(device_t bus, int order, const char *name,
|
||||
int unit);
|
||||
static struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
|
||||
u_long, u_long, u_long, u_int);
|
||||
static int nexus_activate_resource(device_t, device_t, int, int,
|
||||
@ -99,6 +101,7 @@ static device_method_t nexus_methods[] = {
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_print_child, nexus_print_child),
|
||||
DEVMETHOD(bus_add_child, nexus_add_child),
|
||||
DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
|
||||
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
|
||||
@ -192,9 +195,12 @@ nexus_probe(device_t dev)
|
||||
if (child == 0)
|
||||
panic("nexus_probe apm");
|
||||
|
||||
bus_generic_probe(dev);
|
||||
#if 0
|
||||
child = device_add_child(dev, "pcib", 0, 0);
|
||||
if (child == 0)
|
||||
panic("nexus_probe pcib");
|
||||
#endif
|
||||
|
||||
child = device_add_child(dev, "eisa", 0, 0);
|
||||
if (child == 0)
|
||||
@ -213,6 +219,12 @@ nexus_print_child(device_t bus, device_t child)
|
||||
printf(" on motherboard");
|
||||
}
|
||||
|
||||
static device_t
|
||||
nexus_add_child(device_t bus, int order, const char *name, int unit)
|
||||
{
|
||||
return device_add_child_ordered(bus, order, name, unit, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a resource on behalf of child. NB: child is usually going to be a
|
||||
* child of one of our descendants, not a direct child of nexus0.
|
||||
|
@ -26,7 +26,7 @@
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: nexus.c,v 1.10 1999/05/18 20:48:41 peter Exp $
|
||||
* $Id: nexus.c,v 1.11 1999/05/30 10:50:57 dfr Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -75,6 +75,8 @@ static struct rman irq_rman, drq_rman, port_rman, mem_rman;
|
||||
|
||||
static int nexus_probe(device_t);
|
||||
static void nexus_print_child(device_t, device_t);
|
||||
static device_t nexus_add_child(device_t bus, int order, const char *name,
|
||||
int unit);
|
||||
static struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
|
||||
u_long, u_long, u_long, u_int);
|
||||
static int nexus_activate_resource(device_t, device_t, int, int,
|
||||
@ -99,6 +101,7 @@ static device_method_t nexus_methods[] = {
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_print_child, nexus_print_child),
|
||||
DEVMETHOD(bus_add_child, nexus_add_child),
|
||||
DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
|
||||
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
|
||||
@ -192,9 +195,12 @@ nexus_probe(device_t dev)
|
||||
if (child == 0)
|
||||
panic("nexus_probe apm");
|
||||
|
||||
bus_generic_probe(dev);
|
||||
#if 0
|
||||
child = device_add_child(dev, "pcib", 0, 0);
|
||||
if (child == 0)
|
||||
panic("nexus_probe pcib");
|
||||
#endif
|
||||
|
||||
child = device_add_child(dev, "eisa", 0, 0);
|
||||
if (child == 0)
|
||||
@ -213,6 +219,12 @@ nexus_print_child(device_t bus, device_t child)
|
||||
printf(" on motherboard");
|
||||
}
|
||||
|
||||
static device_t
|
||||
nexus_add_child(device_t bus, int order, const char *name, int unit)
|
||||
{
|
||||
return device_add_child_ordered(bus, order, name, unit, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a resource on behalf of child. NB: child is usually going to be a
|
||||
* child of one of our descendants, not a direct child of nexus0.
|
||||
|
@ -23,7 +23,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: pcibus.c,v 1.41 1997/12/20 09:04:25 se Exp $
|
||||
* $Id: pcibus.c,v 1.42 1999/05/18 20:48:43 peter Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
#include <i386/isa/pcibus.h>
|
||||
|
||||
#ifdef PCI_COMPAT
|
||||
@ -268,13 +269,187 @@ pci_cfgopen(void)
|
||||
|
||||
static devclass_t pcib_devclass;
|
||||
|
||||
static const char *
|
||||
nexus_pcib_is_host_bridge(pcicfgregs *cfg,
|
||||
u_int32_t id, u_int8_t class, u_int8_t subclass,
|
||||
u_int8_t *busnum)
|
||||
{
|
||||
const char *s = "Host to PCI bridge";
|
||||
static u_int8_t pxb[4]; /* hack for 450nx */
|
||||
|
||||
if (class != PCIC_BRIDGE || subclass != PCIS_BRIDGE_HOST)
|
||||
return NULL;
|
||||
|
||||
*busnum = 0;
|
||||
|
||||
switch (id) {
|
||||
case 0x12258086:
|
||||
s = "Intel 824?? host to PCI bridge";
|
||||
/* XXX This is a guess */
|
||||
*busnum = pci_cfgread(cfg, 0x41, 1);
|
||||
break;
|
||||
case 0x71808086:
|
||||
s = "Intel 82443LX (440 LX) host to PCI bridge";
|
||||
break;
|
||||
case 0x71908086:
|
||||
s = "Intel 82443BX (440 BX) host to PCI bridge";
|
||||
break;
|
||||
case 0x71928086:
|
||||
s = "Intel 82443BX host to PCI bridge (AGP disabled)";
|
||||
break;
|
||||
case 0x71a08086:
|
||||
s = "Intel 82443GX host to PCI bridge";
|
||||
break;
|
||||
case 0x71a18086:
|
||||
s = "Intel 82443GX host to AGP bridge";
|
||||
break;
|
||||
case 0x71a28086:
|
||||
s = "Intel 82443GX host to PCI bridge (AGP disabled)";
|
||||
break;
|
||||
case 0x84c48086:
|
||||
s = "Intel 82454KX/GX (Orion) host to PCI bridge";
|
||||
*busnum = pci_cfgread(cfg, 0x4a, 1);
|
||||
break;
|
||||
case 0x84ca8086:
|
||||
/*
|
||||
* For the 450nx chipset, there is a whole bundle of
|
||||
* things pretending to be host bridges. The MIOC will
|
||||
* be seen first and isn't really a pci bridge (the
|
||||
* actual busses are attached to the PXB's). We need to
|
||||
* read the registers of the MIOC to figure out the
|
||||
* bus numbers for the PXB channels.
|
||||
*
|
||||
* Since the MIOC doesn't have a pci bus attached, we
|
||||
* pretend it wasn't there.
|
||||
*/
|
||||
pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
|
||||
pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
|
||||
pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
|
||||
pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
|
||||
return NULL;
|
||||
case 0x84cb8086:
|
||||
switch (cfg->slot) {
|
||||
case 0x12:
|
||||
s = "Intel 82454NX PXB#0, Bus#A";
|
||||
*busnum = pxb[0];
|
||||
break;
|
||||
case 0x13:
|
||||
s = "Intel 82454NX PXB#0, Bus#B";
|
||||
*busnum = pxb[1];
|
||||
break;
|
||||
case 0x14:
|
||||
s = "Intel 82454NX PXB#1, Bus#A";
|
||||
*busnum = pxb[2];
|
||||
break;
|
||||
case 0x15:
|
||||
s = "Intel 82454NX PXB#1, Bus#B";
|
||||
*busnum = pxb[3];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* SiS -- vendor 0x1039 */
|
||||
case 0x04961039:
|
||||
s = "SiS 85c496";
|
||||
break;
|
||||
case 0x04061039:
|
||||
s = "SiS 85c501";
|
||||
break;
|
||||
case 0x06011039:
|
||||
s = "SiS 85c601";
|
||||
break;
|
||||
case 0x55911039:
|
||||
s = "SiS 5591 host to PCI bridge";
|
||||
break;
|
||||
case 0x00011039:
|
||||
s = "SiS 5591 host to AGP bridge";
|
||||
break;
|
||||
|
||||
/* VLSI -- vendor 0x1004 */
|
||||
case 0x00051004:
|
||||
s = "VLSI 82C592 Host to PCI bridge";
|
||||
break;
|
||||
|
||||
/* XXX Here is MVP3, I got the datasheet but NO M/B to test it */
|
||||
/* totally. Please let me know if anything wrong. -F */
|
||||
/* XXX need info on the MVP3 -- any takers? */
|
||||
case 0x05981106:
|
||||
s = "VIA 82C598MVP (Apollo MVP3) host bridge";
|
||||
break;
|
||||
|
||||
/* AcerLabs -- vendor 0x10b9 */
|
||||
/* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
|
||||
/* id is '10b9" but the register always shows "10b9". -Foxfair */
|
||||
case 0x154110b9:
|
||||
s = "AcerLabs M1541 (Aladdin-V) PCI host bridge";
|
||||
break;
|
||||
|
||||
/* OPTi -- vendor 0x1045 */
|
||||
case 0xc8221045:
|
||||
s = "OPTi 82C822 host to PCI Bridge";
|
||||
break;
|
||||
|
||||
/* Ross (?) -- vendor 0x1166 */
|
||||
case 0x00051166:
|
||||
s = "Ross (?) host to PCI bridge";
|
||||
/* just guessing the secondary bus register number ... */
|
||||
*busnum = pci_cfgread(cfg, 0x45, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the first pci bus for host-pci bridges and add pcib instances
|
||||
* to the nexus for each bridge.
|
||||
*/
|
||||
static void
|
||||
nexus_pcib_identify(driver_t *driver, device_t parent)
|
||||
{
|
||||
pcicfgregs probe;
|
||||
|
||||
probe.hose = 0;
|
||||
probe.bus = 0;
|
||||
|
||||
pci_cfgopen();
|
||||
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
|
||||
int pcifunchigh = 0;
|
||||
for (probe.func = 0;
|
||||
probe.func <= pcifunchigh;
|
||||
probe.func++) {
|
||||
/*
|
||||
* Read the IDs and class from the device.
|
||||
*/
|
||||
u_int32_t id;
|
||||
u_int8_t class, subclass, busnum;
|
||||
device_t child;
|
||||
const char *s;
|
||||
|
||||
id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
|
||||
if (id == -1)
|
||||
continue;
|
||||
class = pci_cfgread(&probe, PCIR_CLASS, 1);
|
||||
subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
|
||||
|
||||
s = nexus_pcib_is_host_bridge(&probe, id,
|
||||
class, subclass,
|
||||
&busnum);
|
||||
if (s) {
|
||||
child = BUS_ADD_CHILD(parent, 0,
|
||||
"pcib", busnum);
|
||||
device_set_desc(child, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_pcib_probe(device_t dev)
|
||||
{
|
||||
if (pci_cfgopen() != 0) {
|
||||
device_set_desc(dev, "PCI host bus adapter");
|
||||
|
||||
device_add_child(dev, "pci", 0, 0);
|
||||
device_add_child(dev, "pci", device_get_unit(dev), 0);
|
||||
return 0;
|
||||
}
|
||||
return ENXIO;
|
||||
@ -282,6 +457,7 @@ nexus_pcib_probe(device_t dev)
|
||||
|
||||
static device_method_t nexus_pcib_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_identify, nexus_pcib_identify),
|
||||
DEVMETHOD(device_probe, nexus_pcib_probe),
|
||||
DEVMETHOD(device_attach, bus_generic_attach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
|
@ -23,7 +23,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: pcibus.c,v 1.41 1997/12/20 09:04:25 se Exp $
|
||||
* $Id: pcibus.c,v 1.42 1999/05/18 20:48:43 peter Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
#include <i386/isa/pcibus.h>
|
||||
|
||||
#ifdef PCI_COMPAT
|
||||
@ -268,13 +269,187 @@ pci_cfgopen(void)
|
||||
|
||||
static devclass_t pcib_devclass;
|
||||
|
||||
static const char *
|
||||
nexus_pcib_is_host_bridge(pcicfgregs *cfg,
|
||||
u_int32_t id, u_int8_t class, u_int8_t subclass,
|
||||
u_int8_t *busnum)
|
||||
{
|
||||
const char *s = "Host to PCI bridge";
|
||||
static u_int8_t pxb[4]; /* hack for 450nx */
|
||||
|
||||
if (class != PCIC_BRIDGE || subclass != PCIS_BRIDGE_HOST)
|
||||
return NULL;
|
||||
|
||||
*busnum = 0;
|
||||
|
||||
switch (id) {
|
||||
case 0x12258086:
|
||||
s = "Intel 824?? host to PCI bridge";
|
||||
/* XXX This is a guess */
|
||||
*busnum = pci_cfgread(cfg, 0x41, 1);
|
||||
break;
|
||||
case 0x71808086:
|
||||
s = "Intel 82443LX (440 LX) host to PCI bridge";
|
||||
break;
|
||||
case 0x71908086:
|
||||
s = "Intel 82443BX (440 BX) host to PCI bridge";
|
||||
break;
|
||||
case 0x71928086:
|
||||
s = "Intel 82443BX host to PCI bridge (AGP disabled)";
|
||||
break;
|
||||
case 0x71a08086:
|
||||
s = "Intel 82443GX host to PCI bridge";
|
||||
break;
|
||||
case 0x71a18086:
|
||||
s = "Intel 82443GX host to AGP bridge";
|
||||
break;
|
||||
case 0x71a28086:
|
||||
s = "Intel 82443GX host to PCI bridge (AGP disabled)";
|
||||
break;
|
||||
case 0x84c48086:
|
||||
s = "Intel 82454KX/GX (Orion) host to PCI bridge";
|
||||
*busnum = pci_cfgread(cfg, 0x4a, 1);
|
||||
break;
|
||||
case 0x84ca8086:
|
||||
/*
|
||||
* For the 450nx chipset, there is a whole bundle of
|
||||
* things pretending to be host bridges. The MIOC will
|
||||
* be seen first and isn't really a pci bridge (the
|
||||
* actual busses are attached to the PXB's). We need to
|
||||
* read the registers of the MIOC to figure out the
|
||||
* bus numbers for the PXB channels.
|
||||
*
|
||||
* Since the MIOC doesn't have a pci bus attached, we
|
||||
* pretend it wasn't there.
|
||||
*/
|
||||
pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
|
||||
pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
|
||||
pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
|
||||
pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
|
||||
return NULL;
|
||||
case 0x84cb8086:
|
||||
switch (cfg->slot) {
|
||||
case 0x12:
|
||||
s = "Intel 82454NX PXB#0, Bus#A";
|
||||
*busnum = pxb[0];
|
||||
break;
|
||||
case 0x13:
|
||||
s = "Intel 82454NX PXB#0, Bus#B";
|
||||
*busnum = pxb[1];
|
||||
break;
|
||||
case 0x14:
|
||||
s = "Intel 82454NX PXB#1, Bus#A";
|
||||
*busnum = pxb[2];
|
||||
break;
|
||||
case 0x15:
|
||||
s = "Intel 82454NX PXB#1, Bus#B";
|
||||
*busnum = pxb[3];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* SiS -- vendor 0x1039 */
|
||||
case 0x04961039:
|
||||
s = "SiS 85c496";
|
||||
break;
|
||||
case 0x04061039:
|
||||
s = "SiS 85c501";
|
||||
break;
|
||||
case 0x06011039:
|
||||
s = "SiS 85c601";
|
||||
break;
|
||||
case 0x55911039:
|
||||
s = "SiS 5591 host to PCI bridge";
|
||||
break;
|
||||
case 0x00011039:
|
||||
s = "SiS 5591 host to AGP bridge";
|
||||
break;
|
||||
|
||||
/* VLSI -- vendor 0x1004 */
|
||||
case 0x00051004:
|
||||
s = "VLSI 82C592 Host to PCI bridge";
|
||||
break;
|
||||
|
||||
/* XXX Here is MVP3, I got the datasheet but NO M/B to test it */
|
||||
/* totally. Please let me know if anything wrong. -F */
|
||||
/* XXX need info on the MVP3 -- any takers? */
|
||||
case 0x05981106:
|
||||
s = "VIA 82C598MVP (Apollo MVP3) host bridge";
|
||||
break;
|
||||
|
||||
/* AcerLabs -- vendor 0x10b9 */
|
||||
/* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
|
||||
/* id is '10b9" but the register always shows "10b9". -Foxfair */
|
||||
case 0x154110b9:
|
||||
s = "AcerLabs M1541 (Aladdin-V) PCI host bridge";
|
||||
break;
|
||||
|
||||
/* OPTi -- vendor 0x1045 */
|
||||
case 0xc8221045:
|
||||
s = "OPTi 82C822 host to PCI Bridge";
|
||||
break;
|
||||
|
||||
/* Ross (?) -- vendor 0x1166 */
|
||||
case 0x00051166:
|
||||
s = "Ross (?) host to PCI bridge";
|
||||
/* just guessing the secondary bus register number ... */
|
||||
*busnum = pci_cfgread(cfg, 0x45, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the first pci bus for host-pci bridges and add pcib instances
|
||||
* to the nexus for each bridge.
|
||||
*/
|
||||
static void
|
||||
nexus_pcib_identify(driver_t *driver, device_t parent)
|
||||
{
|
||||
pcicfgregs probe;
|
||||
|
||||
probe.hose = 0;
|
||||
probe.bus = 0;
|
||||
|
||||
pci_cfgopen();
|
||||
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
|
||||
int pcifunchigh = 0;
|
||||
for (probe.func = 0;
|
||||
probe.func <= pcifunchigh;
|
||||
probe.func++) {
|
||||
/*
|
||||
* Read the IDs and class from the device.
|
||||
*/
|
||||
u_int32_t id;
|
||||
u_int8_t class, subclass, busnum;
|
||||
device_t child;
|
||||
const char *s;
|
||||
|
||||
id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
|
||||
if (id == -1)
|
||||
continue;
|
||||
class = pci_cfgread(&probe, PCIR_CLASS, 1);
|
||||
subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
|
||||
|
||||
s = nexus_pcib_is_host_bridge(&probe, id,
|
||||
class, subclass,
|
||||
&busnum);
|
||||
if (s) {
|
||||
child = BUS_ADD_CHILD(parent, 0,
|
||||
"pcib", busnum);
|
||||
device_set_desc(child, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_pcib_probe(device_t dev)
|
||||
{
|
||||
if (pci_cfgopen() != 0) {
|
||||
device_set_desc(dev, "PCI host bus adapter");
|
||||
|
||||
device_add_child(dev, "pci", 0, 0);
|
||||
device_add_child(dev, "pci", device_get_unit(dev), 0);
|
||||
return 0;
|
||||
}
|
||||
return ENXIO;
|
||||
@ -282,6 +457,7 @@ nexus_pcib_probe(device_t dev)
|
||||
|
||||
static device_method_t nexus_pcib_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_identify, nexus_pcib_identify),
|
||||
DEVMETHOD(device_probe, nexus_pcib_probe),
|
||||
DEVMETHOD(device_attach, bus_generic_attach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
|
@ -26,7 +26,7 @@
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: nexus.c,v 1.10 1999/05/18 20:48:41 peter Exp $
|
||||
* $Id: nexus.c,v 1.11 1999/05/30 10:50:57 dfr Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -75,6 +75,8 @@ static struct rman irq_rman, drq_rman, port_rman, mem_rman;
|
||||
|
||||
static int nexus_probe(device_t);
|
||||
static void nexus_print_child(device_t, device_t);
|
||||
static device_t nexus_add_child(device_t bus, int order, const char *name,
|
||||
int unit);
|
||||
static struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
|
||||
u_long, u_long, u_long, u_int);
|
||||
static int nexus_activate_resource(device_t, device_t, int, int,
|
||||
@ -99,6 +101,7 @@ static device_method_t nexus_methods[] = {
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_print_child, nexus_print_child),
|
||||
DEVMETHOD(bus_add_child, nexus_add_child),
|
||||
DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
|
||||
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
|
||||
@ -192,9 +195,12 @@ nexus_probe(device_t dev)
|
||||
if (child == 0)
|
||||
panic("nexus_probe apm");
|
||||
|
||||
bus_generic_probe(dev);
|
||||
#if 0
|
||||
child = device_add_child(dev, "pcib", 0, 0);
|
||||
if (child == 0)
|
||||
panic("nexus_probe pcib");
|
||||
#endif
|
||||
|
||||
child = device_add_child(dev, "eisa", 0, 0);
|
||||
if (child == 0)
|
||||
@ -213,6 +219,12 @@ nexus_print_child(device_t bus, device_t child)
|
||||
printf(" on motherboard");
|
||||
}
|
||||
|
||||
static device_t
|
||||
nexus_add_child(device_t bus, int order, const char *name, int unit)
|
||||
{
|
||||
return device_add_child_ordered(bus, order, name, unit, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a resource on behalf of child. NB: child is usually going to be a
|
||||
* child of one of our descendants, not a direct child of nexus0.
|
||||
|
@ -26,7 +26,7 @@
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: nexus.c,v 1.10 1999/05/18 20:48:41 peter Exp $
|
||||
* $Id: nexus.c,v 1.11 1999/05/30 10:50:57 dfr Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -75,6 +75,8 @@ static struct rman irq_rman, drq_rman, port_rman, mem_rman;
|
||||
|
||||
static int nexus_probe(device_t);
|
||||
static void nexus_print_child(device_t, device_t);
|
||||
static device_t nexus_add_child(device_t bus, int order, const char *name,
|
||||
int unit);
|
||||
static struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
|
||||
u_long, u_long, u_long, u_int);
|
||||
static int nexus_activate_resource(device_t, device_t, int, int,
|
||||
@ -99,6 +101,7 @@ static device_method_t nexus_methods[] = {
|
||||
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_print_child, nexus_print_child),
|
||||
DEVMETHOD(bus_add_child, nexus_add_child),
|
||||
DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
|
||||
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
|
||||
@ -192,9 +195,12 @@ nexus_probe(device_t dev)
|
||||
if (child == 0)
|
||||
panic("nexus_probe apm");
|
||||
|
||||
bus_generic_probe(dev);
|
||||
#if 0
|
||||
child = device_add_child(dev, "pcib", 0, 0);
|
||||
if (child == 0)
|
||||
panic("nexus_probe pcib");
|
||||
#endif
|
||||
|
||||
child = device_add_child(dev, "eisa", 0, 0);
|
||||
if (child == 0)
|
||||
@ -213,6 +219,12 @@ nexus_print_child(device_t bus, device_t child)
|
||||
printf(" on motherboard");
|
||||
}
|
||||
|
||||
static device_t
|
||||
nexus_add_child(device_t bus, int order, const char *name, int unit)
|
||||
{
|
||||
return device_add_child_ordered(bus, order, name, unit, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a resource on behalf of child. NB: child is usually going to be a
|
||||
* child of one of our descendants, not a direct child of nexus0.
|
||||
|
@ -23,7 +23,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: pcibus.c,v 1.41 1997/12/20 09:04:25 se Exp $
|
||||
* $Id: pcibus.c,v 1.42 1999/05/18 20:48:43 peter Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
#include <i386/isa/pcibus.h>
|
||||
|
||||
#ifdef PCI_COMPAT
|
||||
@ -268,13 +269,187 @@ pci_cfgopen(void)
|
||||
|
||||
static devclass_t pcib_devclass;
|
||||
|
||||
static const char *
|
||||
nexus_pcib_is_host_bridge(pcicfgregs *cfg,
|
||||
u_int32_t id, u_int8_t class, u_int8_t subclass,
|
||||
u_int8_t *busnum)
|
||||
{
|
||||
const char *s = "Host to PCI bridge";
|
||||
static u_int8_t pxb[4]; /* hack for 450nx */
|
||||
|
||||
if (class != PCIC_BRIDGE || subclass != PCIS_BRIDGE_HOST)
|
||||
return NULL;
|
||||
|
||||
*busnum = 0;
|
||||
|
||||
switch (id) {
|
||||
case 0x12258086:
|
||||
s = "Intel 824?? host to PCI bridge";
|
||||
/* XXX This is a guess */
|
||||
*busnum = pci_cfgread(cfg, 0x41, 1);
|
||||
break;
|
||||
case 0x71808086:
|
||||
s = "Intel 82443LX (440 LX) host to PCI bridge";
|
||||
break;
|
||||
case 0x71908086:
|
||||
s = "Intel 82443BX (440 BX) host to PCI bridge";
|
||||
break;
|
||||
case 0x71928086:
|
||||
s = "Intel 82443BX host to PCI bridge (AGP disabled)";
|
||||
break;
|
||||
case 0x71a08086:
|
||||
s = "Intel 82443GX host to PCI bridge";
|
||||
break;
|
||||
case 0x71a18086:
|
||||
s = "Intel 82443GX host to AGP bridge";
|
||||
break;
|
||||
case 0x71a28086:
|
||||
s = "Intel 82443GX host to PCI bridge (AGP disabled)";
|
||||
break;
|
||||
case 0x84c48086:
|
||||
s = "Intel 82454KX/GX (Orion) host to PCI bridge";
|
||||
*busnum = pci_cfgread(cfg, 0x4a, 1);
|
||||
break;
|
||||
case 0x84ca8086:
|
||||
/*
|
||||
* For the 450nx chipset, there is a whole bundle of
|
||||
* things pretending to be host bridges. The MIOC will
|
||||
* be seen first and isn't really a pci bridge (the
|
||||
* actual busses are attached to the PXB's). We need to
|
||||
* read the registers of the MIOC to figure out the
|
||||
* bus numbers for the PXB channels.
|
||||
*
|
||||
* Since the MIOC doesn't have a pci bus attached, we
|
||||
* pretend it wasn't there.
|
||||
*/
|
||||
pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
|
||||
pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
|
||||
pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
|
||||
pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
|
||||
return NULL;
|
||||
case 0x84cb8086:
|
||||
switch (cfg->slot) {
|
||||
case 0x12:
|
||||
s = "Intel 82454NX PXB#0, Bus#A";
|
||||
*busnum = pxb[0];
|
||||
break;
|
||||
case 0x13:
|
||||
s = "Intel 82454NX PXB#0, Bus#B";
|
||||
*busnum = pxb[1];
|
||||
break;
|
||||
case 0x14:
|
||||
s = "Intel 82454NX PXB#1, Bus#A";
|
||||
*busnum = pxb[2];
|
||||
break;
|
||||
case 0x15:
|
||||
s = "Intel 82454NX PXB#1, Bus#B";
|
||||
*busnum = pxb[3];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* SiS -- vendor 0x1039 */
|
||||
case 0x04961039:
|
||||
s = "SiS 85c496";
|
||||
break;
|
||||
case 0x04061039:
|
||||
s = "SiS 85c501";
|
||||
break;
|
||||
case 0x06011039:
|
||||
s = "SiS 85c601";
|
||||
break;
|
||||
case 0x55911039:
|
||||
s = "SiS 5591 host to PCI bridge";
|
||||
break;
|
||||
case 0x00011039:
|
||||
s = "SiS 5591 host to AGP bridge";
|
||||
break;
|
||||
|
||||
/* VLSI -- vendor 0x1004 */
|
||||
case 0x00051004:
|
||||
s = "VLSI 82C592 Host to PCI bridge";
|
||||
break;
|
||||
|
||||
/* XXX Here is MVP3, I got the datasheet but NO M/B to test it */
|
||||
/* totally. Please let me know if anything wrong. -F */
|
||||
/* XXX need info on the MVP3 -- any takers? */
|
||||
case 0x05981106:
|
||||
s = "VIA 82C598MVP (Apollo MVP3) host bridge";
|
||||
break;
|
||||
|
||||
/* AcerLabs -- vendor 0x10b9 */
|
||||
/* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
|
||||
/* id is '10b9" but the register always shows "10b9". -Foxfair */
|
||||
case 0x154110b9:
|
||||
s = "AcerLabs M1541 (Aladdin-V) PCI host bridge";
|
||||
break;
|
||||
|
||||
/* OPTi -- vendor 0x1045 */
|
||||
case 0xc8221045:
|
||||
s = "OPTi 82C822 host to PCI Bridge";
|
||||
break;
|
||||
|
||||
/* Ross (?) -- vendor 0x1166 */
|
||||
case 0x00051166:
|
||||
s = "Ross (?) host to PCI bridge";
|
||||
/* just guessing the secondary bus register number ... */
|
||||
*busnum = pci_cfgread(cfg, 0x45, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the first pci bus for host-pci bridges and add pcib instances
|
||||
* to the nexus for each bridge.
|
||||
*/
|
||||
static void
|
||||
nexus_pcib_identify(driver_t *driver, device_t parent)
|
||||
{
|
||||
pcicfgregs probe;
|
||||
|
||||
probe.hose = 0;
|
||||
probe.bus = 0;
|
||||
|
||||
pci_cfgopen();
|
||||
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
|
||||
int pcifunchigh = 0;
|
||||
for (probe.func = 0;
|
||||
probe.func <= pcifunchigh;
|
||||
probe.func++) {
|
||||
/*
|
||||
* Read the IDs and class from the device.
|
||||
*/
|
||||
u_int32_t id;
|
||||
u_int8_t class, subclass, busnum;
|
||||
device_t child;
|
||||
const char *s;
|
||||
|
||||
id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
|
||||
if (id == -1)
|
||||
continue;
|
||||
class = pci_cfgread(&probe, PCIR_CLASS, 1);
|
||||
subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
|
||||
|
||||
s = nexus_pcib_is_host_bridge(&probe, id,
|
||||
class, subclass,
|
||||
&busnum);
|
||||
if (s) {
|
||||
child = BUS_ADD_CHILD(parent, 0,
|
||||
"pcib", busnum);
|
||||
device_set_desc(child, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_pcib_probe(device_t dev)
|
||||
{
|
||||
if (pci_cfgopen() != 0) {
|
||||
device_set_desc(dev, "PCI host bus adapter");
|
||||
|
||||
device_add_child(dev, "pci", 0, 0);
|
||||
device_add_child(dev, "pci", device_get_unit(dev), 0);
|
||||
return 0;
|
||||
}
|
||||
return ENXIO;
|
||||
@ -282,6 +457,7 @@ nexus_pcib_probe(device_t dev)
|
||||
|
||||
static device_method_t nexus_pcib_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_identify, nexus_pcib_identify),
|
||||
DEVMETHOD(device_probe, nexus_pcib_probe),
|
||||
DEVMETHOD(device_attach, bus_generic_attach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
|
@ -23,7 +23,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: pcibus.c,v 1.41 1997/12/20 09:04:25 se Exp $
|
||||
* $Id: pcibus.c,v 1.42 1999/05/18 20:48:43 peter Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
#include <i386/isa/pcibus.h>
|
||||
|
||||
#ifdef PCI_COMPAT
|
||||
@ -268,13 +269,187 @@ pci_cfgopen(void)
|
||||
|
||||
static devclass_t pcib_devclass;
|
||||
|
||||
static const char *
|
||||
nexus_pcib_is_host_bridge(pcicfgregs *cfg,
|
||||
u_int32_t id, u_int8_t class, u_int8_t subclass,
|
||||
u_int8_t *busnum)
|
||||
{
|
||||
const char *s = "Host to PCI bridge";
|
||||
static u_int8_t pxb[4]; /* hack for 450nx */
|
||||
|
||||
if (class != PCIC_BRIDGE || subclass != PCIS_BRIDGE_HOST)
|
||||
return NULL;
|
||||
|
||||
*busnum = 0;
|
||||
|
||||
switch (id) {
|
||||
case 0x12258086:
|
||||
s = "Intel 824?? host to PCI bridge";
|
||||
/* XXX This is a guess */
|
||||
*busnum = pci_cfgread(cfg, 0x41, 1);
|
||||
break;
|
||||
case 0x71808086:
|
||||
s = "Intel 82443LX (440 LX) host to PCI bridge";
|
||||
break;
|
||||
case 0x71908086:
|
||||
s = "Intel 82443BX (440 BX) host to PCI bridge";
|
||||
break;
|
||||
case 0x71928086:
|
||||
s = "Intel 82443BX host to PCI bridge (AGP disabled)";
|
||||
break;
|
||||
case 0x71a08086:
|
||||
s = "Intel 82443GX host to PCI bridge";
|
||||
break;
|
||||
case 0x71a18086:
|
||||
s = "Intel 82443GX host to AGP bridge";
|
||||
break;
|
||||
case 0x71a28086:
|
||||
s = "Intel 82443GX host to PCI bridge (AGP disabled)";
|
||||
break;
|
||||
case 0x84c48086:
|
||||
s = "Intel 82454KX/GX (Orion) host to PCI bridge";
|
||||
*busnum = pci_cfgread(cfg, 0x4a, 1);
|
||||
break;
|
||||
case 0x84ca8086:
|
||||
/*
|
||||
* For the 450nx chipset, there is a whole bundle of
|
||||
* things pretending to be host bridges. The MIOC will
|
||||
* be seen first and isn't really a pci bridge (the
|
||||
* actual busses are attached to the PXB's). We need to
|
||||
* read the registers of the MIOC to figure out the
|
||||
* bus numbers for the PXB channels.
|
||||
*
|
||||
* Since the MIOC doesn't have a pci bus attached, we
|
||||
* pretend it wasn't there.
|
||||
*/
|
||||
pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
|
||||
pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
|
||||
pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
|
||||
pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
|
||||
return NULL;
|
||||
case 0x84cb8086:
|
||||
switch (cfg->slot) {
|
||||
case 0x12:
|
||||
s = "Intel 82454NX PXB#0, Bus#A";
|
||||
*busnum = pxb[0];
|
||||
break;
|
||||
case 0x13:
|
||||
s = "Intel 82454NX PXB#0, Bus#B";
|
||||
*busnum = pxb[1];
|
||||
break;
|
||||
case 0x14:
|
||||
s = "Intel 82454NX PXB#1, Bus#A";
|
||||
*busnum = pxb[2];
|
||||
break;
|
||||
case 0x15:
|
||||
s = "Intel 82454NX PXB#1, Bus#B";
|
||||
*busnum = pxb[3];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* SiS -- vendor 0x1039 */
|
||||
case 0x04961039:
|
||||
s = "SiS 85c496";
|
||||
break;
|
||||
case 0x04061039:
|
||||
s = "SiS 85c501";
|
||||
break;
|
||||
case 0x06011039:
|
||||
s = "SiS 85c601";
|
||||
break;
|
||||
case 0x55911039:
|
||||
s = "SiS 5591 host to PCI bridge";
|
||||
break;
|
||||
case 0x00011039:
|
||||
s = "SiS 5591 host to AGP bridge";
|
||||
break;
|
||||
|
||||
/* VLSI -- vendor 0x1004 */
|
||||
case 0x00051004:
|
||||
s = "VLSI 82C592 Host to PCI bridge";
|
||||
break;
|
||||
|
||||
/* XXX Here is MVP3, I got the datasheet but NO M/B to test it */
|
||||
/* totally. Please let me know if anything wrong. -F */
|
||||
/* XXX need info on the MVP3 -- any takers? */
|
||||
case 0x05981106:
|
||||
s = "VIA 82C598MVP (Apollo MVP3) host bridge";
|
||||
break;
|
||||
|
||||
/* AcerLabs -- vendor 0x10b9 */
|
||||
/* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
|
||||
/* id is '10b9" but the register always shows "10b9". -Foxfair */
|
||||
case 0x154110b9:
|
||||
s = "AcerLabs M1541 (Aladdin-V) PCI host bridge";
|
||||
break;
|
||||
|
||||
/* OPTi -- vendor 0x1045 */
|
||||
case 0xc8221045:
|
||||
s = "OPTi 82C822 host to PCI Bridge";
|
||||
break;
|
||||
|
||||
/* Ross (?) -- vendor 0x1166 */
|
||||
case 0x00051166:
|
||||
s = "Ross (?) host to PCI bridge";
|
||||
/* just guessing the secondary bus register number ... */
|
||||
*busnum = pci_cfgread(cfg, 0x45, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the first pci bus for host-pci bridges and add pcib instances
|
||||
* to the nexus for each bridge.
|
||||
*/
|
||||
static void
|
||||
nexus_pcib_identify(driver_t *driver, device_t parent)
|
||||
{
|
||||
pcicfgregs probe;
|
||||
|
||||
probe.hose = 0;
|
||||
probe.bus = 0;
|
||||
|
||||
pci_cfgopen();
|
||||
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
|
||||
int pcifunchigh = 0;
|
||||
for (probe.func = 0;
|
||||
probe.func <= pcifunchigh;
|
||||
probe.func++) {
|
||||
/*
|
||||
* Read the IDs and class from the device.
|
||||
*/
|
||||
u_int32_t id;
|
||||
u_int8_t class, subclass, busnum;
|
||||
device_t child;
|
||||
const char *s;
|
||||
|
||||
id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
|
||||
if (id == -1)
|
||||
continue;
|
||||
class = pci_cfgread(&probe, PCIR_CLASS, 1);
|
||||
subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
|
||||
|
||||
s = nexus_pcib_is_host_bridge(&probe, id,
|
||||
class, subclass,
|
||||
&busnum);
|
||||
if (s) {
|
||||
child = BUS_ADD_CHILD(parent, 0,
|
||||
"pcib", busnum);
|
||||
device_set_desc(child, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_pcib_probe(device_t dev)
|
||||
{
|
||||
if (pci_cfgopen() != 0) {
|
||||
device_set_desc(dev, "PCI host bus adapter");
|
||||
|
||||
device_add_child(dev, "pci", 0, 0);
|
||||
device_add_child(dev, "pci", device_get_unit(dev), 0);
|
||||
return 0;
|
||||
}
|
||||
return ENXIO;
|
||||
@ -282,6 +457,7 @@ nexus_pcib_probe(device_t dev)
|
||||
|
||||
static device_method_t nexus_pcib_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_identify, nexus_pcib_identify),
|
||||
DEVMETHOD(device_probe, nexus_pcib_probe),
|
||||
DEVMETHOD(device_attach, bus_generic_attach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
|
@ -23,7 +23,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: pcibus.c,v 1.41 1997/12/20 09:04:25 se Exp $
|
||||
* $Id: pcibus.c,v 1.42 1999/05/18 20:48:43 peter Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
#include <i386/isa/pcibus.h>
|
||||
|
||||
#ifdef PCI_COMPAT
|
||||
@ -268,13 +269,187 @@ pci_cfgopen(void)
|
||||
|
||||
static devclass_t pcib_devclass;
|
||||
|
||||
static const char *
|
||||
nexus_pcib_is_host_bridge(pcicfgregs *cfg,
|
||||
u_int32_t id, u_int8_t class, u_int8_t subclass,
|
||||
u_int8_t *busnum)
|
||||
{
|
||||
const char *s = "Host to PCI bridge";
|
||||
static u_int8_t pxb[4]; /* hack for 450nx */
|
||||
|
||||
if (class != PCIC_BRIDGE || subclass != PCIS_BRIDGE_HOST)
|
||||
return NULL;
|
||||
|
||||
*busnum = 0;
|
||||
|
||||
switch (id) {
|
||||
case 0x12258086:
|
||||
s = "Intel 824?? host to PCI bridge";
|
||||
/* XXX This is a guess */
|
||||
*busnum = pci_cfgread(cfg, 0x41, 1);
|
||||
break;
|
||||
case 0x71808086:
|
||||
s = "Intel 82443LX (440 LX) host to PCI bridge";
|
||||
break;
|
||||
case 0x71908086:
|
||||
s = "Intel 82443BX (440 BX) host to PCI bridge";
|
||||
break;
|
||||
case 0x71928086:
|
||||
s = "Intel 82443BX host to PCI bridge (AGP disabled)";
|
||||
break;
|
||||
case 0x71a08086:
|
||||
s = "Intel 82443GX host to PCI bridge";
|
||||
break;
|
||||
case 0x71a18086:
|
||||
s = "Intel 82443GX host to AGP bridge";
|
||||
break;
|
||||
case 0x71a28086:
|
||||
s = "Intel 82443GX host to PCI bridge (AGP disabled)";
|
||||
break;
|
||||
case 0x84c48086:
|
||||
s = "Intel 82454KX/GX (Orion) host to PCI bridge";
|
||||
*busnum = pci_cfgread(cfg, 0x4a, 1);
|
||||
break;
|
||||
case 0x84ca8086:
|
||||
/*
|
||||
* For the 450nx chipset, there is a whole bundle of
|
||||
* things pretending to be host bridges. The MIOC will
|
||||
* be seen first and isn't really a pci bridge (the
|
||||
* actual busses are attached to the PXB's). We need to
|
||||
* read the registers of the MIOC to figure out the
|
||||
* bus numbers for the PXB channels.
|
||||
*
|
||||
* Since the MIOC doesn't have a pci bus attached, we
|
||||
* pretend it wasn't there.
|
||||
*/
|
||||
pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
|
||||
pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
|
||||
pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
|
||||
pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
|
||||
return NULL;
|
||||
case 0x84cb8086:
|
||||
switch (cfg->slot) {
|
||||
case 0x12:
|
||||
s = "Intel 82454NX PXB#0, Bus#A";
|
||||
*busnum = pxb[0];
|
||||
break;
|
||||
case 0x13:
|
||||
s = "Intel 82454NX PXB#0, Bus#B";
|
||||
*busnum = pxb[1];
|
||||
break;
|
||||
case 0x14:
|
||||
s = "Intel 82454NX PXB#1, Bus#A";
|
||||
*busnum = pxb[2];
|
||||
break;
|
||||
case 0x15:
|
||||
s = "Intel 82454NX PXB#1, Bus#B";
|
||||
*busnum = pxb[3];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* SiS -- vendor 0x1039 */
|
||||
case 0x04961039:
|
||||
s = "SiS 85c496";
|
||||
break;
|
||||
case 0x04061039:
|
||||
s = "SiS 85c501";
|
||||
break;
|
||||
case 0x06011039:
|
||||
s = "SiS 85c601";
|
||||
break;
|
||||
case 0x55911039:
|
||||
s = "SiS 5591 host to PCI bridge";
|
||||
break;
|
||||
case 0x00011039:
|
||||
s = "SiS 5591 host to AGP bridge";
|
||||
break;
|
||||
|
||||
/* VLSI -- vendor 0x1004 */
|
||||
case 0x00051004:
|
||||
s = "VLSI 82C592 Host to PCI bridge";
|
||||
break;
|
||||
|
||||
/* XXX Here is MVP3, I got the datasheet but NO M/B to test it */
|
||||
/* totally. Please let me know if anything wrong. -F */
|
||||
/* XXX need info on the MVP3 -- any takers? */
|
||||
case 0x05981106:
|
||||
s = "VIA 82C598MVP (Apollo MVP3) host bridge";
|
||||
break;
|
||||
|
||||
/* AcerLabs -- vendor 0x10b9 */
|
||||
/* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
|
||||
/* id is '10b9" but the register always shows "10b9". -Foxfair */
|
||||
case 0x154110b9:
|
||||
s = "AcerLabs M1541 (Aladdin-V) PCI host bridge";
|
||||
break;
|
||||
|
||||
/* OPTi -- vendor 0x1045 */
|
||||
case 0xc8221045:
|
||||
s = "OPTi 82C822 host to PCI Bridge";
|
||||
break;
|
||||
|
||||
/* Ross (?) -- vendor 0x1166 */
|
||||
case 0x00051166:
|
||||
s = "Ross (?) host to PCI bridge";
|
||||
/* just guessing the secondary bus register number ... */
|
||||
*busnum = pci_cfgread(cfg, 0x45, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the first pci bus for host-pci bridges and add pcib instances
|
||||
* to the nexus for each bridge.
|
||||
*/
|
||||
static void
|
||||
nexus_pcib_identify(driver_t *driver, device_t parent)
|
||||
{
|
||||
pcicfgregs probe;
|
||||
|
||||
probe.hose = 0;
|
||||
probe.bus = 0;
|
||||
|
||||
pci_cfgopen();
|
||||
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
|
||||
int pcifunchigh = 0;
|
||||
for (probe.func = 0;
|
||||
probe.func <= pcifunchigh;
|
||||
probe.func++) {
|
||||
/*
|
||||
* Read the IDs and class from the device.
|
||||
*/
|
||||
u_int32_t id;
|
||||
u_int8_t class, subclass, busnum;
|
||||
device_t child;
|
||||
const char *s;
|
||||
|
||||
id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
|
||||
if (id == -1)
|
||||
continue;
|
||||
class = pci_cfgread(&probe, PCIR_CLASS, 1);
|
||||
subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
|
||||
|
||||
s = nexus_pcib_is_host_bridge(&probe, id,
|
||||
class, subclass,
|
||||
&busnum);
|
||||
if (s) {
|
||||
child = BUS_ADD_CHILD(parent, 0,
|
||||
"pcib", busnum);
|
||||
device_set_desc(child, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_pcib_probe(device_t dev)
|
||||
{
|
||||
if (pci_cfgopen() != 0) {
|
||||
device_set_desc(dev, "PCI host bus adapter");
|
||||
|
||||
device_add_child(dev, "pci", 0, 0);
|
||||
device_add_child(dev, "pci", device_get_unit(dev), 0);
|
||||
return 0;
|
||||
}
|
||||
return ENXIO;
|
||||
@ -282,6 +457,7 @@ nexus_pcib_probe(device_t dev)
|
||||
|
||||
static device_method_t nexus_pcib_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_identify, nexus_pcib_identify),
|
||||
DEVMETHOD(device_probe, nexus_pcib_probe),
|
||||
DEVMETHOD(device_attach, bus_generic_attach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
|
@ -23,7 +23,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: pcibus.c,v 1.41 1997/12/20 09:04:25 se Exp $
|
||||
* $Id: pcibus.c,v 1.42 1999/05/18 20:48:43 peter Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <pci/pcivar.h>
|
||||
#include <pci/pcireg.h>
|
||||
#include <i386/isa/pcibus.h>
|
||||
|
||||
#ifdef PCI_COMPAT
|
||||
@ -268,13 +269,187 @@ pci_cfgopen(void)
|
||||
|
||||
static devclass_t pcib_devclass;
|
||||
|
||||
static const char *
|
||||
nexus_pcib_is_host_bridge(pcicfgregs *cfg,
|
||||
u_int32_t id, u_int8_t class, u_int8_t subclass,
|
||||
u_int8_t *busnum)
|
||||
{
|
||||
const char *s = "Host to PCI bridge";
|
||||
static u_int8_t pxb[4]; /* hack for 450nx */
|
||||
|
||||
if (class != PCIC_BRIDGE || subclass != PCIS_BRIDGE_HOST)
|
||||
return NULL;
|
||||
|
||||
*busnum = 0;
|
||||
|
||||
switch (id) {
|
||||
case 0x12258086:
|
||||
s = "Intel 824?? host to PCI bridge";
|
||||
/* XXX This is a guess */
|
||||
*busnum = pci_cfgread(cfg, 0x41, 1);
|
||||
break;
|
||||
case 0x71808086:
|
||||
s = "Intel 82443LX (440 LX) host to PCI bridge";
|
||||
break;
|
||||
case 0x71908086:
|
||||
s = "Intel 82443BX (440 BX) host to PCI bridge";
|
||||
break;
|
||||
case 0x71928086:
|
||||
s = "Intel 82443BX host to PCI bridge (AGP disabled)";
|
||||
break;
|
||||
case 0x71a08086:
|
||||
s = "Intel 82443GX host to PCI bridge";
|
||||
break;
|
||||
case 0x71a18086:
|
||||
s = "Intel 82443GX host to AGP bridge";
|
||||
break;
|
||||
case 0x71a28086:
|
||||
s = "Intel 82443GX host to PCI bridge (AGP disabled)";
|
||||
break;
|
||||
case 0x84c48086:
|
||||
s = "Intel 82454KX/GX (Orion) host to PCI bridge";
|
||||
*busnum = pci_cfgread(cfg, 0x4a, 1);
|
||||
break;
|
||||
case 0x84ca8086:
|
||||
/*
|
||||
* For the 450nx chipset, there is a whole bundle of
|
||||
* things pretending to be host bridges. The MIOC will
|
||||
* be seen first and isn't really a pci bridge (the
|
||||
* actual busses are attached to the PXB's). We need to
|
||||
* read the registers of the MIOC to figure out the
|
||||
* bus numbers for the PXB channels.
|
||||
*
|
||||
* Since the MIOC doesn't have a pci bus attached, we
|
||||
* pretend it wasn't there.
|
||||
*/
|
||||
pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
|
||||
pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
|
||||
pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
|
||||
pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
|
||||
return NULL;
|
||||
case 0x84cb8086:
|
||||
switch (cfg->slot) {
|
||||
case 0x12:
|
||||
s = "Intel 82454NX PXB#0, Bus#A";
|
||||
*busnum = pxb[0];
|
||||
break;
|
||||
case 0x13:
|
||||
s = "Intel 82454NX PXB#0, Bus#B";
|
||||
*busnum = pxb[1];
|
||||
break;
|
||||
case 0x14:
|
||||
s = "Intel 82454NX PXB#1, Bus#A";
|
||||
*busnum = pxb[2];
|
||||
break;
|
||||
case 0x15:
|
||||
s = "Intel 82454NX PXB#1, Bus#B";
|
||||
*busnum = pxb[3];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* SiS -- vendor 0x1039 */
|
||||
case 0x04961039:
|
||||
s = "SiS 85c496";
|
||||
break;
|
||||
case 0x04061039:
|
||||
s = "SiS 85c501";
|
||||
break;
|
||||
case 0x06011039:
|
||||
s = "SiS 85c601";
|
||||
break;
|
||||
case 0x55911039:
|
||||
s = "SiS 5591 host to PCI bridge";
|
||||
break;
|
||||
case 0x00011039:
|
||||
s = "SiS 5591 host to AGP bridge";
|
||||
break;
|
||||
|
||||
/* VLSI -- vendor 0x1004 */
|
||||
case 0x00051004:
|
||||
s = "VLSI 82C592 Host to PCI bridge";
|
||||
break;
|
||||
|
||||
/* XXX Here is MVP3, I got the datasheet but NO M/B to test it */
|
||||
/* totally. Please let me know if anything wrong. -F */
|
||||
/* XXX need info on the MVP3 -- any takers? */
|
||||
case 0x05981106:
|
||||
s = "VIA 82C598MVP (Apollo MVP3) host bridge";
|
||||
break;
|
||||
|
||||
/* AcerLabs -- vendor 0x10b9 */
|
||||
/* Funny : The datasheet told me vendor id is "10b8",sub-vendor */
|
||||
/* id is '10b9" but the register always shows "10b9". -Foxfair */
|
||||
case 0x154110b9:
|
||||
s = "AcerLabs M1541 (Aladdin-V) PCI host bridge";
|
||||
break;
|
||||
|
||||
/* OPTi -- vendor 0x1045 */
|
||||
case 0xc8221045:
|
||||
s = "OPTi 82C822 host to PCI Bridge";
|
||||
break;
|
||||
|
||||
/* Ross (?) -- vendor 0x1166 */
|
||||
case 0x00051166:
|
||||
s = "Ross (?) host to PCI bridge";
|
||||
/* just guessing the secondary bus register number ... */
|
||||
*busnum = pci_cfgread(cfg, 0x45, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the first pci bus for host-pci bridges and add pcib instances
|
||||
* to the nexus for each bridge.
|
||||
*/
|
||||
static void
|
||||
nexus_pcib_identify(driver_t *driver, device_t parent)
|
||||
{
|
||||
pcicfgregs probe;
|
||||
|
||||
probe.hose = 0;
|
||||
probe.bus = 0;
|
||||
|
||||
pci_cfgopen();
|
||||
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
|
||||
int pcifunchigh = 0;
|
||||
for (probe.func = 0;
|
||||
probe.func <= pcifunchigh;
|
||||
probe.func++) {
|
||||
/*
|
||||
* Read the IDs and class from the device.
|
||||
*/
|
||||
u_int32_t id;
|
||||
u_int8_t class, subclass, busnum;
|
||||
device_t child;
|
||||
const char *s;
|
||||
|
||||
id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
|
||||
if (id == -1)
|
||||
continue;
|
||||
class = pci_cfgread(&probe, PCIR_CLASS, 1);
|
||||
subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
|
||||
|
||||
s = nexus_pcib_is_host_bridge(&probe, id,
|
||||
class, subclass,
|
||||
&busnum);
|
||||
if (s) {
|
||||
child = BUS_ADD_CHILD(parent, 0,
|
||||
"pcib", busnum);
|
||||
device_set_desc(child, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_pcib_probe(device_t dev)
|
||||
{
|
||||
if (pci_cfgopen() != 0) {
|
||||
device_set_desc(dev, "PCI host bus adapter");
|
||||
|
||||
device_add_child(dev, "pci", 0, 0);
|
||||
device_add_child(dev, "pci", device_get_unit(dev), 0);
|
||||
return 0;
|
||||
}
|
||||
return ENXIO;
|
||||
@ -282,6 +457,7 @@ nexus_pcib_probe(device_t dev)
|
||||
|
||||
static device_method_t nexus_pcib_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_identify, nexus_pcib_identify),
|
||||
DEVMETHOD(device_probe, nexus_pcib_probe),
|
||||
DEVMETHOD(device_attach, bus_generic_attach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** $Id: pcisupport.c,v 1.121 1999/06/16 12:26:40 billf Exp $
|
||||
** $Id: pcisupport.c,v 1.122 1999/06/24 04:06:26 jlemon Exp $
|
||||
**
|
||||
** Device driver for DEC/INTEL PCI chipsets.
|
||||
**
|
||||
@ -75,19 +75,6 @@ struct condmsg {
|
||||
const char *text;
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX Both fixbushigh_orion() and fixbushigh_i1225() are bogus in that way,
|
||||
* that they store the highest bus number to scan in this device's config
|
||||
* data, though it is about PCI buses attached to the CPU independently!
|
||||
* The same goes for fixbushigh_450nx.
|
||||
*/
|
||||
|
||||
static void
|
||||
fixbushigh_orion(device_t dev)
|
||||
{
|
||||
pci_set_secondarybus(dev, pci_read_config(dev, 0x4a, 1));
|
||||
pci_set_subordinatebus(dev, pci_read_config(dev, 0x4b, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
fixbushigh_i1225(device_t dev)
|
||||
@ -101,81 +88,6 @@ fixbushigh_i1225(device_t dev)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This reads the PCI config space for the 82451NX MIOC in the 450NX
|
||||
* chipset to determine the PCI bus configuration.
|
||||
*
|
||||
* Assuming the BIOS has set up the MIOC properly, this will correctly
|
||||
* report the number of PCI busses in the system.
|
||||
*
|
||||
* A small problem is that the Host to PCI bridge control is in the MIOC,
|
||||
* while the host-pci bridges are separate PCI devices. So it really
|
||||
* isn't easily possible to set up the subordinatebus mappings as the
|
||||
* 82454NX PCI expander bridges are probed, although that makes the
|
||||
* most sense.
|
||||
*/
|
||||
static void
|
||||
fixbushigh_450nx(device_t dev)
|
||||
{
|
||||
int subordinatebus;
|
||||
unsigned long devmap;
|
||||
|
||||
/*
|
||||
* Read the DEVMAP field, so we know which fields to check.
|
||||
* If the Host-PCI bridge isn't marked as present by the BIOS,
|
||||
* we have to assume it doesn't exist.
|
||||
* If this doesn't find all the PCI busses, complain to the
|
||||
* BIOS vendor. There is nothing more we can do.
|
||||
*/
|
||||
devmap = pci_read_config(dev, 0xd6, 2) & 0x3c;
|
||||
if (!devmap)
|
||||
panic("450NX MIOC: No host to PCI bridges marked present.\n");
|
||||
/*
|
||||
* Since the buses are configured in order, we just have to
|
||||
* find the highest bus, and use those numbers.
|
||||
*/
|
||||
if (devmap & 0x20) { /* B1 */
|
||||
subordinatebus = pci_read_config(dev, 0xd5, 1);
|
||||
} else if (devmap & 0x10) { /* A1 */
|
||||
subordinatebus = pci_read_config(dev, 0xd4, 1);
|
||||
} else if (devmap & 0x8) { /* B0 */
|
||||
subordinatebus = pci_read_config(dev, 0xd2, 1);
|
||||
} else /* if (devmap & 0x4) */ { /* A0 */
|
||||
subordinatebus = pci_read_config(dev, 0xd1, 1);
|
||||
}
|
||||
if (subordinatebus == 255) {
|
||||
printf("fixbushigh_450nx: bogus highest PCI bus %d",
|
||||
subordinatebus);
|
||||
#ifdef NBUS
|
||||
subordinatebus = NBUS - 2;
|
||||
#else
|
||||
subordinatebus = 10;
|
||||
#endif
|
||||
printf(", reduced to %d\n", subordinatebus);
|
||||
}
|
||||
|
||||
if (bootverbose)
|
||||
printf("fixbushigh_450nx: subordinatebus is %d\n",
|
||||
subordinatebus);
|
||||
|
||||
pci_set_secondarybus(dev, subordinatebus);
|
||||
pci_set_subordinatebus(dev, subordinatebus);
|
||||
}
|
||||
|
||||
static void
|
||||
fixbushigh_Ross(device_t dev)
|
||||
{
|
||||
int secondarybus;
|
||||
|
||||
/* just guessing the secondary bus register number ... */
|
||||
secondarybus = pci_read_config(dev, 0x45, 1);
|
||||
if (secondarybus != 0 && secondarybus != 0xff) {
|
||||
pci_set_secondarybus(dev, secondarybus);
|
||||
pci_set_subordinatebus(dev, secondarybus);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fixwsc_natoma(device_t dev)
|
||||
{
|
||||
@ -806,6 +718,8 @@ pcib_match(device_t dev)
|
||||
return ("Intel 82443LX (440 LX) PCI-PCI (AGP) bridge");
|
||||
case 0x71918086:
|
||||
return ("Intel 82443BX (440 BX) PCI-PCI (AGP) bridge");
|
||||
case 0x71A18086:
|
||||
return ("Intel 82443GX (440 GX) PCI-PCI (AGP) bridge");
|
||||
case 0x84cb8086:
|
||||
return ("Intel 82454NX PCI Expander Bridge");
|
||||
case 0x124b8086:
|
||||
@ -834,11 +748,6 @@ pcib_match(device_t dev)
|
||||
return ("IBM 82351 PCI-PCI bridge");
|
||||
case 0x00011011:
|
||||
return ("DEC 21050 PCI-PCI bridge");
|
||||
|
||||
/* Ross (?) -- vendor 0x1166 */
|
||||
case 0x00051166:
|
||||
fixbushigh_Ross(dev);
|
||||
return ("Ross (?) host to PCI bridge");
|
||||
};
|
||||
|
||||
if (pci_get_class(dev) == PCIC_BRIDGE
|
||||
@ -1100,10 +1009,8 @@ chip_match(device_t dev)
|
||||
case 0x71a28086:
|
||||
return ("Intel 82443GX host to PCI bridge (AGP disabled)");
|
||||
case 0x84c48086:
|
||||
fixbushigh_orion(dev);
|
||||
return ("Intel 82454KX/GX (Orion) host to PCI bridge");
|
||||
case 0x84ca8086:
|
||||
fixbushigh_450nx(dev);
|
||||
return ("Intel 82451NX Memory and I/O controller");
|
||||
case 0x04868086:
|
||||
return ("Intel 82425EX PCI system controller");
|
||||
@ -1259,6 +1166,15 @@ static int chip_probe(device_t dev)
|
||||
if (desc == NULL)
|
||||
desc = ide_pci_match(dev);
|
||||
if (desc) {
|
||||
if (pci_get_class(dev) == PCIC_BRIDGE
|
||||
&& pci_get_subclass(dev) == PCIS_BRIDGE_HOST) {
|
||||
/*
|
||||
* Suppress printing this device since the nexus
|
||||
* has already described it.
|
||||
*/
|
||||
device_quiet(dev);
|
||||
}
|
||||
|
||||
device_set_desc_copy(dev, desc);
|
||||
return -100; /* Low match priority */
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user