PCI-CardBus bridge support for sparc64:
- handle devices which has no OBP node. - move PCI latency-timer initialization from pci_intr_map to pci_enumerate_bus. - make PCI bus free space extents for cardbus devices. - fix PCI config space map size. - some code integrations.
This commit is contained in:
parent
a8e1b2f5c5
commit
aad45dd3ad
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: pci_machdep.c,v 1.34 2002/12/10 13:44:51 pk Exp $ */
|
/* $NetBSD: pci_machdep.c,v 1.35 2003/03/22 06:33:09 nakayama Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2000 Matthew R. Green
|
* Copyright (c) 1999, 2000 Matthew R. Green
|
||||||
|
@ -114,8 +114,10 @@ pci_make_tag(pc, b, d, f)
|
||||||
int d;
|
int d;
|
||||||
int f;
|
int f;
|
||||||
{
|
{
|
||||||
|
struct psycho_pbm *pp = pc->cookie;
|
||||||
struct ofw_pci_register reg;
|
struct ofw_pci_register reg;
|
||||||
pcitag_t tag;
|
pcitag_t tag;
|
||||||
|
int (*valid) __P((void *));
|
||||||
int busrange[2];
|
int busrange[2];
|
||||||
int node, len;
|
int node, len;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -123,6 +125,18 @@ pci_make_tag(pc, b, d, f)
|
||||||
bzero(name, sizeof(name));
|
bzero(name, sizeof(name));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Refer to the PCI/CardBus bus node first.
|
||||||
|
* It returns a tag if node is present and bus is valid.
|
||||||
|
*/
|
||||||
|
if (0 <= b && b < 256) {
|
||||||
|
node = (*pp->pp_busnode)[b].node;
|
||||||
|
valid = (*pp->pp_busnode)[b].valid;
|
||||||
|
if (node != 0 && d == 0 &&
|
||||||
|
(valid == NULL || (*valid)((*pp->pp_busnode)[b].arg)))
|
||||||
|
return ofpci_make_tag(pc, node, b, d, f);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hunt for the node that corresponds to this device
|
* Hunt for the node that corresponds to this device
|
||||||
*
|
*
|
||||||
|
@ -247,8 +261,9 @@ pci_enumerate_bus(struct pci_softc *sc,
|
||||||
struct ofw_pci_register reg;
|
struct ofw_pci_register reg;
|
||||||
pci_chipset_tag_t pc = sc->sc_pc;
|
pci_chipset_tag_t pc = sc->sc_pc;
|
||||||
pcitag_t tag;
|
pcitag_t tag;
|
||||||
pcireg_t class, csr;
|
pcireg_t class, csr, bhlc, ic;
|
||||||
int node, b, d, f, ret;
|
int node, b, d, f, ret;
|
||||||
|
int len, bus_frequency, lt, cl;
|
||||||
char name[30];
|
char name[30];
|
||||||
extern int pci_config_dump;
|
extern int pci_config_dump;
|
||||||
|
|
||||||
|
@ -257,12 +272,36 @@ pci_enumerate_bus(struct pci_softc *sc,
|
||||||
else
|
else
|
||||||
node = pc->rootnode;
|
node = pc->rootnode;
|
||||||
|
|
||||||
|
len = OF_getproplen(node, "clock-frequency");
|
||||||
|
if (len < sizeof(bus_frequency)) {
|
||||||
|
DPRINTF(SPDB_PROBE,
|
||||||
|
("pci_enumerate_bus: clock-frequency len %d too small\n",
|
||||||
|
len));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (OF_getprop(node, "clock-frequency", &bus_frequency,
|
||||||
|
sizeof(bus_frequency)) != len) {
|
||||||
|
DPRINTF(SPDB_PROBE,
|
||||||
|
("pci_enumerate_bus: could not read clock-frequency\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bus_frequency /= 1000000;
|
||||||
|
|
||||||
/* Turn on parity for the bus. */
|
/* Turn on parity for the bus. */
|
||||||
tag = ofpci_make_tag(pc, node, sc->sc_bus, 0, 0);
|
tag = ofpci_make_tag(pc, node, sc->sc_bus, 0, 0);
|
||||||
csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
|
csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
|
||||||
csr |= PCI_COMMAND_PARITY_ENABLE;
|
csr |= PCI_COMMAND_PARITY_ENABLE;
|
||||||
pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
|
pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the latency timer register.
|
||||||
|
* The value 0x40 is from Solaris.
|
||||||
|
*/
|
||||||
|
bhlc = pci_conf_read(pc, tag, PCI_BHLC_REG);
|
||||||
|
bhlc &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
|
||||||
|
bhlc |= 0x40 << PCI_LATTIMER_SHIFT;
|
||||||
|
pci_conf_write(pc, tag, PCI_BHLC_REG, bhlc);
|
||||||
|
|
||||||
if (pci_config_dump) pci_conf_print(pc, tag, NULL);
|
if (pci_config_dump) pci_conf_print(pc, tag, NULL);
|
||||||
|
|
||||||
for (node = OF_child(node); node != 0 && node != -1;
|
for (node = OF_child(node); node != 0 && node != -1;
|
||||||
|
@ -297,6 +336,30 @@ pci_enumerate_bus(struct pci_softc *sc,
|
||||||
csr |= PCI_COMMAND_PARITY_ENABLE;
|
csr |= PCI_COMMAND_PARITY_ENABLE;
|
||||||
pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
|
pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the latency timer register for busmaster
|
||||||
|
* devices to work properly.
|
||||||
|
* latency-timer = min-grant * bus-freq / 4 (from FreeBSD)
|
||||||
|
* Also initialize the cache line size register.
|
||||||
|
* Solaris anytime sets this register to the value 0x10.
|
||||||
|
*/
|
||||||
|
bhlc = pci_conf_read(pc, tag, PCI_BHLC_REG);
|
||||||
|
ic = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
|
||||||
|
|
||||||
|
lt = min(PCI_MIN_GNT(ic) * bus_frequency / 4, 255);
|
||||||
|
if (lt == 0 || lt < PCI_LATTIMER(bhlc))
|
||||||
|
lt = PCI_LATTIMER(bhlc);
|
||||||
|
|
||||||
|
cl = PCI_CACHELINE(bhlc);
|
||||||
|
if (cl == 0)
|
||||||
|
cl = 0x10;
|
||||||
|
|
||||||
|
bhlc &= ~((PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT) |
|
||||||
|
(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT));
|
||||||
|
bhlc |= (lt << PCI_LATTIMER_SHIFT) |
|
||||||
|
(cl << PCI_CACHELINE_SHIFT);
|
||||||
|
pci_conf_write(pc, tag, PCI_BHLC_REG, bhlc);
|
||||||
|
|
||||||
ret = pci_probe_device(sc, tag, match, pap);
|
ret = pci_probe_device(sc, tag, match, pap);
|
||||||
if (match != NULL && ret != 0)
|
if (match != NULL && ret != 0)
|
||||||
return (ret);
|
return (ret);
|
||||||
|
@ -373,26 +436,10 @@ pci_intr_map(pa, ihp)
|
||||||
pci_intr_handle_t *ihp;
|
pci_intr_handle_t *ihp;
|
||||||
{
|
{
|
||||||
pcitag_t tag = pa->pa_tag;
|
pcitag_t tag = pa->pa_tag;
|
||||||
pcireg_t bhlc, ic;
|
|
||||||
int bus_frequency, val, bus_node;
|
|
||||||
int interrupts;
|
int interrupts;
|
||||||
int len, node = PCITAG_NODE(tag);
|
int len, node = PCITAG_NODE(tag);
|
||||||
char devtype[30];
|
char devtype[30];
|
||||||
|
|
||||||
bus_node = OF_parent(node);
|
|
||||||
len = OF_getproplen(bus_node, "clock-frequency");
|
|
||||||
if (len < sizeof(bus_frequency)) {
|
|
||||||
DPRINTF(SPDB_INTMAP,
|
|
||||||
("pci_intr_map: clock-frequency len %d too small\n", len));
|
|
||||||
return (ENODEV);
|
|
||||||
}
|
|
||||||
if (OF_getprop(bus_node, "clock-frequency", (void *)&bus_frequency,
|
|
||||||
sizeof(bus_frequency)) != len) {
|
|
||||||
DPRINTF(SPDB_INTMAP,
|
|
||||||
("pci_intr_map: could not read bus_frequency\n"));
|
|
||||||
return (ENODEV);
|
|
||||||
}
|
|
||||||
|
|
||||||
len = OF_getproplen(node, "interrupts");
|
len = OF_getproplen(node, "interrupts");
|
||||||
if (len < sizeof(interrupts)) {
|
if (len < sizeof(interrupts)) {
|
||||||
DPRINTF(SPDB_INTMAP,
|
DPRINTF(SPDB_INTMAP,
|
||||||
|
@ -419,23 +466,6 @@ pci_intr_map(pa, ihp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Initialize the latency timer register for busmaster devices
|
|
||||||
* to work properly.
|
|
||||||
* latency-timer = min-grant * bus-freq / 4 (from FreeBSD)
|
|
||||||
*/
|
|
||||||
ic = pci_conf_read(pa->pa_pc, tag, PCI_INTERRUPT_REG);
|
|
||||||
bus_frequency /= 1000000;
|
|
||||||
val = min(PCI_MIN_GNT(ic) * bus_frequency / 4, 255);
|
|
||||||
if (val > 0) {
|
|
||||||
bhlc = pci_conf_read(pa->pa_pc, tag, PCI_BHLC_REG);
|
|
||||||
if (PCI_LATTIMER(bhlc) < val) {
|
|
||||||
bhlc &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
|
|
||||||
bhlc |= (val << PCI_LATTIMER_SHIFT);
|
|
||||||
pci_conf_write(pa->pa_pc, tag, PCI_BHLC_REG, bhlc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXXX -- we use the ino. What if there is a valid IGN? */
|
/* XXXX -- we use the ino. What if there is a valid IGN? */
|
||||||
*ihp = interrupts;
|
*ihp = interrupts;
|
||||||
return (0);
|
return (0);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: psycho.c,v 1.57 2002/12/10 13:44:51 pk Exp $ */
|
/* $NetBSD: psycho.c,v 1.58 2003/03/22 06:33:09 nakayama Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2002 Eduardo E. Horvath
|
* Copyright (c) 2001, 2002 Eduardo E. Horvath
|
||||||
|
@ -55,6 +55,8 @@ int psycho_debug = 0x0;
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/reboot.h>
|
#include <sys/reboot.h>
|
||||||
|
|
||||||
|
#include <uvm/uvm.h>
|
||||||
|
|
||||||
#define _SPARC_BUS_DMA_PRIVATE
|
#define _SPARC_BUS_DMA_PRIVATE
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
#include <machine/autoconf.h>
|
#include <machine/autoconf.h>
|
||||||
|
@ -73,6 +75,8 @@ int psycho_debug = 0x0;
|
||||||
|
|
||||||
static pci_chipset_tag_t psycho_alloc_chipset __P((struct psycho_pbm *, int,
|
static pci_chipset_tag_t psycho_alloc_chipset __P((struct psycho_pbm *, int,
|
||||||
pci_chipset_tag_t));
|
pci_chipset_tag_t));
|
||||||
|
static struct extent *psycho_alloc_extent __P((struct psycho_pbm *, int, int,
|
||||||
|
char *));
|
||||||
static void psycho_get_bus_range __P((int, int *));
|
static void psycho_get_bus_range __P((int, int *));
|
||||||
static void psycho_get_ranges __P((int, struct psycho_ranges **, int *));
|
static void psycho_get_ranges __P((int, struct psycho_ranges **, int *));
|
||||||
static void psycho_set_intr __P((struct psycho_softc *, int, void *,
|
static void psycho_set_intr __P((struct psycho_softc *, int, void *,
|
||||||
|
@ -94,6 +98,9 @@ static void psycho_iommu_init __P((struct psycho_softc *, int));
|
||||||
* bus space and bus dma support for UltraSPARC `psycho'. note that most
|
* bus space and bus dma support for UltraSPARC `psycho'. note that most
|
||||||
* of the bus dma support is provided by the iommu dvma controller.
|
* of the bus dma support is provided by the iommu dvma controller.
|
||||||
*/
|
*/
|
||||||
|
static int get_childspace __P((int));
|
||||||
|
static struct psycho_ranges *get_psychorange __P((struct psycho_pbm *, int));
|
||||||
|
|
||||||
static paddr_t psycho_bus_mmap __P((bus_space_tag_t, bus_addr_t, off_t,
|
static paddr_t psycho_bus_mmap __P((bus_space_tag_t, bus_addr_t, off_t,
|
||||||
int, int));
|
int, int));
|
||||||
static int _psycho_bus_map __P((bus_space_tag_t, bus_addr_t, bus_size_t, int,
|
static int _psycho_bus_map __P((bus_space_tag_t, bus_addr_t, bus_size_t, int,
|
||||||
|
@ -382,12 +389,11 @@ found:
|
||||||
/*
|
/*
|
||||||
* Allocate our psycho_pbm
|
* Allocate our psycho_pbm
|
||||||
*/
|
*/
|
||||||
pp = sc->sc_psycho_this = malloc(sizeof *pp, M_DEVBUF, M_NOWAIT);
|
pp = sc->sc_psycho_this = malloc(sizeof *pp, M_DEVBUF,
|
||||||
|
M_NOWAIT | M_ZERO);
|
||||||
if (pp == NULL)
|
if (pp == NULL)
|
||||||
panic("could not allocate psycho pbm");
|
panic("could not allocate psycho pbm");
|
||||||
|
|
||||||
memset(pp, 0, sizeof *pp);
|
|
||||||
|
|
||||||
pp->pp_sc = sc;
|
pp->pp_sc = sc;
|
||||||
|
|
||||||
/* grab the psycho ranges */
|
/* grab the psycho ranges */
|
||||||
|
@ -398,6 +404,7 @@ found:
|
||||||
|
|
||||||
pba.pba_bus = psycho_br[0];
|
pba.pba_bus = psycho_br[0];
|
||||||
pba.pba_bridgetag = NULL;
|
pba.pba_bridgetag = NULL;
|
||||||
|
pp->pp_busmax = psycho_br[1];
|
||||||
|
|
||||||
printf("bus range %u to %u", psycho_br[0], psycho_br[1]);
|
printf("bus range %u to %u", psycho_br[0], psycho_br[1]);
|
||||||
printf("; PCI bus %d", psycho_br[0]);
|
printf("; PCI bus %d", psycho_br[0]);
|
||||||
|
@ -419,6 +426,10 @@ found:
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
/* allocate extents for free bus space */
|
||||||
|
pp->pp_exmem = psycho_alloc_extent(pp, sc->sc_node, 0x02, "psycho mem");
|
||||||
|
pp->pp_exio = psycho_alloc_extent(pp, sc->sc_node, 0x01, "psycho io");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* And finally, if we're a sabre or the first of a pair of psycho's to
|
* And finally, if we're a sabre or the first of a pair of psycho's to
|
||||||
* arrive here, start up the IOMMU and get a config space tag.
|
* arrive here, start up the IOMMU and get a config space tag.
|
||||||
|
@ -471,6 +482,14 @@ found:
|
||||||
sc->sc_regs->intr_retry_timer = 0xff;
|
sc->sc_regs->intr_retry_timer = 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate bus node, this contains a prom node per bus.
|
||||||
|
*/
|
||||||
|
pp->pp_busnode = malloc(sizeof(*pp->pp_busnode), M_DEVBUF,
|
||||||
|
M_NOWAIT | M_ZERO);
|
||||||
|
if (pp->pp_busnode == NULL)
|
||||||
|
panic("psycho_attach: malloc pp->pp_busnode");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup IOMMU and PCI configuration if we're the first
|
* Setup IOMMU and PCI configuration if we're the first
|
||||||
* of a pair of psycho's to arrive here.
|
* of a pair of psycho's to arrive here.
|
||||||
|
@ -520,11 +539,14 @@ found:
|
||||||
i = sc->sc_bustag->type;
|
i = sc->sc_bustag->type;
|
||||||
sc->sc_bustag->type = PCI_CONFIG_BUS_SPACE;
|
sc->sc_bustag->type = PCI_CONFIG_BUS_SPACE;
|
||||||
if (bus_space_map(sc->sc_bustag, sc->sc_basepaddr + 0x01000000,
|
if (bus_space_map(sc->sc_bustag, sc->sc_basepaddr + 0x01000000,
|
||||||
0x0100000, 0, &bh))
|
0x01000000, 0, &bh))
|
||||||
panic("could not map psycho PCI configuration space");
|
panic("could not map psycho PCI configuration space");
|
||||||
sc->sc_bustag->type = i;
|
sc->sc_bustag->type = i;
|
||||||
sc->sc_configaddr = bh;
|
sc->sc_configaddr = bh;
|
||||||
} else {
|
} else {
|
||||||
|
/* Share bus numbers with the pair of mine */
|
||||||
|
pp->pp_busnode = osc->sc_psycho_this->pp_busnode;
|
||||||
|
|
||||||
/* Just copy IOMMU state, config tag and address */
|
/* Just copy IOMMU state, config tag and address */
|
||||||
sc->sc_is = osc->sc_is;
|
sc->sc_is = osc->sc_is;
|
||||||
sc->sc_configtag = osc->sc_configtag;
|
sc->sc_configtag = osc->sc_configtag;
|
||||||
|
@ -624,6 +646,84 @@ psycho_alloc_chipset(pp, node, pc)
|
||||||
return (npc);
|
return (npc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* create extent for free bus space, then allocate assigned regions.
|
||||||
|
*/
|
||||||
|
static struct extent *
|
||||||
|
psycho_alloc_extent(pp, node, ss, name)
|
||||||
|
struct psycho_pbm *pp;
|
||||||
|
int node;
|
||||||
|
int ss;
|
||||||
|
char *name;
|
||||||
|
{
|
||||||
|
struct psycho_registers *pa = NULL;
|
||||||
|
struct psycho_ranges *pr;
|
||||||
|
struct extent *ex;
|
||||||
|
bus_addr_t baddr, addr;
|
||||||
|
bus_size_t bsize, size;
|
||||||
|
int i, num;
|
||||||
|
|
||||||
|
/* get bus space size */
|
||||||
|
pr = get_psychorange(pp, ss);
|
||||||
|
if (pr == NULL) {
|
||||||
|
printf("psycho_alloc_extent: get_psychorange failed\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
baddr = 0x00000000;
|
||||||
|
bsize = BUS_ADDR(pr->size_hi, pr->size_lo);
|
||||||
|
|
||||||
|
/* get available lists */
|
||||||
|
if (PROM_getprop(node, "available", sizeof(*pa), &num, (void **)&pa)) {
|
||||||
|
printf("psycho_alloc_extent: PROM_getprop failed\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create extent */
|
||||||
|
ex = extent_create(name, baddr, bsize - baddr - 1, M_DEVBUF, 0, 0,
|
||||||
|
EX_NOWAIT);
|
||||||
|
if (ex == NULL) {
|
||||||
|
printf("psycho_alloc_extent: extent_create failed\n");
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate assigned regions */
|
||||||
|
for (i = 0; i < num; i++)
|
||||||
|
if (((pa[i].phys_hi >> 24) & 0x03) == ss) {
|
||||||
|
/* allocate bus space */
|
||||||
|
addr = BUS_ADDR(pa[i].phys_mid, pa[i].phys_lo);
|
||||||
|
size = BUS_ADDR(pa[i].size_hi, pa[i].size_lo);
|
||||||
|
if (extent_alloc_region(ex, baddr, addr - baddr,
|
||||||
|
EX_NOWAIT)) {
|
||||||
|
printf("psycho_alloc_extent: "
|
||||||
|
"extent_alloc_region %" PRIx64 "-%"
|
||||||
|
PRIx64 " failed\n", baddr, addr);
|
||||||
|
extent_destroy(ex);
|
||||||
|
ex = NULL;
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
baddr = addr + size;
|
||||||
|
}
|
||||||
|
/* allocate left region if available */
|
||||||
|
if (baddr < bsize)
|
||||||
|
if (extent_alloc_region(ex, baddr, bsize - baddr, EX_NOWAIT)) {
|
||||||
|
printf("psycho_alloc_extent: extent_alloc_region %"
|
||||||
|
PRIx64 "-%" PRIx64 " failed\n", baddr, bsize);
|
||||||
|
extent_destroy(ex);
|
||||||
|
ex = NULL;
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
/* print extent */
|
||||||
|
extent_print(ex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret:
|
||||||
|
/* return extent */
|
||||||
|
free(pa, M_DEVBUF);
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* grovel the OBP for various psycho properties
|
* grovel the OBP for various psycho properties
|
||||||
*/
|
*/
|
||||||
|
@ -886,8 +986,6 @@ psycho_alloc_dma_tag(pp)
|
||||||
* PCI physical addresses.
|
* PCI physical addresses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int get_childspace __P((int));
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
get_childspace(type)
|
get_childspace(type)
|
||||||
int type;
|
int type;
|
||||||
|
@ -917,6 +1015,21 @@ get_childspace(type)
|
||||||
return (ss);
|
return (ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct psycho_ranges *
|
||||||
|
get_psychorange(pp, ss)
|
||||||
|
struct psycho_pbm *pp;
|
||||||
|
int ss;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < pp->pp_nrange; i++) {
|
||||||
|
if (((pp->pp_range[i].cspace >> 24) & 0x03) == ss)
|
||||||
|
return (&pp->pp_range[i]);
|
||||||
|
}
|
||||||
|
/* not found */
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_psycho_bus_map(t, offset, size, flags, unused, hp)
|
_psycho_bus_map(t, offset, size, flags, unused, hp)
|
||||||
bus_space_tag_t t;
|
bus_space_tag_t t;
|
||||||
|
@ -928,7 +1041,9 @@ _psycho_bus_map(t, offset, size, flags, unused, hp)
|
||||||
{
|
{
|
||||||
struct psycho_pbm *pp = t->cookie;
|
struct psycho_pbm *pp = t->cookie;
|
||||||
struct psycho_softc *sc = pp->pp_sc;
|
struct psycho_softc *sc = pp->pp_sc;
|
||||||
int i, ss;
|
struct psycho_ranges *pr;
|
||||||
|
bus_addr_t paddr;
|
||||||
|
int ss;
|
||||||
|
|
||||||
DPRINTF(PDB_BUSMAP,
|
DPRINTF(PDB_BUSMAP,
|
||||||
("_psycho_bus_map: type %d off %qx sz %qx flags %d",
|
("_psycho_bus_map: type %d off %qx sz %qx flags %d",
|
||||||
|
@ -938,15 +1053,11 @@ _psycho_bus_map(t, offset, size, flags, unused, hp)
|
||||||
ss = get_childspace(t->type);
|
ss = get_childspace(t->type);
|
||||||
DPRINTF(PDB_BUSMAP, (" cspace %d", ss));
|
DPRINTF(PDB_BUSMAP, (" cspace %d", ss));
|
||||||
|
|
||||||
for (i = 0; i < pp->pp_nrange; i++) {
|
pr = get_psychorange(pp, ss);
|
||||||
bus_addr_t paddr;
|
if (pr != NULL) {
|
||||||
|
paddr = BUS_ADDR(pr->phys_hi, pr->phys_lo + offset);
|
||||||
if (((pp->pp_range[i].cspace >> 24) & 0x03) != ss)
|
DPRINTF(PDB_BUSMAP, ("\n_psycho_bus_map: mapping paddr "
|
||||||
continue;
|
"space %lx offset %lx paddr %qx\n",
|
||||||
|
|
||||||
paddr = pp->pp_range[i].phys_lo + offset;
|
|
||||||
paddr |= ((bus_addr_t)pp->pp_range[i].phys_hi<<32);
|
|
||||||
DPRINTF(PDB_BUSMAP, ("\n_psycho_bus_map: mapping paddr space %lx offset %lx paddr %qx\n",
|
|
||||||
(long)ss, (long)offset,
|
(long)ss, (long)offset,
|
||||||
(unsigned long long)paddr));
|
(unsigned long long)paddr));
|
||||||
return ((*sc->sc_bustag->sparc_bus_map)(t, paddr, size,
|
return ((*sc->sc_bustag->sparc_bus_map)(t, paddr, size,
|
||||||
|
@ -967,21 +1078,17 @@ psycho_bus_mmap(t, paddr, off, prot, flags)
|
||||||
bus_addr_t offset = paddr;
|
bus_addr_t offset = paddr;
|
||||||
struct psycho_pbm *pp = t->cookie;
|
struct psycho_pbm *pp = t->cookie;
|
||||||
struct psycho_softc *sc = pp->pp_sc;
|
struct psycho_softc *sc = pp->pp_sc;
|
||||||
int i, ss;
|
struct psycho_ranges *pr;
|
||||||
|
int ss;
|
||||||
|
|
||||||
ss = get_childspace(t->type);
|
ss = get_childspace(t->type);
|
||||||
|
|
||||||
DPRINTF(PDB_BUSMAP, ("_psycho_bus_mmap: prot %x flags %d pa %qx\n",
|
DPRINTF(PDB_BUSMAP, ("_psycho_bus_mmap: prot %x flags %d pa %qx\n",
|
||||||
prot, flags, (unsigned long long)paddr));
|
prot, flags, (unsigned long long)paddr));
|
||||||
|
|
||||||
for (i = 0; i < pp->pp_nrange; i++) {
|
pr = get_psychorange(pp, ss);
|
||||||
bus_addr_t paddr;
|
if (pr != NULL) {
|
||||||
|
paddr = BUS_ADDR(pr->phys_hi, pr->phys_lo + offset);
|
||||||
if (((pp->pp_range[i].cspace >> 24) & 0x03) != ss)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
paddr = pp->pp_range[i].phys_lo + offset;
|
|
||||||
paddr |= ((bus_addr_t)pp->pp_range[i].phys_hi<<32);
|
|
||||||
DPRINTF(PDB_BUSMAP, ("\n_psycho_bus_mmap: mapping paddr "
|
DPRINTF(PDB_BUSMAP, ("\n_psycho_bus_mmap: mapping paddr "
|
||||||
"space %lx offset %lx paddr %qx\n",
|
"space %lx offset %lx paddr %qx\n",
|
||||||
(long)ss, (long)offset,
|
(long)ss, (long)offset,
|
||||||
|
@ -993,6 +1100,45 @@ psycho_bus_mmap(t, paddr, off, prot, flags)
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a PCI offset address from bus_space_handle_t.
|
||||||
|
*/
|
||||||
|
bus_addr_t
|
||||||
|
psycho_bus_offset(t, hp)
|
||||||
|
bus_space_tag_t t;
|
||||||
|
bus_space_handle_t *hp;
|
||||||
|
{
|
||||||
|
struct psycho_pbm *pp = t->cookie;
|
||||||
|
struct psycho_ranges *pr;
|
||||||
|
bus_addr_t addr, offset;
|
||||||
|
vaddr_t va;
|
||||||
|
int ss;
|
||||||
|
|
||||||
|
addr = hp->_ptr;
|
||||||
|
ss = get_childspace(t->type);
|
||||||
|
DPRINTF(PDB_BUSMAP, ("psycho_bus_offset: type %d addr %" PRIx64
|
||||||
|
" cspace %d", t->type, addr, ss));
|
||||||
|
|
||||||
|
pr = get_psychorange(pp, ss);
|
||||||
|
if (pr != NULL) {
|
||||||
|
if (!PHYS_ASI(hp->_asi)) {
|
||||||
|
va = trunc_page((vaddr_t)addr);
|
||||||
|
if (pmap_extract(pmap_kernel(), va, &addr) == FALSE) {
|
||||||
|
DPRINTF(PDB_BUSMAP,
|
||||||
|
("\n pmap_extract FAILED\n"));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
addr += hp->_ptr & PGOFSET;
|
||||||
|
}
|
||||||
|
offset = BUS_ADDR_PADDR(addr) - pr->phys_lo;
|
||||||
|
DPRINTF(PDB_BUSMAP, ("\npsycho_bus_offset: paddr %" PRIx64
|
||||||
|
" offset %" PRIx64 "\n", addr, offset));
|
||||||
|
return (offset);
|
||||||
|
}
|
||||||
|
DPRINTF(PDB_BUSMAP, ("\n FAILED\n"));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* install an interrupt handler for a PCI device
|
* install an interrupt handler for a PCI device
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: psychovar.h,v 1.8 2002/06/20 18:26:24 eeh Exp $ */
|
/* $NetBSD: psychovar.h,v 1.9 2003/03/22 06:33:10 nakayama Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2000 Matthew R. Green
|
* Copyright (c) 1999, 2000 Matthew R. Green
|
||||||
|
@ -51,6 +51,10 @@ struct psycho_pbm {
|
||||||
int pp_nrange;
|
int pp_nrange;
|
||||||
int pp_nintmap;
|
int pp_nintmap;
|
||||||
|
|
||||||
|
/* extents for free bus space */
|
||||||
|
struct extent *pp_exmem;
|
||||||
|
struct extent *pp_exio;
|
||||||
|
|
||||||
/* chipset tag for this instance */
|
/* chipset tag for this instance */
|
||||||
pci_chipset_tag_t pp_pc;
|
pci_chipset_tag_t pp_pc;
|
||||||
|
|
||||||
|
@ -59,6 +63,12 @@ struct psycho_pbm {
|
||||||
bus_space_tag_t pp_iot;
|
bus_space_tag_t pp_iot;
|
||||||
bus_dma_tag_t pp_dmat;
|
bus_dma_tag_t pp_dmat;
|
||||||
int pp_bus;
|
int pp_bus;
|
||||||
|
int pp_busmax;
|
||||||
|
struct pp_busnode {
|
||||||
|
int node;
|
||||||
|
int (*valid) __P((void *));
|
||||||
|
void *arg;
|
||||||
|
} (*pp_busnode)[256];
|
||||||
int pp_flags;
|
int pp_flags;
|
||||||
|
|
||||||
/* and pointers into the psycho regs for our bits */
|
/* and pointers into the psycho regs for our bits */
|
||||||
|
@ -113,6 +123,9 @@ struct psycho_softc {
|
||||||
struct iommu_state *sc_is;
|
struct iommu_state *sc_is;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* get a PCI offset address from bus_space_handle_t */
|
||||||
|
bus_addr_t psycho_bus_offset __P((bus_space_tag_t, bus_space_handle_t *));
|
||||||
|
|
||||||
/* config space is per-psycho. mem/io/dma are per-pci bus */
|
/* config space is per-psycho. mem/io/dma are per-pci bus */
|
||||||
bus_dma_tag_t psycho_alloc_dma_tag __P((struct psycho_pbm *));
|
bus_dma_tag_t psycho_alloc_dma_tag __P((struct psycho_pbm *));
|
||||||
bus_space_tag_t psycho_alloc_bus_tag __P((struct psycho_pbm *, int));
|
bus_space_tag_t psycho_alloc_bus_tag __P((struct psycho_pbm *, int));
|
||||||
|
|
Loading…
Reference in New Issue