* Split bandit and grackle.

* Add UniNorth support.

Now pcibus is attached like:
  bandit0 at mainbus0
  pci0 at bandit0 bus 0
  ...
This commit is contained in:
tsubai 2000-02-03 19:27:43 +00:00
parent b20e217bb8
commit e29a886cd6
12 changed files with 885 additions and 470 deletions

View File

@ -1,11 +1,11 @@
# $NetBSD: GENERIC,v 1.50 2000/01/25 14:43:49 tsubai Exp $
# $NetBSD: GENERIC,v 1.51 2000/02/03 19:27:43 tsubai Exp $
#
# GENERIC -- everything that's currently supported
#
include "arch/macppc/conf/std.macppc"
#ident "GENERIC-$Revision: 1.50 $"
#ident "GENERIC-$Revision: 1.51 $"
maxusers 32
@ -125,7 +125,11 @@ config netbsd root on ? type ?
mainbus* at root
cpu* at mainbus?
pci* at mainbus? bus ?
bandit* at mainbus?
grackle* at mainbus?
pci* at bandit? bus ?
pci* at grackle? bus ?
pci* at ppb? bus ?
pchb* at pci? dev ? function ? # PCI-Host bridges

View File

@ -1,4 +1,4 @@
# $NetBSD: INSTALL,v 1.19 2000/01/25 14:43:49 tsubai Exp $
# $NetBSD: INSTALL,v 1.20 2000/02/03 19:27:44 tsubai Exp $
#
# config file for INSTALL FLOPPY
#
@ -47,7 +47,11 @@ config netbsd root on ? type ?
mainbus* at root
cpu* at mainbus?
pci* at mainbus? bus ?
bandit* at mainbus?
grackle* at mainbus?
pci* at bandit? bus ?
pci* at grackle? bus ?
pci* at ppb? bus ?
pchb* at pci? dev ? function ? # PCI-Host bridges

View File

@ -1,4 +1,4 @@
# $NetBSD: POWERMAC,v 1.19 1999/07/29 10:37:19 augustss Exp $
# $NetBSD: POWERMAC,v 1.20 2000/02/03 19:27:44 tsubai Exp $
#
# POWERMAC config file
#
@ -58,7 +58,9 @@ config netbsd root on ? type ?
mainbus* at root
cpu* at mainbus?
pci* at mainbus? bus ?
bandit* at mainbus?
pci* at bandit? bus ?
pci* at ppb? bus ?
pchb* at pci? dev ? function ? # PCI-Host bridges

View File

@ -1,4 +1,4 @@
# $NetBSD: files.macppc,v 1.26 2000/01/25 14:38:39 tsubai Exp $
# $NetBSD: files.macppc,v 1.27 2000/02/03 19:27:44 tsubai Exp $
#
# macppc-specific configuration info
@ -48,7 +48,7 @@ major {wd = 10}
# System bus types
#
define mainbus {}
device mainbus: pcibus, mainbus
device mainbus: mainbus
attach mainbus at root
file arch/macppc/macppc/mainbus.c mainbus
@ -56,6 +56,20 @@ device cpu
attach cpu at mainbus
file arch/macppc/macppc/cpu.c
file arch/macppc/pci/pci_machdep.c pci
device bandit: pcibus
attach bandit at mainbus
file arch/macppc/pci/bandit.c bandit
device grackle: pcibus
attach grackle at mainbus
file arch/macppc/pci/grackle.c grackle
device uninorth: pcibus
attach uninorth at mainbus
file arch/macppc/pci/uninorth.c uninorth
# PCI bus support
include "dev/pci/files.pci"
@ -70,9 +84,6 @@ device ofb: wsemuldisplaydev, wsrasteremulops
attach ofb at pci
file arch/macppc/dev/ofb.c ofb needs-flag
file arch/macppc/pci/pci_machdep.c pci
file arch/macppc/pci/bandit.c pci
# PCI-Host bridge chipsets
device pchb
attach pchb at pci

View File

@ -1,4 +1,4 @@
/* $NetBSD: pci_machdep.h,v 1.9 2000/02/01 04:04:17 danw Exp $ */
/* $NetBSD: pci_machdep.h,v 1.10 2000/02/03 19:27:45 tsubai Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@ -47,24 +47,20 @@
/*
* Types provided to machine-independent PCI code
*/
typedef int pci_chipset_tag_t;
typedef struct pci_bridge *pci_chipset_tag_t;
typedef int pcitag_t;
typedef int pci_intr_handle_t;
struct pci_bridge {
int node;
u_int *addr;
u_int *data;
int bus;
bus_space_tag_t iot;
bus_space_tag_t memt;
pci_chipset_tag_t pc;
u_int reg[2];
int present;
bus_space_tag_t iot;
pcireg_t (*conf_read)();
void (*conf_write)();
};
struct pci_bridge pci_bridges[2];
#define PCI_CHIPSET_BANDIT 0x00
#define PCI_CHIPSET_MPC106 0x10
extern struct macppc_bus_dma_tag pci_bus_dma_tag;

View File

