version 1.33.2.2, 2001/09/13 01:14:40 |
version 1.33.2.3, 2002/01/10 19:49:17 |
Line 96 static void psycho_iommu_init __P((struc |
|
Line 96 static void psycho_iommu_init __P((struc |
|
* 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 psycho_bus_mmap __P((bus_space_tag_t, bus_type_t, bus_addr_t, |
static paddr_t psycho_bus_mmap __P((bus_space_tag_t, bus_addr_t, off_t, int, int)); |
int, bus_space_handle_t *)); |
|
static int _psycho_bus_map __P((bus_space_tag_t, bus_type_t, bus_addr_t, |
static int _psycho_bus_map __P((bus_space_tag_t, bus_type_t, bus_addr_t, |
bus_size_t, int, vaddr_t, |
bus_size_t, int, vaddr_t, |
bus_space_handle_t *)); |
bus_space_handle_t *)); |
Line 191 psycho_match(parent, match, aux) |
|
Line 190 psycho_match(parent, match, aux) |
|
void *aux; |
void *aux; |
{ |
{ |
struct mainbus_attach_args *ma = aux; |
struct mainbus_attach_args *ma = aux; |
char *model = getpropstring(ma->ma_node, "model"); |
char *model = PROM_getpropstring(ma->ma_node, "model"); |
int i; |
int i; |
|
|
/* match on a name of "pci" and a sabre or a psycho */ |
/* match on a name of "pci" and a sabre or a psycho */ |
Line 200 psycho_match(parent, match, aux) |
|
Line 199 psycho_match(parent, match, aux) |
|
if (strcmp(model, psycho_names[i].p_name) == 0) |
if (strcmp(model, psycho_names[i].p_name) == 0) |
return (1); |
return (1); |
|
|
model = getpropstring(ma->ma_node, "compatible"); |
model = PROM_getpropstring(ma->ma_node, "compatible"); |
for (i=0; psycho_names[i].p_name; i++) |
for (i=0; psycho_names[i].p_name; i++) |
if (strcmp(model, psycho_names[i].p_name) == 0) |
if (strcmp(model, psycho_names[i].p_name) == 0) |
return (1); |
return (1); |
Line 234 psycho_attach(parent, self, aux) |
|
Line 233 psycho_attach(parent, self, aux) |
|
u_int64_t csr; |
u_int64_t csr; |
int psycho_br[2], n, i; |
int psycho_br[2], n, i; |
struct pci_ctl *pci_ctl; |
struct pci_ctl *pci_ctl; |
char *model = getpropstring(ma->ma_node, "model"); |
char *model = PROM_getpropstring(ma->ma_node, "model"); |
|
|
printf("\n"); |
printf("\n"); |
|
|
Line 251 psycho_attach(parent, self, aux) |
|
Line 250 psycho_attach(parent, self, aux) |
|
goto found; |
goto found; |
} |
} |
|
|
model = getpropstring(ma->ma_node, "compatible"); |
model = PROM_getpropstring(ma->ma_node, "compatible"); |
for (i=0; psycho_names[i].p_name; i++) |
for (i=0; psycho_names[i].p_name; i++) |
if (strcmp(model, psycho_names[i].p_name) == 0) { |
if (strcmp(model, psycho_names[i].p_name) == 0) { |
sc->sc_mode = psycho_names[i].p_type; |
sc->sc_mode = psycho_names[i].p_type; |
|
|
* |
* |
* For the moment, 32KB should be more than enough. |
* For the moment, 32KB should be more than enough. |
*/ |
*/ |
|
sc->sc_is = malloc(sizeof(struct iommu_state), |
|
M_DEVBUF, M_NOWAIT); |
|
if (sc->sc_is == NULL) |
|
panic("psycho_attach: malloc iommu_state"); |
|
|
|
|
|
sc->sc_is->is_sb[0] = 0; |
|
sc->sc_is->is_sb[1] = 0; |
|
if (PROM_getproplen(sc->sc_node, "no-streaming-cache") >= 0) |
|
sc->sc_is->is_sb[0] = &pci_ctl->pci_strbuf; |
|
|
psycho_iommu_init(sc, 2); |
psycho_iommu_init(sc, 2); |
|
|
sc->sc_configtag = psycho_alloc_config_tag(sc->sc_psycho_this); |
sc->sc_configtag = psycho_alloc_config_tag(sc->sc_psycho_this); |
|
|
sc->sc_is = osc->sc_is; |
sc->sc_is = osc->sc_is; |
sc->sc_configtag = osc->sc_configtag; |
sc->sc_configtag = osc->sc_configtag; |
sc->sc_configaddr = osc->sc_configaddr; |
sc->sc_configaddr = osc->sc_configaddr; |
|
|
|
if (PROM_getproplen(sc->sc_node, "no-streaming-cache") >= 0) |
|
sc->sc_is->is_sb[1] = &pci_ctl->pci_strbuf; |
|
iommu_reset(sc->sc_is); |
} |
} |
|
|
/* |
/* |
Line 556 psycho_get_bus_range(node, brp) |
|
Line 570 psycho_get_bus_range(node, brp) |
|
{ |
{ |
int n; |
int n; |
|
|
if (getprop(node, "bus-range", sizeof(*brp), &n, (void **)&brp)) |
if (PROM_getprop(node, "bus-range", sizeof(*brp), &n, (void **)&brp)) |
panic("could not get psycho bus-range"); |
panic("could not get psycho bus-range"); |
if (n != 2) |
if (n != 2) |
panic("broken psycho bus-range"); |
panic("broken psycho bus-range"); |
Line 570 psycho_get_ranges(node, rp, np) |
|
Line 584 psycho_get_ranges(node, rp, np) |
|
int *np; |
int *np; |
{ |
{ |
|
|
if (getprop(node, "ranges", sizeof(**rp), np, (void **)rp)) |
if (PROM_getprop(node, "ranges", sizeof(**rp), np, (void **)rp)) |
panic("could not get psycho ranges"); |
panic("could not get psycho ranges"); |
DPRINTF(PDB_PROM, ("psycho debug: got `ranges' for node %08x: %d entries\n", node, *np)); |
DPRINTF(PDB_PROM, ("psycho debug: got `ranges' for node %08x: %d entries\n", node, *np)); |
} |
} |
|
|
{ |
{ |
struct psycho_softc *sc = (struct psycho_softc *)arg; |
struct psycho_softc *sc = (struct psycho_softc *)arg; |
struct psychoreg *regs = sc->sc_regs; |
struct psychoreg *regs = sc->sc_regs; |
|
long long afsr = regs->psy_ue_afsr; |
|
long long afar = regs->psy_ue_afar; |
|
char bits[128]; |
|
|
/* |
/* |
* It's uncorrectable. Dump the regs and panic. |
* It's uncorrectable. Dump the regs and panic. |
*/ |
*/ |
|
panic("%s: uncorrectable DMA error AFAR %llx pa %llx AFSR %llx:\n%s", |
panic("%s: uncorrectable DMA error AFAR %llx AFSR %llx\n", |
sc->sc_dev.dv_xname, afar, |
sc->sc_dev.dv_xname, |
(long long)iommu_extract(sc->sc_is, (vaddr_t)afar), afsr, |
(long long)regs->psy_ue_afar, (long long)regs->psy_ue_afsr); |
bitmask_snprintf(afsr, PSYCHO_UE_AFSR_BITS, |
|
bits, sizeof(bits))); |
return (1); |
return (1); |
} |
} |
static int |
static int |
Line 682 psycho_iommu_init(sc, tsbsize) |
|
Line 700 psycho_iommu_init(sc, tsbsize) |
|
int tsbsize; |
int tsbsize; |
{ |
{ |
char *name; |
char *name; |
struct iommu_state *is; |
struct iommu_state *is = sc->sc_is; |
u_int32_t iobase = -1; |
u_int32_t iobase = -1; |
int *vdma = NULL; |
int *vdma = NULL; |
int nitem; |
int nitem; |
|
|
is = malloc(sizeof(struct iommu_state), M_DEVBUF, M_NOWAIT); |
|
if (is == NULL) |
|
panic("psycho_iommu_init: malloc is"); |
|
|
|
sc->sc_is = is; |
|
|
|
/* punch in our copies */ |
/* punch in our copies */ |
is->is_bustag = sc->sc_bustag; |
is->is_bustag = sc->sc_bustag; |
is->is_iommu = &sc->sc_regs->psy_iommu; |
is->is_iommu = &sc->sc_regs->psy_iommu; |
|
|
if (getproplen(sc->sc_node, "no-streaming-cache") < 0) |
|
is->is_sb = 0; |
|
else |
|
is->is_sb = &sc->sc_regs->psy_iommu_strbuf; |
|
|
|
/* |
/* |
* Separate the men from the boys. Get the `virtual-dma' |
* Separate the men from the boys. Get the `virtual-dma' |
* property for sabre and use that to make sure the damn |
* property for sabre and use that to make sure the damn |
Line 710 psycho_iommu_init(sc, tsbsize) |
|
Line 717 psycho_iommu_init(sc, tsbsize) |
|
* We could query the `#virtual-dma-size-cells' and |
* We could query the `#virtual-dma-size-cells' and |
* `#virtual-dma-addr-cells' and DTRT, but I'm lazy. |
* `#virtual-dma-addr-cells' and DTRT, but I'm lazy. |
*/ |
*/ |
if (!getprop(sc->sc_node, "virtual-dma", sizeof(vdma), &nitem, |
if (!PROM_getprop(sc->sc_node, "virtual-dma", sizeof(vdma), &nitem, |
(void **)&vdma)) { |
(void **)&vdma)) { |
/* Damn. Gotta use these values. */ |
/* Damn. Gotta use these values. */ |
iobase = vdma[0]; |
iobase = vdma[0]; |
Line 867 _psycho_bus_map(t, btype, offset, size, |
|
Line 874 _psycho_bus_map(t, btype, offset, size, |
|
return (EINVAL); |
return (EINVAL); |
} |
} |
|
|
static int |
static paddr_t |
psycho_bus_mmap(t, btype, paddr, flags, hp) |
psycho_bus_mmap(t, paddr, off, prot, flags) |
bus_space_tag_t t; |
bus_space_tag_t t; |
bus_type_t btype; |
|
bus_addr_t paddr; |
bus_addr_t paddr; |
|
off_t off; |
|
int prot; |
int flags; |
int flags; |
bus_space_handle_t *hp; |
|
{ |
{ |
bus_addr_t offset = paddr; |
bus_addr_t offset = paddr; |
struct psycho_pbm *pp = t->cookie; |
struct psycho_pbm *pp = t->cookie; |
Line 882 psycho_bus_mmap(t, btype, paddr, flags, |
|
Line 889 psycho_bus_mmap(t, btype, paddr, flags, |
|
|
|
ss = get_childspace(t->type); |
ss = get_childspace(t->type); |
|
|
DPRINTF(PDB_BUSMAP, ("_psycho_bus_mmap: type %d flags %d pa %qx\n", btype, flags, (unsigned long long)paddr)); |
DPRINTF(PDB_BUSMAP, ("_psycho_bus_mmap: prot %x flags %d pa %qx\n", |
|
prot, flags, (unsigned long long)paddr)); |
|
|
for (i = 0; i < pp->pp_nrange; i++) { |
for (i = 0; i < pp->pp_nrange; i++) { |
bus_addr_t paddr; |
bus_addr_t paddr; |
Line 892 psycho_bus_mmap(t, btype, paddr, flags, |
|
Line 900 psycho_bus_mmap(t, btype, paddr, flags, |
|
|
|
paddr = pp->pp_range[i].phys_lo + offset; |
paddr = pp->pp_range[i].phys_lo + offset; |
paddr |= ((bus_addr_t)pp->pp_range[i].phys_hi<<32); |
paddr |= ((bus_addr_t)pp->pp_range[i].phys_hi<<32); |
DPRINTF(PDB_BUSMAP, ("\n_psycho_bus_mmap: mapping paddr space %lx offset %lx paddr %qx\n", |
DPRINTF(PDB_BUSMAP, ("\n_psycho_bus_mmap: 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 (bus_space_mmap(sc->sc_bustag, 0, paddr, |
return (bus_space_mmap(sc->sc_bustag, paddr, off, |
flags, hp)); |
prot, flags)); |
} |
} |
|
|
return (-1); |
return (-1); |