* 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:
parent
b20e217bb8
commit
e29a886cd6
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
184
sys/arch/macppc/pci/grackle.c
Normal file
184
sys/arch/macppc/pci/grackle.c
Normal 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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
243
sys/arch/macppc/pci/uninorth.c
Normal file
243
sys/arch/macppc/pci/uninorth.c
Normal 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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user