@ -1,4 +1,4 @@
/* $NetBSD: autoconf.c,v 1.17 2000/02/02 16:41:56 danw Exp $ */
/* $NetBSD: autoconf.c,v 1.18 2000/02/03 19:27:45 tsubai Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@ -137,7 +137,7 @@ device_register(dev, aux)
/* Skip over devices not represented in the OF tree. */
if (DEVICE_IS(dev, "mainbus") || DEVICE_IS(dev, "scsibus") ||
DEVICE_IS(dev, "atapibus") || DEVICE_IS(parent, "ppb")) {
DEVICE_IS(dev, "atapibus") || DEVICE_IS(dev, "pci")) {
parent = dev;
return;
}
@ -160,17 +160,11 @@ device_register(dev, aux)
} else
addr = strtoul(p + 1, &p, 16);
if (DEVICE_IS(parent, "mainbus") && DEVICE_IS(dev, "pci")) {
struct pcibus_attach_args *pba = aux;
int n, size = sizeof(pci_bridges) / sizeof(struct pci_bridge);
if (DEVICE_IS(dev, "bandit") || DEVICE_IS(dev, "grackle") ||
DEVICE_IS(dev, "uninorth")) {
struct confargs *ca = aux;
for (n = 0; n < size; n++) {
if (pci_bridges[n].present &&
pci_bridges[n].bus == pba->pba_bus &&
pci_bridges[n].reg[0] == addr)
break;
}
if (n == size)
if (addr != ca->ca_reg[0])
return;
} else if (DEVICE_IS(parent, "pci")) {
struct pci_attach_args *pa = aux;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mainbus.c,v 1.6 1999/05/06 19:16:44 thorpej Exp $ */
/* $NetBSD: mainbus.c,v 1.7 2000/02/03 19:27:45 tsubai Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@ -31,16 +31,14 @@
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <dev/pci/pcivar.h>
#include <dev/ofw/openfirm.h>
#include <machine/autoconf.h>
#include "pci.h"
int mainbus_match __P((struct device *, struct cfdata *, void *));
void mainbus_attach __P((struct device *, struct device *, void *));
int mainbus_print __P((void *, const char *));
@ -69,10 +67,11 @@ mainbus_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
struct pcibus_attach_args pba;
struct ofbus_attach_args oba;
struct confargs ca;
int node, n;
int node;
u_int32_t reg[4];
char name[32];
printf("\n");
@ -86,22 +85,16 @@ mainbus_attach(parent, self, aux)
ca.ca_name = "cpu";
config_found(self, &ca, NULL);
/* Now can map PCI configuration space registers. */
pci_init(1);
for (node = OF_child(OF_finddevice("/")); node; node = OF_peer(node)) {
bzero(name, sizeof(name));
if (OF_getprop(node, "name", name, sizeof(name)) == -1)
continue;
for (n = 0; n < 2; n++) {
if (pci_bridges[n].addr) {
bzero(&pba, sizeof(pba));
pba.pba_busname = "pci";
pba.pba_iot = pci_bridges[n].iot;
pba.pba_memt = pci_bridges[n].memt;
pba.pba_dmat = &pci_bus_dma_tag;
pba.pba_bus = pci_bridges[n].bus;
pba.pba_pc = pci_bridges[n].pc;
pba.pba_flags =
PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
config_found(self, &pba, mainbus_print);
}
ca.ca_name = name;
ca.ca_node = node;
ca.ca_nreg = OF_getprop(node, "reg", reg, sizeof(reg));
ca.ca_reg = reg;
config_found(self, &ca, NULL);
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: rbus_machdep.c,v 1.3 1999/12/18 01:37:00 thorpej Exp $ */
/* $NetBSD: rbus_machdep.c,v 1.4 2000/02/03 19:27:45 tsubai Exp $ */
/*
* Copyright (c) 1999
@ -41,6 +41,7 @@
#include <machine/bus.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <dev/cardbus/rbus.h>
static void macppc_cardbus_init __P((pci_chipset_tag_t, pcitag_t));
@ -133,7 +134,11 @@ macppc_cardbus_init(pc, tag)
return;
initted = 1;
if (pc == PCI_CHIPSET_MPC106) {
/* XXX What about other bridges? */
x = pci_conf_read(pc, tag, PCI_ID_REG);
if (PCI_VENDOR(x) == PCI_VENDOR_TI &&
PCI_PRODUCT(x) == PCI_PRODUCT_TI_PCI1211) {
/* For CardBus card. */
pci_conf_write(pc, tag, 0x18, 0x10010100);

View File

@ -1,12 +1,7 @@
/* $NetBSD: bandit.c,v 1.12 2000/02/01 04:04:18 danw Exp $ */
/* $NetBSD: bandit.c,v 1.13 2000/02/03 19:27:45 tsubai Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center.
* Copyright (c) 2000 Tsubai Masanari. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -16,355 +11,240 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright 1991-1998 by Open Software Foundation, Inc.
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both the copyright notice and this permission notice appear in
* supporting documentation.
*
* OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
* NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Copyright 1991-1998 by Apple Computer, Inc.
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both the copyright notice and this permission notice appear in
* supporting documentation.
*
* APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
* NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <machine/bus.h>
#include <machine/autoconf.h>
struct bandit_softc {
struct device sc_dev;
struct pci_bridge sc_pc;
};
void bandit_attach __P((struct device *, struct device *, void *));
int bandit_match __P((struct device *, struct cfdata *, void *));
int bandit_print __P((void *, const char *));
pcireg_t bandit_conf_read __P((pci_chipset_tag_t, pcitag_t, int));
void bandit_conf_write __P((pci_chipset_tag_t, pcitag_t, int, pcireg_t));
static void bandit_init __P((struct bandit_softc *));
struct cfattach bandit_ca = {
sizeof(struct bandit_softc), bandit_match, bandit_attach
};
int
bandit_match(parent, cf, aux)
struct device *parent;
struct cfdata *cf;
void *aux;
{
struct confargs *ca = aux;
char compat[32];
if (strcmp(ca->ca_name, "bandit") == 0)
return 1;
return 0;
}
void
bandit_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
struct bandit_softc *sc = (void *)self;
pci_chipset_tag_t pc = &sc->sc_pc;
struct confargs *ca = aux;
struct pcibus_attach_args pba;
int len, node = ca->ca_node;
u_int32_t reg[2], busrange[2];
struct ranges {
u_int32_t pci_hi, pci_mid, pci_lo;
u_int32_t host;
u_int32_t size_hi, size_lo;
} ranges[6], *rp = ranges;
printf("\n");
/* Bandit address */
if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8)
return;
/* PCI bus number */
if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
return;
pc->node = node;
pc->addr = mapiodev(reg[0] + 0x800000, 4);
pc->data = mapiodev(reg[0] + 0xc00000, 8);
pc->bus = busrange[0];
pc->conf_read = bandit_conf_read;
pc->conf_write = bandit_conf_write;
pc->memt = (bus_space_tag_t)0;
/* find i/o tag */
len = OF_getprop(node, "ranges", ranges, sizeof(ranges));
if (len == -1)
return;
while (len >= sizeof(ranges[0])) {
if ((rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) ==
OFW_PCI_PHYS_HI_SPACE_IO)
pc->iot = (bus_space_tag_t)rp->host;
len -= sizeof(ranges[0]);
rp++;
}
bandit_init(sc);
bzero(&pba, sizeof(pba));
pba.pba_busname = "pci";
pba.pba_memt = pc->memt;
pba.pba_iot = pc->iot;
pba.pba_dmat = &pci_bus_dma_tag;
pba.pba_bus = pc->bus;
pba.pba_pc = pc;
pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
config_found(self, &pba, bandit_print);
}
int
bandit_print(aux, pnp)
void *aux;
const char *pnp;
{
struct pcibus_attach_args *pa = aux;
if (pnp)
printf("%s at %s", pa->pba_busname, pnp);
printf(" bus %d", pa->pba_bus);
return UNCONF;
}
pcireg_t
bandit_conf_read(pc, tag, reg)
pci_chipset_tag_t pc;
pcitag_t tag;
int reg;
{
pcireg_t data;
int bus, dev, func, s;
u_int32_t x;
pci_decompose_tag(pc, tag, &bus, &dev, &func);
/*
* bandit's minimum device number of the first bus is 11.
* So we behave as if there is no device when dev < 11.
*/
if (func > 7)
panic("pci_conf_read: func > 7");
if (bus == pc->bus) {
if (dev < 11) {
if (reg == PCI_ID_REG)
return 0xffffffff;
else
panic("pci_conf_read: dev < 11");
}
x = (1 << dev) | (func << 8) | reg;
} else
x = tag | reg | 1;
s = splhigh();
out32rb(pc->addr, x);
DELAY(10);
data = 0xffffffff;
if (!badaddr(pc->data, 4))
data = in32rb(pc->data);
DELAY(10);
out32rb(pc->addr, 0);
DELAY(10);
splx(s);
return data;
}
void
bandit_conf_write(pc, tag, reg, data)
pci_chipset_tag_t pc;
pcitag_t tag;
int reg;
pcireg_t data;
{
int bus, dev, func, s;
u_int32_t x;
pci_decompose_tag(pc, tag, &bus, &dev, &func);
if (func > 7)
panic("pci_conf_write: func > 7");
if (bus == pc->bus) {
if (dev < 11)
panic("pci_conf_write: dev < 11");
x = (1 << dev) | (func << 8) | reg;
} else
x = tag | reg | 1;
s = splhigh();
out32rb(pc->addr, x);
DELAY(10);
out32rb(pc->data, data);
DELAY(10);
out32rb(pc->addr, 0);
DELAY(10);
splx(s);
}
#define PCI_BANDIT 11
#define PCI_REG_BANDIT_CFG 0x40
#define PCI_REG_ADDR_MASK 0x48
#define PCI_REG_MODE_SELECT 0x50
#define PCI_REG_ARBUS_HOLDOFF 0x58
#define PCI_MS_BYTESWAP 0x001 /* Enable Big Endian mode. (R/W)*/
#define PCI_MS_PASSATOMIC 0x002 /* PCI Bus to ARBus Lock are always allowed (R)*/
#define PCI_MS_NUMBER_MASK 0x00C /* PCI Bus Number (R) */
#define PCI_MS_IS_SYNC 0x010 /* Is Synchronous (1) or Async (0) ? (R)*/
#define PCI_MS_VGA_SPACE 0x020 /* Map VGA I/O space (R/W) */
#define PCI_MS_IO_COHERENT 0x040 /* I/O Coherent (R/W) */
#define PCI_MS_INT_ENABLE 0x080 /* Allow TEA or PCI Abort INT to pass to Grand Central (R/W) */
#define BANDIT_SPECIAL_CYCLE 0xe00000 /* Special Cycle offset */
static void bandit_init __P((pci_chipset_tag_t));
static void scan_pci_devs __P((int));
static void config_slot __P((int, pci_chipset_tag_t, int));
#define PCI_MODE_IO_COHERENT 0x040 /* I/O coherent */
void
pci_init(canmap)
int canmap;
bandit_init(sc)
struct bandit_softc *sc;
{
scan_pci_devs(canmap);
}
static void
bandit_init(pc)
pci_chipset_tag_t pc;
{
u_int status;
pci_chipset_tag_t pc = &sc->sc_pc;
pcitag_t tag;
u_int mode;
tag = pci_make_tag(pc, 0, PCI_BANDIT, 0);
tag = pci_make_tag(pc, pc->bus, PCI_BANDIT, 0);
if ((pci_conf_read(pc, tag, PCI_ID_REG) & 0xffff) == 0xffff)
return;
status = pci_conf_read(pc, tag, PCI_REG_MODE_SELECT);
mode = pci_conf_read(pc, tag, PCI_REG_MODE_SELECT);
if ((status & PCI_MS_IO_COHERENT) == 0) {
status |= PCI_MS_IO_COHERENT;
pci_conf_write(pc, tag, PCI_REG_MODE_SELECT, status);
if ((mode & PCI_MODE_IO_COHERENT) == 0) {
mode |= PCI_MODE_IO_COHERENT;
pci_conf_write(pc, tag, PCI_REG_MODE_SELECT, mode);
}
}
static void
scan_pci_devs(canmap)
int canmap;
{
int reglen, node, child, n, is_bandit, is_mpc106;
char name[64];
u_int32_t *p, reg[36];
bzero(pci_bridges, sizeof(pci_bridges));
node = OF_peer(0);
node = OF_child(node);
for (n = 0; node != 0; node = OF_peer(node)) {
if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
continue;
is_bandit = (strcmp(name, "bandit") == 0 ||
strcmp(name, "chaos") == 0) ? 1 : 0;
/* XXX for now */
is_mpc106 = (strcmp(name, "pci") == 0) ? 1 : 0;
if (is_bandit == 0 && is_mpc106 == 0)
continue;
/*
* Get the "ranges" property. We're expecting 6 32-bit
* values for each address space:
*
* phys.hi phys.mid phys.lo host size.hi size.lo
*
* Note that the MPC106 maps PCI memory space into
* two regions, one of which has a 24-bit addressing
* mode. We don't know the order of the "ranges"
* property, but both Address Map modes of the MPC106
* map the 32-bit memory range at a lower host address
* than the 24-bit range. We always pick the lower
* of the memory ranges for this reason.
*/
pci_bridges[n].memt = (bus_space_tag_t) 0xffffffff;
reglen = OF_getproplen(node, "ranges");
if (reglen > sizeof(reg) || reglen <= 0 ||
reglen % (6 * sizeof(u_int32_t)) != 0)
continue; /* eek */
reglen = OF_getprop(node, "ranges", reg, sizeof(reg));
for (p = reg; reglen > 0;
reglen -= (6 * sizeof(u_int32_t)), p += 6) {
switch (p[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
case OFW_PCI_PHYS_HI_SPACE_IO:
pci_bridges[n].iot =
(bus_space_tag_t) p[3];
break;
case OFW_PCI_PHYS_HI_SPACE_MEM32:
#if 0 /* XXX XXX XXX */
if (pci_bridges[n].memt >
(bus_space_tag_t)p[3])
pci_bridges[n].memt =
(bus_space_tag_t) p[3];
#else
/*
* XXX The Power Mac firmware seems to
* XXX include the PCI memory space base
* XXX in the device's BARs. We can remove
* XXX this kludge from here once we
* XXX fix the bus_space(9) implelentation.
*/
pci_bridges[n].memt = (bus_space_tag_t) 0;
#endif
break;
/* XXX What about OFW_PCI_PHYS_HI_SPACE_MEM64? */
}
}
/*
* The "bus-range" property tells us our PCI bus number.
*/
if (OF_getprop(node, "bus-range", reg, sizeof(reg)) != 8)
continue;
pci_bridges[n].bus = reg[0];
pci_bridges[n].present = 1;
/*
* Map the PCI configuration space access registers,
* and perform any PCI-Host bridge initialization.
*/
if (OF_getprop(node, "reg", pci_bridges[n].reg,
sizeof(pci_bridges[n].reg)) != 8)
continue;
if (is_bandit) {
/* XXX magic numbers */
pci_bridges[n].pc = n;
if (canmap) {
pci_bridges[n].addr =
mapiodev(pci_bridges[n].reg[0] + 0x800000,
4);
pci_bridges[n].data =
mapiodev(pci_bridges[n].reg[0] + 0xc00000,
4);
bandit_init(n);
}
} else if (is_mpc106) {
/* XXX magic numbers */
pci_bridges[n].pc = PCI_CHIPSET_MPC106; /* for now */
if (canmap) {
pci_bridges[n].addr = mapiodev(0xfec00000, 4);
pci_bridges[n].data = mapiodev(0xfee00000, 4);
}
}
if (canmap) {
/*
* Configure all of the PCI devices attached to this
* PCI-Host bridge.
*/
child = OF_child(node);
while (child) {
config_slot(child, pci_bridges[n].pc, -1);
child = OF_peer(child);
}
}
/* Bridge found, increment bridge instance. */
n++;
}
}
static void
config_slot(node, pc, irq)
int node;
pci_chipset_tag_t pc;
int irq;
{
pcitag_t tag;
pcireg_t csr, intr;
int i, sz;
int bus, dev, func;
u_int32_t reg[40], *rp;
char name[16];
struct {
u_int32_t device;
u_int32_t junk[3];
u_int32_t intrnode;
u_int32_t interrupt;
} imap[16];
bzero(name, sizeof(name));
OF_getprop(node, "name", name, sizeof(name));
if (strcmp(name, "pci-bridge") == 0) {
if (irq == -1)
OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq));
node = OF_child(node);
while (node) {
config_slot(node, pc, irq);
node = OF_peer(node);
}
return;
}
sz = OF_getprop(node, "assigned-addresses", reg, sizeof(reg));
if (sz < 4)
return;
rp = reg;
bus = (rp[0] & OFW_PCI_PHYS_HI_BUSMASK) >>
OFW_PCI_PHYS_HI_BUSSHIFT;
dev = (rp[0] & OFW_PCI_PHYS_HI_DEVICEMASK) >>
OFW_PCI_PHYS_HI_DEVICESHIFT;
func = (rp[0] & OFW_PCI_PHYS_HI_FUNCTIONMASK) >>
OFW_PCI_PHYS_HI_FUNCTIONSHIFT;
tag = pci_make_tag(pc, bus, dev, func);
csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
/*
* Make sure the IO and MEM enable bits are set in the CSR.
*/
csr &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
for (; sz > 0; sz -= 5 * sizeof(u_int32_t), rp += 5) {
switch (rp[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
case OFW_PCI_PHYS_HI_SPACE_IO:
csr |= PCI_COMMAND_IO_ENABLE;
break;
case OFW_PCI_PHYS_HI_SPACE_MEM32:
csr |= PCI_COMMAND_MEM_ENABLE;
break;
}
}
pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
/*
* Make sure the line register is programmed with the interrupt
* mapping.
*/
if (irq == -1 &&
OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq)) == -1 &&
OF_getprop(node, "interrupts", &irq, sizeof(irq)) == -1)
return;
if (irq == 1) { /* XXX */
sz = OF_getprop(OF_parent(node), "interrupt-map",
imap, sizeof(imap));
if (sz != -1) {
for (i = 0; i < sz / sizeof(*imap); i++) {
/* XXX should use interrupt-map-mask */
if (((imap[i].device &
OFW_PCI_PHYS_HI_DEVICEMASK) >>
OFW_PCI_PHYS_HI_DEVICESHIFT) == dev) {
irq = imap[i].interrupt;
break;
}
}
}
}
intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
intr = (intr & ~PCI_INTERRUPT_LINE_MASK) |
(irq & PCI_INTERRUPT_LINE_MASK);
pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
}

View File

@ -0,0 +1,184 @@
/* $NetBSD: grackle.c,v 1.1 2000/02/03 19:27:45 tsubai Exp $ */
/*-
* Copyright (c) 2000 Tsubai Masanari. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <dev/pci/pcivar.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <machine/autoconf.h>
struct grackle_softc {
struct device sc_dev;
struct pci_bridge sc_pc;
};
void grackle_attach __P((struct device *, struct device *, void *));
int grackle_match __P((struct device *, struct cfdata *, void *));
int grackle_print __P((void *, const char *));
pcireg_t grackle_conf_read __P((pci_chipset_tag_t, pcitag_t, int));
void grackle_conf_write __P((pci_chipset_tag_t, pcitag_t, int, pcireg_t));
struct cfattach grackle_ca = {
sizeof(struct grackle_softc), grackle_match, grackle_attach
};
int
grackle_match(parent, cf, aux)
struct device *parent;
struct cfdata *cf;
void *aux;
{
struct confargs *ca = aux;
char compat[32];
if (strcmp(ca->ca_name, "pci") != 0)
return 0;
bzero(compat, sizeof(compat));
OF_getprop(ca->ca_node, "compatible", compat, sizeof(compat));
if (strcmp(compat, "grackle") != 0)
return 0;
return 1;
}
#define GRACKLE_ADDR 0xfec00000
#define GRACKLE_DATA 0xfee00000
void
grackle_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
struct grackle_softc *sc = (void *)self;
pci_chipset_tag_t pc = &sc->sc_pc;
struct confargs *ca = aux;
struct pcibus_attach_args pba;
int len, node = ca->ca_node;
u_int32_t busrange[2];
struct ranges {
u_int32_t pci_hi, pci_mid, pci_lo;
u_int32_t host;
u_int32_t size_hi, size_lo;
} ranges[6], *rp = ranges;
printf("\n");
/* PCI bus number */
if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
return;
pc->node = node;
pc->addr = mapiodev(GRACKLE_ADDR, 4);
pc->data = mapiodev(GRACKLE_DATA, 4);
pc->bus = busrange[0];
pc->conf_read = grackle_conf_read;
pc->conf_write = grackle_conf_write;
pc->memt = (bus_space_tag_t)0;
/* find i/o tag */
len = OF_getprop(node, "ranges", ranges, sizeof(ranges));
if (len == -1)
return;
while (len >= sizeof(ranges[0])) {
if ((rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) ==
OFW_PCI_PHYS_HI_SPACE_IO)
pc->iot = (bus_space_tag_t)rp->host;
len -= sizeof(ranges[0]);
rp++;
}
bzero(&pba, sizeof(pba));
pba.pba_busname = "pci";
pba.pba_memt = pc->memt;
pba.pba_iot = pc->iot;
pba.pba_dmat = &pci_bus_dma_tag;
pba.pba_bus = pc->bus;
pba.pba_pc = pc;
pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
config_found(self, &pba, grackle_print);
}
int
grackle_print(aux, pnp)
void *aux;
const char *pnp;
{
struct pcibus_attach_args *pa = aux;
if (pnp)
printf("%s at %s", pa->pba_busname, pnp);
printf(" bus %d", pa->pba_bus);
return UNCONF;
}
pcireg_t
grackle_conf_read(pc, tag, reg)
pci_chipset_tag_t pc;
pcitag_t tag;
int reg;
{
pcireg_t data;
int s;
s = splhigh();
out32rb(pc->addr, tag | reg);
data = 0xffffffff;
if (!badaddr(pc->data, 4))
data = in32rb(pc->data);
out32rb(pc->addr, 0);
splx(s);
return data;
}
void
grackle_conf_write(pc, tag, reg, data)
pci_chipset_tag_t pc;
pcitag_t tag;
int reg;
pcireg_t data;
{
int s;
s = splhigh();
out32rb(pc->addr, tag | reg);
out32rb(pc->data, data);
out32rb(pc->addr, 0);
splx(s);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: pci_machdep.c,v 1.9 1999/05/05 04:32:28 thorpej Exp $ */
/* $NetBSD: pci_machdep.c,v 1.10 2000/02/03 19:27:46 tsubai Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@ -62,6 +62,12 @@
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
static void fixpci __P((int, pci_chipset_tag_t));
static int find_node_intr __P((int, u_int32_t *, u_int32_t *));
/*
* PCI doesn't have any special needs; just use the generic versions
* of these functions.
@ -88,8 +94,25 @@ pci_attach_hook(parent, self, pba)
struct device *parent, *self;
struct pcibus_attach_args *pba;
{
pci_chipset_tag_t pc = pba->pba_pc;
int bus = pba->pba_bus;
int node, nn, sz;
int32_t busrange[2];
/* Nothing to do. */
for (node = pc->node; node; node = nn) {
sz = OF_getprop(node, "bus-range", busrange, 8);
if (sz == 8 && busrange[0] == bus) {
fixpci(node, pc);
return;
}
if ((nn = OF_child(node)) != 0)
continue;
while ((nn = OF_peer(node)) == 0) {
node = OF_parent(node);
if (node == pc->node)
return; /* not found */
}
}
}
int
@ -142,54 +165,8 @@ pci_conf_read(pc, tag, reg)
pcitag_t tag;
int reg;
{
pcireg_t data;
struct pci_bridge *r;
int bus, dev, func, s;
s = splhigh();
if (pc == PCI_CHIPSET_MPC106) {
r = &pci_bridges[0];
out32rb(r->addr, tag | reg);
data = 0xffffffff;
if (!badaddr(r->data, 4))
data = in32rb(r->data);
out32rb(r->addr, 0);
} else {
pci_decompose_tag(pc, tag, &bus, &dev, &func);
r = &pci_bridges[pc];
/*
* bandit's minimum device number of the first bus is 11.
* So we behave as if there is no device when dev < 11.
*/
if (func > 7)
panic("pci_conf_read: func > 7");
if (bus == r->bus) {
if (dev < 11) {
if (reg == PCI_ID_REG)
return 0xffffffff;
else
panic("pci_conf_read: dev < 11");
}
out32rb(r->addr, (1 << dev) | (func << 8) | reg);
} else
out32rb(r->addr, tag | reg | 1);
DELAY(10);
data = 0xffffffff;
if (!badaddr(r->data, 4))
data = in32rb(r->data);
DELAY(10);
out32rb(r->addr, 0);
DELAY(10);
}
splx(s);
return data;
return (*pc->conf_read)(pc, tag, reg);
}
void
@ -199,39 +176,8 @@ pci_conf_write(pc, tag, reg, data)
int reg;
pcireg_t data;
{
struct pci_bridge *r;
int bus, dev, func, s;
s = splhigh();
if (pc == PCI_CHIPSET_MPC106) {
r = &pci_bridges[0];
out32rb(r->addr, tag | reg);
out32rb(r->data, data);
out32rb(r->addr, 0);
} else {
r = &pci_bridges[pc];
pci_decompose_tag(pc, tag, &bus, &dev, &func);
if (func > 7)
panic("pci_conf_write: func > 7");
if (bus == r->bus) {
if (dev < 11)
panic("pci_conf_write: dev < 11");
out32rb(r->addr, (1 << dev) | (func << 8) | reg);
} else
out32rb(r->addr, tag | reg | 1);
DELAY(10);
out32rb(r->data, data);
DELAY(10);
out32rb(r->addr, 0);
DELAY(10);
}
splx(s);
(*pc->conf_write)(pc, tag, reg, data);
}
int
@ -324,3 +270,156 @@ pci_intr_disestablish(pc, cookie)
intr_disestablish(cookie);
}
#define pcibus(x) \
(((x) & OFW_PCI_PHYS_HI_BUSMASK) >> OFW_PCI_PHYS_HI_BUSSHIFT)
#define pcidev(x) \
(((x) & OFW_PCI_PHYS_HI_DEVICEMASK) >> OFW_PCI_PHYS_HI_DEVICESHIFT)
#define pcifunc(x) \
(((x) & OFW_PCI_PHYS_HI_FUNCTIONMASK) >> OFW_PCI_PHYS_HI_FUNCTIONSHIFT)
void
fixpci(parent, pc)
int parent;
pci_chipset_tag_t pc;
{
int node;
pcitag_t tag;
pcireg_t csr, intr;
int len, i;
int32_t irqs[4];
struct {
u_int32_t phys_hi, phys_mid, phys_lo;
u_int32_t size_hi, size_lo;
} addr[8];
for (node = OF_child(parent); node; node = OF_peer(node)) {
len = OF_getprop(node, "assigned-addresses", addr,
sizeof(addr));
if (len < (int)sizeof(addr[0]))
continue;
tag = pci_make_tag(pc, pcibus(addr[0].phys_hi),
pcidev(addr[0].phys_hi),
pcifunc(addr[0].phys_hi));
/*
* Make sure the IO and MEM enable bits are set in the CSR.
*/
csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
csr &= ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE);
for (i = 0; i < len / sizeof(addr[0]); i++) {
switch (addr[i].phys_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
case OFW_PCI_PHYS_HI_SPACE_IO:
csr |= PCI_COMMAND_IO_ENABLE;
break;
case OFW_PCI_PHYS_HI_SPACE_MEM32:
csr |= PCI_COMMAND_MEM_ENABLE;
break;
}
}
pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
/*
* Make sure the line register is programmed with the
* interrupt mapping.
*/
if (find_node_intr(node, &addr[0].phys_hi, irqs) == -1)
continue;
intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
intr &= ~PCI_INTERRUPT_LINE_MASK;
intr |= irqs[0] & PCI_INTERRUPT_LINE_MASK;
pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
}
}
/*
* Find PCI IRQ of the node from OF tree.
*/
int
find_node_intr(node, addr, intr)
int node;
u_int32_t *addr, *intr;
{
int parent, len, mlen, iparent;
int match, i;
u_int32_t map[64], *mp;
u_int32_t imask[8], maskedaddr[8];
u_int32_t icells;
char name[32];
len = OF_getprop(node, "AAPL,interrupts", intr, 4) ;
if (len == 4)
return len;
parent = OF_parent(node);
len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask));
if (len == -1 || mlen == -1)
goto nomap;
#ifdef DIAGNOSTIC
if (mlen == sizeof(imask)) {
printf("interrupt-map too long\n");
return -1;
}
#endif
/* mask addr by "interrupt-map-mask" */
bcopy(addr, maskedaddr, mlen);
for (i = 0; i < mlen / 4; i++)
maskedaddr[i] &= imask[i];
mp = map;
while (len > mlen) {
match = bcmp(maskedaddr, mp, mlen);
mp += mlen / 4;
len -= mlen;
/*
* We must read "#interrupt-cells" for each time because
* interrupt-parent may be defferent.
*
* XXX assume #address-cells == 1
*/
iparent = *mp++;
len -= 4;
if (OF_getprop(iparent, "#interrupt-cells", &icells, 4) != 4)
return -1;
/* Found. */
if (match == 0) {
bcopy(mp, intr, icells * 4);
return icells * 4;
}
mp += icells;
len -= icells * 4;
}
nomap:
/*
* If the node has no interrupt property and the parent is a
* pci-bridge, use parent's interrupt. This occurs on a PCI
* slot. (e.g. AHA-3940)
*/
bzero(name, sizeof(name));
OF_getprop(parent, "name", name, sizeof(name));
if (strcmp(name, "pci-bridge") == 0) {
len = OF_getprop(parent, "AAPL,interrupts", intr, 4) ;
if (len == 4)
return len;
}
/* XXX This may be wrong... */
len = OF_getprop(node, "interrupts", intr, 4) ;
if (len == 4)
return len;
return -1;
}

View File

@ -0,0 +1,243 @@
/* $NetBSD: uninorth.c,v 1.1 2000/02/03 19:27:46 tsubai Exp $ */
/*-
* Copyright (c) 2000 Tsubai Masanari. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <dev/pci/pcivar.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <machine/autoconf.h>
struct uninorth_softc {
struct device sc_dev;
struct pci_bridge sc_pc;
};
void uninorth_attach __P((struct device *, struct device *, void *));
int uninorth_match __P((struct device *, struct cfdata *, void *));
int uninorth_print __P((void *, const char *));
pcireg_t uninorth_conf_read __P((pci_chipset_tag_t, pcitag_t, int));
void uninorth_conf_write __P((pci_chipset_tag_t, pcitag_t, int, pcireg_t));
struct cfattach uninorth_ca = {
sizeof(struct uninorth_softc), uninorth_match, uninorth_attach
};
int
uninorth_match(parent, cf, aux)
struct device *parent;
struct cfdata *cf;
void *aux;
{
struct confargs *ca = aux;
char compat[32];
if (strcmp(ca->ca_name, "pci") != 0)
return 0;
bzero(compat, sizeof(compat));
OF_getprop(ca->ca_node, "compatible", compat, sizeof(compat));
if (strcmp(compat, "uni-north") != 0)
return 0;
return 1;
}
void
uninorth_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
struct uninorth_softc *sc = (void *)self;
pci_chipset_tag_t pc = &sc->sc_pc;
struct confargs *ca = aux;
struct pcibus_attach_args pba;
int len, child, node = ca->ca_node;
u_int32_t reg[2], busrange[2];
struct ranges {
u_int32_t pci_hi, pci_mid, pci_lo;
u_int32_t host;
u_int32_t size_hi, size_lo;
} ranges[6], *rp = ranges;
printf("\n");
/* UniNorth address */
if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8)
return;
/* PCI bus number */
if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
return;
pc->node = node;
pc->addr = mapiodev(reg[0] + 0x800000, 4);
pc->data = mapiodev(reg[0] + 0xc00000, 8);
pc->bus = busrange[0];
pc->conf_read = uninorth_conf_read;
pc->conf_write = uninorth_conf_write;
pc->memt = (bus_space_tag_t)0;
/* find i/o tag */
len = OF_getprop(node, "ranges", ranges, sizeof(ranges));
if (len == -1)
return;
while (len >= sizeof(ranges[0])) {
if ((rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) ==
OFW_PCI_PHYS_HI_SPACE_IO)
pc->iot = (bus_space_tag_t)rp->host;
len -= sizeof(ranges[0]);
rp++;
}
/* XXX enable gmac ethernet */
for (child = OF_child(node); child; child = OF_peer(child)) {
volatile int *gmac_gbclock_en = (void *)0xf8000020;
char compat[32];
bzero(compat, sizeof(compat));
OF_getprop(child, "compatible", compat, sizeof(compat));
if (strcmp(compat, "gmac") == 0)
*gmac_gbclock_en |= 0x02;
}
bzero(&pba, sizeof(pba));
pba.pba_busname = "pci";
pba.pba_memt = pc->memt;
pba.pba_iot = pc->iot;
pba.pba_dmat = &pci_bus_dma_tag;
pba.pba_bus = pc->bus;
pba.pba_pc = pc;
pba.pba_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
config_found(self, &pba, uninorth_print);
}
int
uninorth_print(aux, pnp)
void *aux;
const char *pnp;
{
struct pcibus_attach_args *pa = aux;
if (pnp)
printf("%s at %s", pa->pba_busname, pnp);
printf(" bus %d", pa->pba_bus);
return UNCONF;
}
pcireg_t
uninorth_conf_read(pc, tag, reg)
pci_chipset_tag_t pc;
pcitag_t tag;
int reg;
{
int32_t *daddr = pc->data;
pcireg_t data;
int bus, dev, func, s;
u_int32_t x;
/* UniNorth seems to have a 64bit data port */
if (reg & 0x04)
daddr++;
pci_decompose_tag(pc, tag, &bus, &dev, &func);
/*
* bandit's minimum device number of the first bus is 11.
* So we behave as if there is no device when dev < 11.
*/
if (func > 7)
panic("pci_conf_read: func > 7");
if (bus == pc->bus) {
if (dev < 11) {
if (reg == PCI_ID_REG)
return 0xffffffff;
else
panic("pci_conf_read: dev < 11");
}
x = (1 << dev) | (func << 8) | reg;
} else
x = tag | reg | 1;
s = splhigh();
out32rb(pc->addr, x);
in32rb(pc->addr);
data = 0xffffffff;
if (!badaddr(daddr, 4))
data = in32rb(daddr);
out32rb(pc->addr, 0);
in32rb(pc->addr);
splx(s);
return data;
}
void
uninorth_conf_write(pc, tag, reg, data)
pci_chipset_tag_t pc;
pcitag_t tag;
int reg;
pcireg_t data;
{
int32_t *daddr = pc->data;
int bus, dev, func, s;
u_int32_t x;
/* UniNorth seems to have a 64bit data port */
if (reg & 0x04)
daddr++;
pci_decompose_tag(pc, tag, &bus, &dev, &func);
if (func > 7)
panic("pci_conf_write: func > 7");
if (bus == pc->bus) {
if (dev < 11)
panic("pci_conf_write: dev < 11");
x = (1 << dev) | (func << 8) | reg;
} else
x = tag | reg | 1;
s = splhigh();
out32rb(pc->addr, x);
in32rb(pc->addr);
out32rb(daddr, data);
out32rb(pc->addr, 0);
in32rb(pc->addr);
splx(s);
}