diff options
author | dfr <dfr@FreeBSD.org> | 2000-08-28 21:48:13 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2000-08-28 21:48:13 +0000 |
commit | dd8b44b3958fa67d802cbbec7c7d82f7fb476229 (patch) | |
tree | 61496c144b3ecd15192a2e07e755754e18346bc9 /sys/alpha/pci | |
parent | 9ed8ded4d312c58a27de9402fd9802e78a591cb9 (diff) | |
download | FreeBSD-src-dd8b44b3958fa67d802cbbec7c7d82f7fb476229.zip FreeBSD-src-dd8b44b3958fa67d802cbbec7c7d82f7fb476229.tar.gz |
* Completely rewrite the alpha busspace to hide the implementation from
the drivers.
* Remove legacy inx/outx support from chipset and replace with macros
which call busspace.
* Rework pci config accesses to route through the pcib device instead of
calling a MD function directly.
With these changes it is possible to cleanly support machines which have
more than one independantly numbered PCI busses. As a bonus, the new
busspace implementation should be measurably faster than the old one.
Diffstat (limited to 'sys/alpha/pci')
-rw-r--r-- | sys/alpha/pci/alphapci_if.m | 59 | ||||
-rw-r--r-- | sys/alpha/pci/apecs.c | 325 | ||||
-rw-r--r-- | sys/alpha/pci/apecs_pci.c | 115 | ||||
-rw-r--r-- | sys/alpha/pci/apecsvar.h | 5 | ||||
-rw-r--r-- | sys/alpha/pci/bwx.c | 131 | ||||
-rw-r--r-- | sys/alpha/pci/cia.c | 541 | ||||
-rw-r--r-- | sys/alpha/pci/cia_pci.c | 332 | ||||
-rw-r--r-- | sys/alpha/pci/dwlpx_pci.c | 80 | ||||
-rw-r--r-- | sys/alpha/pci/irongate.c | 255 | ||||
-rw-r--r-- | sys/alpha/pci/irongate_pci.c | 127 | ||||
-rw-r--r-- | sys/alpha/pci/lca.c | 252 | ||||
-rw-r--r-- | sys/alpha/pci/lca_pci.c | 111 | ||||
-rw-r--r-- | sys/alpha/pci/lcavar.h | 4 | ||||
-rw-r--r-- | sys/alpha/pci/mcpcia_pci.c | 80 | ||||
-rw-r--r-- | sys/alpha/pci/pcibus.c | 151 | ||||
-rw-r--r-- | sys/alpha/pci/pcibus.h | 2 | ||||
-rw-r--r-- | sys/alpha/pci/swiz.c | 154 | ||||
-rw-r--r-- | sys/alpha/pci/t2.c | 259 | ||||
-rw-r--r-- | sys/alpha/pci/t2_pci.c | 114 | ||||
-rw-r--r-- | sys/alpha/pci/t2var.h | 2 | ||||
-rw-r--r-- | sys/alpha/pci/tsunami.c | 308 | ||||
-rw-r--r-- | sys/alpha/pci/tsunami_pci.c | 271 |
22 files changed, 1468 insertions, 2210 deletions
diff --git a/sys/alpha/pci/alphapci_if.m b/sys/alpha/pci/alphapci_if.m new file mode 100644 index 0000000..1525af9 --- /dev/null +++ b/sys/alpha/pci/alphapci_if.m @@ -0,0 +1,59 @@ +# +# Copyright (c) 2000 Doug Rabson +# 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. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# + +#include <sys/bus.h> +#include <alpha/pci/pcibus.h> + +INTERFACE alphapci; + +CODE { + static void *null_cvt(device_t dev, vm_offset_t ba) + { + return 0; + } +}; + +METHOD void * cvt_dense { + device_t dev; + vm_offset_t ba; +} DEFAULT null_cvt; + +METHOD void * cvt_bwx { + device_t dev; + vm_offset_t ba; +} DEFAULT null_cvt; + +METHOD struct alpha_busspace * get_bustag { + device_t dev; + int type; +} DEFAULT pci_get_bustag; + +METHOD struct rman * get_rman { + device_t dev; + int type; +} DEFAULT pci_get_rman; diff --git a/sys/alpha/pci/apecs.c b/sys/alpha/pci/apecs.c index d23df8a..e15aee1 100644 --- a/sys/alpha/pci/apecs.c +++ b/sys/alpha/pci/apecs.c @@ -94,105 +94,14 @@ struct apecs_softc { #define APECS_SOFTC(dev) (struct apecs_softc*) device_get_softc(dev) -static alpha_chipset_inb_t apecs_swiz_inb; -static alpha_chipset_inw_t apecs_swiz_inw; -static alpha_chipset_inl_t apecs_swiz_inl; -static alpha_chipset_outb_t apecs_swiz_outb; -static alpha_chipset_outw_t apecs_swiz_outw; -static alpha_chipset_outl_t apecs_swiz_outl; -static alpha_chipset_readb_t apecs_swiz_readb; -static alpha_chipset_readw_t apecs_swiz_readw; -static alpha_chipset_readl_t apecs_swiz_readl; -static alpha_chipset_writeb_t apecs_swiz_writeb; -static alpha_chipset_writew_t apecs_swiz_writew; -static alpha_chipset_writel_t apecs_swiz_writel; -static alpha_chipset_maxdevs_t apecs_swiz_maxdevs; -static alpha_chipset_cfgreadb_t apecs_swiz_cfgreadb; -static alpha_chipset_cfgreadw_t apecs_swiz_cfgreadw; -static alpha_chipset_cfgreadl_t apecs_swiz_cfgreadl; -static alpha_chipset_cfgwriteb_t apecs_swiz_cfgwriteb; -static alpha_chipset_cfgwritew_t apecs_swiz_cfgwritew; -static alpha_chipset_cfgwritel_t apecs_swiz_cfgwritel; -static alpha_chipset_addrcvt_t apecs_cvt_dense; static alpha_chipset_read_hae_t apecs_read_hae; static alpha_chipset_write_hae_t apecs_write_hae; static alpha_chipset_t apecs_swiz_chipset = { - apecs_swiz_inb, - apecs_swiz_inw, - apecs_swiz_inl, - apecs_swiz_outb, - apecs_swiz_outw, - apecs_swiz_outl, - apecs_swiz_readb, - apecs_swiz_readw, - apecs_swiz_readl, - apecs_swiz_writeb, - apecs_swiz_writew, - apecs_swiz_writel, - apecs_swiz_maxdevs, - apecs_swiz_cfgreadb, - apecs_swiz_cfgreadw, - apecs_swiz_cfgreadl, - apecs_swiz_cfgwriteb, - apecs_swiz_cfgwritew, - apecs_swiz_cfgwritel, - apecs_cvt_dense, - NULL, apecs_read_hae, apecs_write_hae, }; -static int -apecs_swiz_maxdevs(u_int b) -{ - return 12; /* XXX */ -} - - - -static u_int8_t -apecs_swiz_inb(u_int32_t port) -{ - alpha_mb(); - return SPARSE_READ_BYTE(KV(APECS_PCI_SIO), port); -} - -static u_int16_t -apecs_swiz_inw(u_int32_t port) -{ - alpha_mb(); - return SPARSE_READ_WORD(KV(APECS_PCI_SIO), port); -} - -static u_int32_t -apecs_swiz_inl(u_int32_t port) -{ - alpha_mb(); - return SPARSE_READ_LONG(KV(APECS_PCI_SIO), port); -} - -static void -apecs_swiz_outb(u_int32_t port, u_int8_t data) -{ - SPARSE_WRITE_BYTE(KV(APECS_PCI_SIO), port, data); - alpha_wmb(); -} - -static void -apecs_swiz_outw(u_int32_t port, u_int16_t data) -{ - SPARSE_WRITE_WORD(KV(APECS_PCI_SIO), port, data); - alpha_wmb(); -} - -static void -apecs_swiz_outl(u_int32_t port, u_int32_t data) -{ - SPARSE_WRITE_LONG(KV(APECS_PCI_SIO), port, data); - alpha_wmb(); -} - /* * Memory functions. * @@ -204,14 +113,14 @@ apecs_swiz_outl(u_int32_t port, u_int32_t data) static u_int32_t apecs_hae_mem; #define REG1 (1UL << 24) -static __inline void -apecs_swiz_set_hae_mem(u_int32_t *pa) +static u_int32_t +apecs_set_hae_mem(void *arg, u_int32_t pa) { int s; u_int32_t msb; - if(*pa >= REG1){ - msb = *pa & 0xf8000000; - *pa -= msb; + if (pa >= REG1){ + msb = pa & 0xf8000000; + pa -= msb; s = splhigh(); if (msb != apecs_hae_mem) { apecs_hae_mem = msb; @@ -221,217 +130,7 @@ apecs_swiz_set_hae_mem(u_int32_t *pa) } splx(s); } -} - -static u_int8_t -apecs_swiz_readb(u_int32_t pa) -{ - alpha_mb(); - apecs_swiz_set_hae_mem(&pa); - return SPARSE_READ_BYTE(KV(APECS_PCI_SPARSE), pa); -} - -static u_int16_t -apecs_swiz_readw(u_int32_t pa) -{ - alpha_mb(); - apecs_swiz_set_hae_mem(&pa); - return SPARSE_READ_WORD(KV(APECS_PCI_SPARSE), pa); -} - -static u_int32_t -apecs_swiz_readl(u_int32_t pa) -{ - alpha_mb(); - apecs_swiz_set_hae_mem(&pa); - return SPARSE_READ_LONG(KV(APECS_PCI_SPARSE), pa); -} - -static void -apecs_swiz_writeb(u_int32_t pa, u_int8_t data) -{ - apecs_swiz_set_hae_mem(&pa); - SPARSE_WRITE_BYTE(KV(APECS_PCI_SPARSE), pa, data); - alpha_wmb(); -} - -static void -apecs_swiz_writew(u_int32_t pa, u_int16_t data) -{ - apecs_swiz_set_hae_mem(&pa); - SPARSE_WRITE_WORD(KV(APECS_PCI_SPARSE), pa, data); - alpha_wmb(); -} - - -static void -apecs_swiz_writel(u_int32_t pa, u_int32_t data) -{ - apecs_swiz_set_hae_mem(&pa); - SPARSE_WRITE_LONG(KV(APECS_PCI_SPARSE), pa, data); - alpha_wmb(); - -} - - -#define APECS_SWIZ_CFGOFF(b, s, f, r) \ - (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) - -#define APECS_TYPE1_SETUP(b,s,old_haxr2) if((b)) { \ - do { \ - (s) = splhigh(); \ - (old_haxr2) = REGVAL(EPIC_HAXR2); \ - alpha_mb(); \ - REGVAL(EPIC_HAXR2) = (old_haxr2) | 0x1; \ - alpha_mb(); \ - } while(0); \ -} - -#define APECS_TYPE1_TEARDOWN(b,s,old_haxr2) if((b)) { \ - do { \ - alpha_mb(); \ - REGVAL(EPIC_HAXR2) = (old_haxr2); \ - alpha_mb(); \ - splx((s)); \ - } while(0); \ -} - -#define SWIZ_CFGREAD(b, s, f, r, width, type) \ - type val = ~0; \ - int ipl = 0; \ - u_int32_t old_haxr2 = 0; \ - struct apecs_softc* sc = APECS_SOFTC(apecs0); \ - vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); \ - vm_offset_t kv = SPARSE_##width##_ADDRESS(sc->cfg0_base, off); \ - alpha_mb(); \ - APECS_TYPE1_SETUP(b,ipl,old_haxr2); \ - if (!badaddr((caddr_t)kv, sizeof(type))) { \ - val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \ - } \ - APECS_TYPE1_TEARDOWN(b,ipl,old_haxr2); \ - return val; - -#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) \ - int ipl = 0; \ - u_int32_t old_haxr2 = 0; \ - struct apecs_softc* sc = APECS_SOFTC(apecs0); \ - vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); \ - vm_offset_t kv = SPARSE_##width##_ADDRESS(sc->cfg0_base, off); \ - alpha_mb(); \ - APECS_TYPE1_SETUP(b,ipl,old_haxr2); \ - if (!badaddr((caddr_t)kv, sizeof(type))) { \ - SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \ - alpha_wmb(); \ - } \ - APECS_TYPE1_TEARDOWN(b,ipl,old_haxr2); \ - return; - -#if 1 -static u_int8_t -apecs_swiz_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - SWIZ_CFGREAD(b, s, f, r, BYTE, u_int8_t); -} - -static u_int16_t -apecs_swiz_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - SWIZ_CFGREAD(b, s, f, r, WORD, u_int16_t); -} - -static u_int32_t -apecs_swiz_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - SWIZ_CFGREAD(b, s, f, r, LONG, u_int32_t); -} - -static void -apecs_swiz_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data) -{ - SWIZ_CFGWRITE(b, s, f, r, data, BYTE, u_int8_t); -} - -static void -apecs_swiz_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data) -{ - SWIZ_CFGWRITE(b, s, f, r, data, WORD, u_int16_t); -} - -static void -apecs_swiz_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data) -{ - SWIZ_CFGWRITE(b, s, f, r, data, LONG, u_int32_t); -} - -#else -static u_int8_t -apecs_swiz_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - struct apecs_softc* sc = APECS_SOFTC(apecs0); - vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); - alpha_mb(); - if (badaddr((caddr_t)(sc->cfg0_base + SPARSE_BYTE_OFFSET(off)), 1)) return ~0; - return SPARSE_READ_BYTE(sc->cfg0_base, off); -} - -static u_int16_t -apecs_swiz_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - struct apecs_softc* sc = APECS_SOFTC(apecs0); - vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); - alpha_mb(); - if (badaddr((caddr_t)(sc->cfg0_base + SPARSE_WORD_OFFSET(off)), 2)) return ~0; - return SPARSE_READ_WORD(sc->cfg0_base, off); -} - -static u_int32_t -apecs_swiz_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - struct apecs_softc* sc = APECS_SOFTC(apecs0); - vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); - alpha_mb(); - if (badaddr((caddr_t)(sc->cfg0_base + SPARSE_LONG_OFFSET(off)), 4)) return ~0; - return SPARSE_READ_LONG(sc->cfg0_base, off); -} - -static void -apecs_swiz_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data) -{ - struct apecs_softc* sc = APECS_SOFTC(apecs0); - vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); - if (badaddr((caddr_t)(sc->cfg0_base + SPARSE_BYTE_OFFSET(off)), 1)) return; - SPARSE_WRITE_BYTE(sc->cfg0_base, off, data); - alpha_wmb(); -} - -static void -apecs_swiz_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data) -{ - struct apecs_softc* sc = APECS_SOFTC(apecs0); - vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); - if (badaddr((caddr_t)(sc->cfg0_base + SPARSE_WORD_OFFSET(off)), 2)) return; - SPARSE_WRITE_WORD(sc->cfg0_base, off, data); - alpha_wmb(); -} - -static void -apecs_swiz_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data) -{ - struct apecs_softc* sc = APECS_SOFTC(apecs0); - vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); - if (badaddr((caddr_t)(sc->cfg0_base + SPARSE_LONG_OFFSET(off)), 4)) return; - SPARSE_WRITE_LONG(sc->cfg0_base, off, data); - alpha_wmb(); -} -#endif - - -static vm_offset_t -apecs_cvt_dense(vm_offset_t addr) -{ - addr &= 0xffffffffUL; - return (addr | APECS_PCI_DENSE); - + return pa; } static u_int64_t @@ -444,7 +143,7 @@ static void apecs_write_hae(u_int64_t hae) { u_int32_t pa = hae; - apecs_swiz_set_hae_mem(&pa); + apecs_set_hae_mem(0, pa); } static int apecs_probe(device_t dev); @@ -495,7 +194,7 @@ apecs_sgmap_invalidate(void) } static void -apecs_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa) +apecs_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa) { u_int64_t *sgtable = arg; int index = alpha_btop(ba - APECS_SGMAP_BASE); @@ -544,10 +243,18 @@ void apecs_init() { static int initted = 0; + static struct swiz_space io_space, mem_space; if (initted) return; initted = 1; + swiz_init_space(&io_space, KV(APECS_PCI_SIO)); + swiz_init_space_hae(&mem_space, KV(APECS_PCI_SPARSE), + apecs_set_hae_mem, 0); + + busspace_isa_io = (struct alpha_busspace *) &io_space; + busspace_isa_mem = (struct alpha_busspace *) &mem_space; + chipset = apecs_swiz_chipset; if (platform.pci_intr_init) diff --git a/sys/alpha/pci/apecs_pci.c b/sys/alpha/pci/apecs_pci.c index bb1b8bd..287b2d9 100644 --- a/sys/alpha/pci/apecs_pci.c +++ b/sys/alpha/pci/apecs_pci.c @@ -34,6 +34,15 @@ #include <machine/bus.h> #include <sys/rman.h> #include <pci/pcivar.h> +#include <machine/swiz.h> + +#include <alpha/pci/apecsreg.h> +#include <alpha/pci/apecsvar.h> + +#include "alphapci_if.h" +#include "pcib_if.h" + +#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa) static devclass_t pcib_devclass; @@ -50,13 +59,109 @@ apecs_pcib_probe(device_t dev) static int apecs_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result) { - if (which == PCIB_IVAR_HOSE) { + if (which == PCIB_IVAR_BUS) { *result = 0; return 0; } return ENOENT; } +static void * +apecs_pcib_cvt_dense(device_t dev, vm_offset_t addr) +{ + addr &= 0xffffffffUL; + return (void *) KV(addr | APECS_PCI_DENSE); +} + +static int +apecs_pcib_maxslots(device_t dev) +{ + return 31; +} + +#define APECS_SWIZ_CFGOFF(b, s, f, r) \ + (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) + +#define APECS_TYPE1_SETUP(b,s,old_haxr2) if((b)) { \ + do { \ + (s) = splhigh(); \ + (old_haxr2) = REGVAL(EPIC_HAXR2); \ + alpha_mb(); \ + REGVAL(EPIC_HAXR2) = (old_haxr2) | 0x1; \ + alpha_mb(); \ + } while(0); \ +} + +#define APECS_TYPE1_TEARDOWN(b,s,old_haxr2) if((b)) { \ + do { \ + alpha_mb(); \ + REGVAL(EPIC_HAXR2) = (old_haxr2); \ + alpha_mb(); \ + splx((s)); \ + } while(0); \ +} + +#define SWIZ_CFGREAD(b, s, f, r, width, type) do { \ + type val = ~0; \ + int ipl = 0; \ + u_int32_t old_haxr2 = 0; \ + vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); \ + vm_offset_t kv = \ + SPARSE_##width##_ADDRESS(KV(APECS_PCI_CONF), off); \ + alpha_mb(); \ + APECS_TYPE1_SETUP(b,ipl,old_haxr2); \ + if (!badaddr((caddr_t)kv, sizeof(type))) { \ + val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \ + } \ + APECS_TYPE1_TEARDOWN(b,ipl,old_haxr2); \ + return val; \ +} while (0) + +#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) do { \ + int ipl = 0; \ + u_int32_t old_haxr2 = 0; \ + vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); \ + vm_offset_t kv = \ + SPARSE_##width##_ADDRESS(KV(APECS_PCI_CONF), off); \ + alpha_mb(); \ + APECS_TYPE1_SETUP(b,ipl,old_haxr2); \ + if (!badaddr((caddr_t)kv, sizeof(type))) { \ + SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \ + alpha_wmb(); \ + } \ + APECS_TYPE1_TEARDOWN(b,ipl,old_haxr2); \ + return; \ +} while (0) + +u_int32_t +apecs_pcib_read_config(device_t dev, int b, int s, int f, + int reg, int width) +{ + switch (width) { + case 1: + SWIZ_CFGREAD(b, s, f, reg, BYTE, u_int8_t); + case 2: + SWIZ_CFGREAD(b, s, f, reg, WORD, u_int16_t); + case 4: + SWIZ_CFGREAD(b, s, f, reg, LONG, u_int32_t); + } + return ~0; +} + +static void +apecs_pcib_write_config(device_t dev, int b, int s, int f, + int reg, u_int32_t val, int width) +{ + switch (width) { + case 1: + SWIZ_CFGWRITE(b, s, f, reg, val, BYTE, u_int8_t); + case 2: + SWIZ_CFGWRITE(b, s, f, reg, val, WORD, u_int16_t); + case 4: + SWIZ_CFGWRITE(b, s, f, reg, val, LONG, u_int32_t); + } +} + static device_method_t apecs_pcib_methods[] = { /* Device interface */ DEVMETHOD(device_probe, apecs_pcib_probe), @@ -72,6 +177,14 @@ static device_method_t apecs_pcib_methods[] = { DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + /* alphapci interface */ + DEVMETHOD(alphapci_cvt_dense, apecs_pcib_cvt_dense), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, apecs_pcib_maxslots), + DEVMETHOD(pcib_read_config, apecs_pcib_read_config), + DEVMETHOD(pcib_write_config, apecs_pcib_write_config), + { 0, 0 } }; diff --git a/sys/alpha/pci/apecsvar.h b/sys/alpha/pci/apecsvar.h index a5fa82e..56ade54 100644 --- a/sys/alpha/pci/apecsvar.h +++ b/sys/alpha/pci/apecsvar.h @@ -26,5 +26,8 @@ * $FreeBSD$ */ -extern void apecs_init(void); +struct device; +extern void apecs_init(void); +u_int32_t apecs_pcib_read_config(struct device *dev, int b, int s, int f, + int reg, int width); diff --git a/sys/alpha/pci/bwx.c b/sys/alpha/pci/bwx.c new file mode 100644 index 0000000..9dd0e92 --- /dev/null +++ b/sys/alpha/pci/bwx.c @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 2000 Doug Rabson + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/kobj.h> + +#include <machine/bus.h> +#include <machine/bwx.h> + +static u_int8_t +bwx_read_1(struct alpha_busspace *space, size_t offset) +{ + struct bwx_space *bwx = (struct bwx_space *) space; + alpha_mb(); + return ldbu(bwx->base + offset); +} + +static u_int16_t +bwx_read_2(struct alpha_busspace *space, size_t offset) +{ + struct bwx_space *bwx = (struct bwx_space *) space; + alpha_mb(); + return ldwu(bwx->base + offset); +} + +static u_int32_t +bwx_read_4(struct alpha_busspace *space, size_t offset) +{ + struct bwx_space *bwx = (struct bwx_space *) space; + alpha_mb(); + return ldl(bwx->base + offset); +} + +static void +bwx_write_1(struct alpha_busspace *space, size_t offset, u_int8_t data) +{ + struct bwx_space *bwx = (struct bwx_space *) space; + stb(bwx->base + offset, data); + alpha_mb(); +} + +static void +bwx_write_2(struct alpha_busspace *space, size_t offset, u_int16_t data) +{ + struct bwx_space *bwx = (struct bwx_space *) space; + stw(bwx->base + offset, data); + alpha_mb(); +} + +static void +bwx_write_4(struct alpha_busspace *space, size_t offset, u_int32_t data) +{ + struct bwx_space *bwx = (struct bwx_space *) space; + stl(bwx->base + offset, data); + alpha_mb(); +} + +static struct alpha_busspace_ops bwx_space_ops = { + bwx_read_1, + bwx_read_2, + bwx_read_4, + + busspace_generic_read_multi_1, + busspace_generic_read_multi_2, + busspace_generic_read_multi_4, + + busspace_generic_read_region_1, + busspace_generic_read_region_2, + busspace_generic_read_region_4, + + bwx_write_1, + bwx_write_2, + bwx_write_4, + + busspace_generic_write_multi_1, + busspace_generic_write_multi_2, + busspace_generic_write_multi_4, + + busspace_generic_write_region_1, + busspace_generic_write_region_2, + busspace_generic_write_region_4, + + busspace_generic_set_multi_1, + busspace_generic_set_multi_2, + busspace_generic_set_multi_4, + + busspace_generic_set_region_1, + busspace_generic_set_region_2, + busspace_generic_set_region_4, + + busspace_generic_copy_region_1, + busspace_generic_copy_region_2, + busspace_generic_copy_region_4, + + busspace_generic_barrier, +}; + +void +bwx_init_space(struct bwx_space *bwx, u_int64_t base) +{ + bwx->ops = &bwx_space_ops; + bwx->base = base; +} + diff --git a/sys/alpha/pci/cia.c b/sys/alpha/pci/cia.c index 55a4750..558bad0 100644 --- a/sys/alpha/pci/cia.c +++ b/sys/alpha/pci/cia.c @@ -116,6 +116,8 @@ #include <vm/vm.h> #include <vm/vm_page.h> +#include "alphapci_if.h" + #define KV(pa) ALPHA_PHYS_TO_K0SEG(pa) static devclass_t cia_devclass; @@ -129,533 +131,36 @@ struct cia_softc { #define CIA_SOFTC(dev) (struct cia_softc*) device_get_softc(dev) -static alpha_chipset_inb_t cia_bwx_inb, cia_swiz_inb; -static alpha_chipset_inw_t cia_bwx_inw, cia_swiz_inw; -static alpha_chipset_inl_t cia_bwx_inl, cia_swiz_inl; -static alpha_chipset_outb_t cia_bwx_outb, cia_swiz_outb; -static alpha_chipset_outw_t cia_bwx_outw, cia_swiz_outw; -static alpha_chipset_outl_t cia_bwx_outl, cia_swiz_outl; -static alpha_chipset_readb_t cia_bwx_readb, cia_swiz_readb; -static alpha_chipset_readw_t cia_bwx_readw, cia_swiz_readw; -static alpha_chipset_readl_t cia_bwx_readl, cia_swiz_readl; -static alpha_chipset_writeb_t cia_bwx_writeb, cia_swiz_writeb; -static alpha_chipset_writew_t cia_bwx_writew, cia_swiz_writew; -static alpha_chipset_writel_t cia_bwx_writel, cia_swiz_writel; -static alpha_chipset_maxdevs_t cia_bwx_maxdevs, cia_swiz_maxdevs; -static alpha_chipset_cfgreadb_t cia_bwx_cfgreadb, cia_swiz_cfgreadb; -static alpha_chipset_cfgreadw_t cia_bwx_cfgreadw, cia_swiz_cfgreadw; -static alpha_chipset_cfgreadl_t cia_bwx_cfgreadl, cia_swiz_cfgreadl; -static alpha_chipset_cfgwriteb_t cia_bwx_cfgwriteb, cia_swiz_cfgwriteb; -static alpha_chipset_cfgwritew_t cia_bwx_cfgwritew, cia_swiz_cfgwritew; -static alpha_chipset_cfgwritel_t cia_bwx_cfgwritel, cia_swiz_cfgwritel; -static alpha_chipset_addrcvt_t cia_cvt_dense, cia_cvt_bwx; static alpha_chipset_read_hae_t cia_read_hae; static alpha_chipset_write_hae_t cia_write_hae; static alpha_chipset_t cia_bwx_chipset = { - cia_bwx_inb, - cia_bwx_inw, - cia_bwx_inl, - cia_bwx_outb, - cia_bwx_outw, - cia_bwx_outl, - cia_bwx_readb, - cia_bwx_readw, - cia_bwx_readl, - cia_bwx_writeb, - cia_bwx_writew, - cia_bwx_writel, - cia_bwx_maxdevs, - cia_bwx_cfgreadb, - cia_bwx_cfgreadw, - cia_bwx_cfgreadl, - cia_bwx_cfgwriteb, - cia_bwx_cfgwritew, - cia_bwx_cfgwritel, - cia_cvt_dense, - cia_cvt_bwx, cia_read_hae, cia_write_hae, }; static alpha_chipset_t cia_swiz_chipset = { - cia_swiz_inb, - cia_swiz_inw, - cia_swiz_inl, - cia_swiz_outb, - cia_swiz_outw, - cia_swiz_outl, - cia_swiz_readb, - cia_swiz_readw, - cia_swiz_readl, - cia_swiz_writeb, - cia_swiz_writew, - cia_swiz_writel, - cia_swiz_maxdevs, - cia_swiz_cfgreadb, - cia_swiz_cfgreadw, - cia_swiz_cfgreadl, - cia_swiz_cfgwriteb, - cia_swiz_cfgwritew, - cia_swiz_cfgwritel, - cia_cvt_dense, - NULL, cia_read_hae, cia_write_hae, }; -static u_int8_t -cia_bwx_inb(u_int32_t port) -{ - alpha_mb(); - return ldbu(KV(CIA_EV56_BWIO+BWX_EV56_INT1 + port)); -} - -static u_int16_t -cia_bwx_inw(u_int32_t port) -{ - alpha_mb(); - return ldwu(KV(CIA_EV56_BWIO+BWX_EV56_INT2 + port)); -} - -static u_int32_t -cia_bwx_inl(u_int32_t port) -{ - alpha_mb(); - return ldl(KV(CIA_EV56_BWIO+BWX_EV56_INT4 + port)); -} - -static void -cia_bwx_outb(u_int32_t port, u_int8_t data) -{ - stb(KV(CIA_EV56_BWIO+BWX_EV56_INT1 + port), data); - alpha_wmb(); -} - -static void -cia_bwx_outw(u_int32_t port, u_int16_t data) -{ - stw(KV(CIA_EV56_BWIO+BWX_EV56_INT2 + port), data); - alpha_wmb(); -} - -static void -cia_bwx_outl(u_int32_t port, u_int32_t data) -{ - stl(KV(CIA_EV56_BWIO+BWX_EV56_INT4 + port), data); - alpha_wmb(); -} - -static u_int8_t -cia_bwx_readb(u_int32_t pa) -{ - alpha_mb(); - return ldbu(KV(CIA_EV56_BWMEM+BWX_EV56_INT1 + pa)); -} - -static u_int16_t -cia_bwx_readw(u_int32_t pa) -{ - alpha_mb(); - return ldwu(KV(CIA_EV56_BWMEM+BWX_EV56_INT2 + pa)); -} - -static u_int32_t -cia_bwx_readl(u_int32_t pa) -{ - alpha_mb(); - return ldl(KV(CIA_EV56_BWMEM+BWX_EV56_INT4 + pa)); -} - -static void -cia_bwx_writeb(u_int32_t pa, u_int8_t data) -{ - stb(KV(CIA_EV56_BWMEM+BWX_EV56_INT1 + pa), data); - alpha_wmb(); -} - -static void -cia_bwx_writew(u_int32_t pa, u_int16_t data) -{ - stw(KV(CIA_EV56_BWMEM+BWX_EV56_INT2 + pa), data); - alpha_wmb(); -} - -static void -cia_bwx_writel(u_int32_t pa, u_int32_t data) -{ - stl(KV(CIA_EV56_BWMEM+BWX_EV56_INT4 + pa), data); - alpha_wmb(); -} - -static int -cia_bwx_maxdevs(u_int b) -{ - return 12; /* XXX */ -} - -static void -cia_clear_abort(void) -{ - /* - * Some (apparently-common) revisions of EB164 and AlphaStation - * firmware do the Wrong thing with PCI master and target aborts, - * which are caused by accesing the configuration space of devices - * that don't exist (for example). - * - * To work around this, we clear the CIA error register's PCI - * master and target abort bits before touching PCI configuration - * space and check it afterwards. If it indicates a master or target - * abort, the device wasn't there so we return 0xffffffff. - */ - REGVAL(CIA_CSR_CIA_ERR) = CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT; - alpha_mb(); - alpha_pal_draina(); -} - -static int -cia_check_abort(void) -{ - u_int32_t errbits; - int ba = 0; - - alpha_pal_draina(); - alpha_mb(); - errbits = REGVAL(CIA_CSR_CIA_ERR); - if (errbits & (CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT)) - ba = 1; - - if (errbits) { - REGVAL(CIA_CSR_CIA_ERR) = errbits; - alpha_mb(); - alpha_pal_draina(); - } - - return ba; -} - -#define CIA_BWX_CFGADDR(b, s, f, r) \ - KV(((b) ? CIA_EV56_BWCONF1 : CIA_EV56_BWCONF0) \ - | ((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) - -static u_int8_t -cia_bwx_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r); - u_int8_t data; - cia_clear_abort(); - if (badaddr((caddr_t)va, 1)) { - cia_check_abort(); - return ~0; - } - data = ldbu(va+BWX_EV56_INT1); - if (cia_check_abort()) - return ~0; - return data; -} - -static u_int16_t -cia_bwx_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r); - u_int16_t data; - cia_clear_abort(); - if (badaddr((caddr_t)va, 2)) { - cia_check_abort(); - return ~0; - } - data = ldwu(va+BWX_EV56_INT2); - if (cia_check_abort()) - return ~0; - return data; -} - -static u_int32_t -cia_bwx_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r); - u_int32_t data; - cia_clear_abort(); - if (badaddr((caddr_t)va, 4)) { - cia_check_abort(); - return ~0; - } - data = ldl(va+BWX_EV56_INT4); - if (cia_check_abort()) - return ~0; - return data; -} - -static void -cia_bwx_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data) -{ - vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r); - cia_clear_abort(); - if (badaddr((caddr_t)va, 1)) return; - stb(va+BWX_EV56_INT1, data); - cia_check_abort(); -} - -static void -cia_bwx_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data) -{ - vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r); - if (badaddr((caddr_t)va, 2)) return; - stw(va+BWX_EV56_INT2, data); - cia_check_abort(); -} - -static void -cia_bwx_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data) -{ - vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r); - if (badaddr((caddr_t)va, 4)) return; - stl(va+BWX_EV56_INT4, data); - cia_check_abort(); -} - -static u_int8_t -cia_swiz_inb(u_int32_t port) -{ - alpha_mb(); - return SPARSE_READ_BYTE(KV(CIA_PCI_SIO1), port); -} - -static u_int16_t -cia_swiz_inw(u_int32_t port) -{ - alpha_mb(); - return SPARSE_READ_WORD(KV(CIA_PCI_SIO1), port); -} - static u_int32_t -cia_swiz_inl(u_int32_t port) -{ - alpha_mb(); - return SPARSE_READ_LONG(KV(CIA_PCI_SIO1), port); -} - -static void -cia_swiz_outb(u_int32_t port, u_int8_t data) -{ - SPARSE_WRITE_BYTE(KV(CIA_PCI_SIO1), port, data); - alpha_wmb(); -} - -static void -cia_swiz_outw(u_int32_t port, u_int16_t data) -{ - SPARSE_WRITE_WORD(KV(CIA_PCI_SIO1), port, data); - alpha_wmb(); -} - -static void -cia_swiz_outl(u_int32_t port, u_int32_t data) -{ - SPARSE_WRITE_LONG(KV(CIA_PCI_SIO1), port, data); - alpha_wmb(); -} - -static __inline void -cia_swiz_set_hae_mem(u_int32_t *pa) +cia_swiz_set_hae_mem(void *arg, u_int32_t pa) { /* Only bother with region 1 */ #define REG1 (7 << 29) - if ((cia_hae_mem & REG1) != (*pa & REG1)) { + if ((cia_hae_mem & REG1) != (pa & REG1)) { /* * Seems fairly paranoid but this is what Linux does... */ - u_int32_t msb = *pa & REG1; + u_int32_t msb = pa & REG1; int s = splhigh(); cia_hae_mem = (cia_hae_mem & ~REG1) | msb; REGVAL(CIA_CSR_HAE_MEM) = cia_hae_mem; alpha_mb(); cia_hae_mem = REGVAL(CIA_CSR_HAE_MEM); splx(s); - *pa -= msb; } -} - -static u_int8_t -cia_swiz_readb(u_int32_t pa) -{ - alpha_mb(); - cia_swiz_set_hae_mem(&pa); - return SPARSE_READ_BYTE(KV(CIA_PCI_SMEM1), pa); -} - -static u_int16_t -cia_swiz_readw(u_int32_t pa) -{ - alpha_mb(); - cia_swiz_set_hae_mem(&pa); - return SPARSE_READ_WORD(KV(CIA_PCI_SMEM1), pa); -} - -static u_int32_t -cia_swiz_readl(u_int32_t pa) -{ - alpha_mb(); - cia_swiz_set_hae_mem(&pa); - return SPARSE_READ_LONG(KV(CIA_PCI_SMEM1), pa); -} - -static void -cia_swiz_writeb(u_int32_t pa, u_int8_t data) -{ - cia_swiz_set_hae_mem(&pa); - SPARSE_WRITE_BYTE(KV(CIA_PCI_SMEM1), pa, data); - alpha_wmb(); -} - -static void -cia_swiz_writew(u_int32_t pa, u_int16_t data) -{ - cia_swiz_set_hae_mem(&pa); - SPARSE_WRITE_WORD(KV(CIA_PCI_SMEM1), pa, data); - alpha_wmb(); -} - -static void -cia_swiz_writel(u_int32_t pa, u_int32_t data) -{ - cia_swiz_set_hae_mem(&pa); - SPARSE_WRITE_LONG(KV(CIA_PCI_SMEM1), pa, data); - alpha_wmb(); -} - -static int -cia_swiz_maxdevs(u_int b) -{ - return 12; /* XXX */ -} - -#define CIA_SWIZ_CFGOFF(b, s, f, r) \ - (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) - -/* when doing a type 1 pci configuration space access, we - * must set a bit in the CIA_CSR_CFG register & clear it - * when we're done -*/ - -#define CIA_TYPE1_SETUP(b,s,old_cfg) if((b)) { \ - do { \ - (s) = splhigh(); \ - (old_cfg) = REGVAL(CIA_CSR_CFG); \ - alpha_mb(); \ - REGVAL(CIA_CSR_CFG) = (old_cfg) | 0x1; \ - alpha_mb(); \ - } while(0); \ -} - -#define CIA_TYPE1_TEARDOWN(b,s,old_cfg) if((b)) { \ - do { \ - alpha_mb(); \ - REGVAL(CIA_CSR_CFG) = (old_cfg); \ - alpha_mb(); \ - splx((s)); \ - } while(0); \ -} - -/* - * From NetBSD: - * Some (apparently-common) revisions of EB164 and AlphaStation - * firmware do the Wrong thing with PCI master and target aborts, - * which are caused by accesing the configuration space of devices - * that don't exist (for example). - * - * To work around this, we clear the CIA error register's PCI - * master and target abort bits before touching PCI configuration - * space and check it afterwards. If it indicates a master or target - * abort, the device wasn't there so we return ~0 - */ - - -#define SWIZ_CFGREAD(b, s, f, r, width, type) \ - type val = ~0; \ - int ipl = 0; \ - u_int32_t old_cfg = 0, errbits; \ - vm_offset_t off = CIA_SWIZ_CFGOFF(b, s, f, r); \ - vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(CIA_PCI_CONF), off); \ - REGVAL(CIA_CSR_CIA_ERR) = CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT;\ - alpha_mb(); \ - CIA_TYPE1_SETUP(b,ipl,old_cfg); \ - if (!badaddr((caddr_t)kv, sizeof(type))) { \ - val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \ - } \ - CIA_TYPE1_TEARDOWN(b,ipl,old_cfg); \ - errbits = REGVAL(CIA_CSR_CIA_ERR); \ - if (errbits & (CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT)) \ - val = ~0; \ - if (errbits) { \ - REGVAL(CIA_CSR_CIA_ERR) = errbits; \ - alpha_mb(); \ - alpha_pal_draina(); \ - } \ - return val; - -#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) \ - int ipl = 0; \ - u_int32_t old_cfg = 0; \ - vm_offset_t off = CIA_SWIZ_CFGOFF(b, s, f, r); \ - vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(CIA_PCI_CONF), off); \ - alpha_mb(); \ - CIA_TYPE1_SETUP(b,ipl,old_cfg); \ - if (!badaddr((caddr_t)kv, sizeof(type))) { \ - SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \ - alpha_wmb(); \ - } \ - CIA_TYPE1_TEARDOWN(b,ipl,old_cfg); \ - return; - -static u_int8_t -cia_swiz_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - SWIZ_CFGREAD(b, s, f, r, BYTE, u_int8_t); -} - -static u_int16_t -cia_swiz_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - SWIZ_CFGREAD(b, s, f, r, WORD, u_int16_t); -} - -static u_int32_t -cia_swiz_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - SWIZ_CFGREAD(b, s, f, r, LONG, u_int32_t); -} - -static void -cia_swiz_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data) -{ - SWIZ_CFGWRITE(b, s, f, r, data, BYTE, u_int8_t); -} - -static void -cia_swiz_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data) -{ - SWIZ_CFGWRITE(b, s, f, r, data, WORD, u_int16_t); -} - -static void -cia_swiz_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data) -{ - SWIZ_CFGWRITE(b, s, f, r, data, LONG, u_int32_t); -} - -vm_offset_t -cia_cvt_dense(vm_offset_t addr) -{ - addr &= 0xffffffffUL; - return (addr | CIA_PCI_DENSE); - -} - -vm_offset_t -cia_cvt_bwx(vm_offset_t addr) -{ - addr &= 0xffffffffUL; - return (addr |= CIA_EV56_BWMEM); + return pa & ~REG1; } static u_int64_t @@ -668,7 +173,7 @@ static void cia_write_hae(u_int64_t hae) { u_int32_t pa = hae; - cia_swiz_set_hae_mem(&pa); + cia_swiz_set_hae_mem(0, pa); } static int cia_probe(device_t dev); @@ -756,7 +261,7 @@ cia_sgmap_invalidate_pyxis(void) } static void -cia_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa) +cia_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa) { u_int64_t *sgtable = arg; int index = alpha_btop(ba - CIA_SGMAP_BASE); @@ -842,6 +347,10 @@ void cia_init() { static int initted = 0; + static union space { + struct bwx_space bwx; + struct swiz_space swiz; + } io_space, mem_space; if (initted) return; initted = 1; @@ -870,16 +379,22 @@ cia_init() if (alpha_implver() != ALPHA_IMPLVER_EV5 || alpha_amask(ALPHA_AMASK_BWX) - || !(cia_config & CNFG_BWEN)) + || !(cia_config & CNFG_BWEN)) { + swiz_init_space(&io_space.swiz, KV(CIA_PCI_SIO1)); + swiz_init_space_hae(&mem_space.swiz, KV(CIA_PCI_SMEM1), + cia_swiz_set_hae_mem, 0); + chipset = cia_swiz_chipset; - else + } else { + bwx_init_space(&io_space.bwx, KV(CIA_EV56_BWIO)); + bwx_init_space(&mem_space.bwx, KV(CIA_EV56_BWMEM)); + chipset = cia_bwx_chipset; + } cia_hae_mem = REGVAL(CIA_CSR_HAE_MEM); -#if 0 - chipset = cia_swiz_chipset; /* XXX */ - cia_ispyxis = 0; -#endif + busspace_isa_io = (struct alpha_busspace *) &io_space; + busspace_isa_mem = (struct alpha_busspace *) &mem_space; if (platform.pci_intr_init) platform.pci_intr_init(); @@ -888,6 +403,8 @@ cia_init() static int cia_probe(device_t dev) { + uintptr_t use_bwx = 1; + if (cia0) return ENXIO; cia0 = dev; @@ -897,7 +414,13 @@ cia_probe(device_t dev) isa_init_intr(); cia_init_sgmap(); + if (alpha_implver() != ALPHA_IMPLVER_EV5 + || alpha_amask(ALPHA_AMASK_BWX) + || !(cia_config & CNFG_BWEN)) + use_bwx = 0; + device_add_child(dev, "pcib", 0); + device_set_ivars(dev, (void *)use_bwx); return 0; } diff --git a/sys/alpha/pci/cia_pci.c b/sys/alpha/pci/cia_pci.c index f9b7268..7b1620b 100644 --- a/sys/alpha/pci/cia_pci.c +++ b/sys/alpha/pci/cia_pci.c @@ -25,6 +25,69 @@ * * $FreeBSD$ */ +/*- + * Copyright (c) 1998 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. + * + * 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. 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. + * + * 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 (c) 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ #include <sys/param.h> #include <sys/systm.h> @@ -35,6 +98,16 @@ #include <machine/md_var.h> #include <sys/rman.h> #include <pci/pcivar.h> +#include <machine/bwx.h> +#include <machine/swiz.h> + +#include <alpha/pci/ciareg.h> +#include <alpha/pci/ciavar.h> + +#include "alphapci_if.h" +#include "pcib_if.h" + +#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa) static devclass_t pcib_devclass; @@ -51,13 +124,261 @@ cia_pcib_probe(device_t dev) static int cia_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result) { - if (which == PCIB_IVAR_HOSE) { + switch (which) { + case PCIB_IVAR_BUS: *result = 0; return 0; } return ENOENT; } +static void * +cia_pcib_cvt_dense(device_t dev, vm_offset_t addr) +{ + addr &= 0xffffffffUL; + return (void *) KV(addr | CIA_PCI_DENSE); +} + +static void * +cia_pcib_cvt_bwx(device_t dev, vm_offset_t addr) +{ + if ((uintptr_t) device_get_ivars(dev)) { + addr &= 0xffffffffUL; + return (void *) KV(addr | CIA_EV56_BWMEM); + } else { + return 0; + } +} + +static void +cia_clear_abort(void) +{ + /* + * Some (apparently-common) revisions of EB164 and AlphaStation + * firmware do the Wrong thing with PCI master and target aborts, + * which are caused by accesing the configuration space of devices + * that don't exist (for example). + * + * To work around this, we clear the CIA error register's PCI + * master and target abort bits before touching PCI configuration + * space and check it afterwards. If it indicates a master or target + * abort, the device wasn't there so we return 0xffffffff. + */ + REGVAL(CIA_CSR_CIA_ERR) = CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT; + alpha_mb(); + alpha_pal_draina(); +} + +static int +cia_check_abort(void) +{ + u_int32_t errbits; + int ba = 0; + + alpha_pal_draina(); + alpha_mb(); + errbits = REGVAL(CIA_CSR_CIA_ERR); + if (errbits & (CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT)) + ba = 1; + + if (errbits) { + REGVAL(CIA_CSR_CIA_ERR) = errbits; + alpha_mb(); + alpha_pal_draina(); + } + + return ba; +} + +#define CIA_BWX_CFGADDR(b, s, f, r) \ + KV(((b) ? CIA_EV56_BWCONF1 : CIA_EV56_BWCONF0) \ + | ((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) + +#define BWX_CFGREAD(b, s, f, r, width, type, op) do { \ + vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r); \ + type data; \ + cia_clear_abort(); \ + if (badaddr((caddr_t)va, width)) { \ + cia_check_abort(); \ + return ~0; \ + } \ + data = op(va); \ + if (cia_check_abort()) \ + return ~0; \ + return data; \ +} while (0) + +#define BWX_CFGWRITE(b, s, f, r, data, width, type, op) do { \ + vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r); \ + cia_clear_abort(); \ + if (badaddr((caddr_t)va, width)) return; \ + op(va, data); \ + cia_check_abort(); \ + return; \ +} while (0) + +#define CIA_SWIZ_CFGOFF(b, s, f, r) \ + (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) + +/* when doing a type 1 pci configuration space access, we + * must set a bit in the CIA_CSR_CFG register & clear it + * when we're done +*/ + +#define CIA_TYPE1_SETUP(b,s,old_cfg) if((b)) { \ + do { \ + (s) = splhigh(); \ + (old_cfg) = REGVAL(CIA_CSR_CFG); \ + alpha_mb(); \ + REGVAL(CIA_CSR_CFG) = (old_cfg) | 0x1; \ + alpha_mb(); \ + } while(0); \ +} + +#define CIA_TYPE1_TEARDOWN(b,s,old_cfg) if((b)) { \ + do { \ + alpha_mb(); \ + REGVAL(CIA_CSR_CFG) = (old_cfg); \ + alpha_mb(); \ + splx((s)); \ + } while(0); \ +} + +/* + * From NetBSD: + * Some (apparently-common) revisions of EB164 and AlphaStation + * firmware do the Wrong thing with PCI master and target aborts, + * which are caused by accesing the configuration space of devices + * that don't exist (for example). + * + * To work around this, we clear the CIA error register's PCI + * master and target abort bits before touching PCI configuration + * space and check it afterwards. If it indicates a master or target + * abort, the device wasn't there so we return ~0 + */ + + +#define SWIZ_CFGREAD(b, s, f, r, width, type) do { \ + type val = ~0; \ + int ipl = 0; \ + u_int32_t old_cfg = 0, errbits; \ + vm_offset_t off = CIA_SWIZ_CFGOFF(b, s, f, r); \ + vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(CIA_PCI_CONF), off); \ + REGVAL(CIA_CSR_CIA_ERR) = CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT; \ + alpha_mb(); \ + CIA_TYPE1_SETUP(b,ipl,old_cfg); \ + if (!badaddr((caddr_t)kv, sizeof(type))) { \ + val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \ + } \ + CIA_TYPE1_TEARDOWN(b,ipl,old_cfg); \ + errbits = REGVAL(CIA_CSR_CIA_ERR); \ + if (errbits & (CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT)) \ + val = ~0; \ + if (errbits) { \ + REGVAL(CIA_CSR_CIA_ERR) = errbits; \ + alpha_mb(); \ + alpha_pal_draina(); \ + } \ + return val; \ +} while (0) + +#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) do { \ + int ipl = 0; \ + u_int32_t old_cfg = 0; \ + vm_offset_t off = CIA_SWIZ_CFGOFF(b, s, f, r); \ + vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(CIA_PCI_CONF), off); \ + alpha_mb(); \ + CIA_TYPE1_SETUP(b,ipl,old_cfg); \ + if (!badaddr((caddr_t)kv, sizeof(type))) { \ + SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \ + alpha_wmb(); \ + } \ + CIA_TYPE1_TEARDOWN(b,ipl,old_cfg); \ + return; \ +} while (0) + +static u_int32_t +cia_pcib_swiz_read_config(int b, int s, int f, int reg, int width) +{ + switch (width) { + case 1: + SWIZ_CFGREAD(b, s, f, reg, BYTE, u_int8_t); + case 2: + SWIZ_CFGREAD(b, s, f, reg, WORD, u_int16_t); + case 4: + SWIZ_CFGREAD(b, s, f, reg, LONG, u_int32_t); + } + return ~0; +} + +static void +cia_pcib_swiz_write_config(int b, int s, int f, int reg, + u_int32_t val, int width) +{ + switch (width) { + case 1: + SWIZ_CFGWRITE(b, s, f, reg, val, BYTE, u_int8_t); + case 2: + SWIZ_CFGWRITE(b, s, f, reg, val, WORD, u_int16_t); + case 4: + SWIZ_CFGWRITE(b, s, f, reg, val, LONG, u_int32_t); + } +} + +static u_int32_t +cia_pcib_bwx_read_config(int b, int s, int f, int reg, int width) +{ + switch (width) { + case 1: + BWX_CFGREAD(b, s, f, reg, 1, u_int8_t, ldbu); + case 2: + BWX_CFGREAD(b, s, f, reg, 2, u_int16_t, ldwu); + case 4: + BWX_CFGREAD(b, s, f, reg, 4, u_int32_t, ldl); + } + return ~0; +} + +static void +cia_pcib_bwx_write_config(int b, int s, int f, int reg, + u_int32_t val, int width) +{ + switch (width) { + case 1: + BWX_CFGWRITE(b, s, f, reg, val, 1, u_int8_t, stb); + case 2: + BWX_CFGWRITE(b, s, f, reg, val, 2, u_int16_t, stw); + case 4: + BWX_CFGWRITE(b, s, f, reg, val, 4, u_int32_t, stl); + } +} + +static int +cia_pcib_maxslots(device_t dev) +{ + return 31; +} + +static u_int32_t +cia_pcib_read_config(device_t dev, int b, int s, int f, + int reg, int width) +{ + if ((uintptr_t) device_get_ivars(dev)) + return cia_pcib_bwx_read_config(b, s, f, reg, width); + else + return cia_pcib_swiz_read_config(b, s, f, reg, width); +} + +static void +cia_pcib_write_config(device_t dev, int b, int s, int f, + int reg, u_int32_t val, int width) +{ + if ((uintptr_t) device_get_ivars(dev)) + cia_pcib_bwx_write_config(b, s, f, reg, val, width); + else + cia_pcib_swiz_write_config(b, s, f, reg, val, width); +} + static device_method_t cia_pcib_methods[] = { /* Device interface */ DEVMETHOD(device_probe, cia_pcib_probe), @@ -73,6 +394,15 @@ static device_method_t cia_pcib_methods[] = { DEVMETHOD(bus_setup_intr, alpha_platform_pci_setup_intr), DEVMETHOD(bus_teardown_intr, alpha_platform_pci_teardown_intr), + /* alphapci interface */ + DEVMETHOD(alphapci_cvt_dense, cia_pcib_cvt_dense), + DEVMETHOD(alphapci_cvt_bwx, cia_pcib_cvt_bwx), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, cia_pcib_maxslots), + DEVMETHOD(pcib_read_config, cia_pcib_read_config), + DEVMETHOD(pcib_write_config, cia_pcib_write_config), + { 0, 0 } }; diff --git a/sys/alpha/pci/dwlpx_pci.c b/sys/alpha/pci/dwlpx_pci.c deleted file mode 100644 index c852b62..0000000 --- a/sys/alpha/pci/dwlpx_pci.c +++ /dev/null @@ -1,80 +0,0 @@ -/* $FreeBSD$ */ -/* - * Copyright (c) 2000 Matthew Jacob - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. - * - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <machine/bus.h> -#include <sys/rman.h> -#include <pci/pcivar.h> - -static devclass_t pcib_devclass; - -static int -dwlpx_pcib_probe(device_t dev) -{ - device_set_desc(dev, "DWLPX PCI host bus adapter"); - device_add_child(dev, "pci", device_get_unit(dev) << 4); - return (0); -} - -static int -dwlpx_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result) -{ - if (which == PCIB_IVAR_HOSE) { - *result = *(int*) device_get_ivars(dev); - return 0; - } - return ENOENT; -} - -static device_method_t dwlpx_pcib_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, dwlpx_pcib_probe), - DEVMETHOD(device_attach, bus_generic_attach), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_read_ivar, dwlpx_pcib_read_ivar), - DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - - { 0, 0 } -}; - -static driver_t dwlpx_pcib_driver = { - "pcib", dwlpx_pcib_methods, 1 -}; - -DRIVER_MODULE(pcib, dwlpx, dwlpx_pcib_driver, pcib_devclass, 0, 0); diff --git a/sys/alpha/pci/irongate.c b/sys/alpha/pci/irongate.c index 296d09d..3983cca 100644 --- a/sys/alpha/pci/irongate.c +++ b/sys/alpha/pci/irongate.c @@ -65,242 +65,14 @@ struct irongate_softc { #define IRONGATE_SOFTC(dev) (struct irongate_softc*) device_get_softc(dev) -static alpha_chipset_inb_t irongate_inb; -static alpha_chipset_inw_t irongate_inw; -static alpha_chipset_inl_t irongate_inl; -static alpha_chipset_outb_t irongate_outb; -static alpha_chipset_outw_t irongate_outw; -static alpha_chipset_outl_t irongate_outl; -static alpha_chipset_readb_t irongate_readb; -static alpha_chipset_readw_t irongate_readw; -static alpha_chipset_readl_t irongate_readl; -static alpha_chipset_writeb_t irongate_writeb; -static alpha_chipset_writew_t irongate_writew; -static alpha_chipset_writel_t irongate_writel; -static alpha_chipset_maxdevs_t irongate_maxdevs; -static alpha_chipset_cfgreadb_t irongate_cfgreadb; -static alpha_chipset_cfgreadw_t irongate_cfgreadw; -static alpha_chipset_cfgreadl_t irongate_cfgreadl; -static alpha_chipset_cfgwriteb_t irongate_cfgwriteb; -static alpha_chipset_cfgwritew_t irongate_cfgwritew; -static alpha_chipset_cfgwritel_t irongate_cfgwritel; -static alpha_chipset_addrcvt_t irongate_cvt_dense, irongate_cvt_bwx; - static alpha_chipset_read_hae_t irongate_read_hae; static alpha_chipset_write_hae_t irongate_write_hae; static alpha_chipset_t irongate_chipset = { - irongate_inb, - irongate_inw, - irongate_inl, - irongate_outb, - irongate_outw, - irongate_outl, - irongate_readb, - irongate_readw, - irongate_readl, - irongate_writeb, - irongate_writew, - irongate_writel, - irongate_maxdevs, - irongate_cfgreadb, - irongate_cfgreadw, - irongate_cfgreadl, - irongate_cfgwriteb, - irongate_cfgwritew, - irongate_cfgwritel, - irongate_cvt_dense, - irongate_cvt_bwx, irongate_read_hae, irongate_write_hae, }; -static u_int8_t -irongate_inb(u_int32_t port) -{ - alpha_mb(); - return ldbu(KV(IRONGATE_IO + port)); -} - -static u_int16_t -irongate_inw(u_int32_t port) -{ - alpha_mb(); - return ldwu(KV(IRONGATE_IO + port)); -} - -static u_int32_t -irongate_inl(u_int32_t port) -{ - alpha_mb(); - return ldl(KV(IRONGATE_IO + port)); -} - -static void -irongate_outb(u_int32_t port, u_int8_t data) -{ - stb(KV(IRONGATE_IO + port), data); - alpha_mb(); -} - -static void -irongate_outw(u_int32_t port, u_int16_t data) -{ - stw(KV(IRONGATE_IO + port), data); - alpha_mb(); -} - -static void -irongate_outl(u_int32_t port, u_int32_t data) -{ - stl(KV(IRONGATE_IO + port), data); - alpha_mb(); -} - -static u_int8_t -irongate_readb(u_int32_t pa) -{ - alpha_mb(); - return ldbu(KV(IRONGATE_MEM + pa)); -} - -static u_int16_t -irongate_readw(u_int32_t pa) -{ - alpha_mb(); - return ldwu(KV(IRONGATE_MEM + pa)); -} - -static u_int32_t -irongate_readl(u_int32_t pa) -{ - alpha_mb(); - return ldl(KV(IRONGATE_MEM + pa)); -} - -static void -irongate_writeb(u_int32_t pa, u_int8_t data) -{ - stb(KV(IRONGATE_MEM + pa), data); - alpha_mb(); -} - -static void -irongate_writew(u_int32_t pa, u_int16_t data) -{ - stw(KV(IRONGATE_MEM + pa), data); - alpha_mb(); -} - -static void -irongate_writel(u_int32_t pa, u_int32_t data) -{ - stl(KV(IRONGATE_MEM + pa), data); - alpha_mb(); -} - -static int -irongate_maxdevs(u_int b) -{ - return 12; /* XXX */ -} - -static void -irongate_clear_abort(void) -{ - alpha_mb(); - alpha_pal_draina(); -} - -static int -irongate_check_abort(void) -{ - alpha_pal_draina(); - alpha_mb(); - - return 0; -} - -#define IRONGATE_CFGADDR(b, s, f, r) \ - KV(IRONGATE_CONF | ((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) - -#define CFGREAD(h, b, s, f, r, op, width, type) \ - vm_offset_t va; \ - type data; \ - va = IRONGATE_CFGADDR(b, s, f, r); \ - irongate_clear_abort(); \ - if (badaddr((caddr_t)va, width)) { \ - irongate_check_abort(); \ - return ~0; \ - } \ - data = ##op##(va); \ - if (irongate_check_abort()) \ - return ~0; \ - return data; - -#define CFWRITE(h, b, s, f, r, data, op, width) \ - vm_offset_t va; \ - va = IRONGATE_CFGADDR(b, s, f, r); \ - irongate_clear_abort(); \ - if (badaddr((caddr_t)va, width)) \ - return; \ - ##op##(va, data); \ - irongate_check_abort(); - - - - -static u_int8_t -irongate_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - CFGREAD(h, b, s, f, r, ldbu, 1, u_int8_t) -} - -static u_int16_t -irongate_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - CFGREAD(h, b, s, f, r, ldwu, 2, u_int16_t) -} - -static u_int32_t -irongate_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - CFGREAD(h, b, s, f, r, ldl, 4, u_int32_t) -} - -static void -irongate_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data) -{ - CFWRITE(h, b, s, f, r, data, stb, 1) -} - -static void -irongate_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data) -{ - CFWRITE(h, b, s, f, r, data, stw, 2) -} - -static void -irongate_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data) -{ - CFWRITE(h, b, s, f, r, data, stl, 4) -} - - -vm_offset_t -irongate_cvt_bwx(vm_offset_t addr) -{ - addr &= 0xffffffffUL; - return (KV(addr | IRONGATE_MEM)); -} - -vm_offset_t -irongate_cvt_dense(vm_offset_t addr) -{ - return irongate_cvt_bwx(addr); -} - - /* * There doesn't appear to be an hae on this platform */ @@ -347,6 +119,7 @@ void irongate_init() { static int initted = 0; + struct bwx_space io_space, mem_space; if (initted) return; initted = 1; @@ -354,6 +127,12 @@ irongate_init() chipset = irongate_chipset; alpha_XXX_dmamap_or = 0UL; + bwx_init_space(&io_space, KV(IRONGATE_IO)); + bwx_init_space(&mem_space, KV(IRONGATE_MEM)); + + busspace_isa_io = (kobj_t) &io_space; + busspace_isa_mem = (kobj_t) &mem_space; + if (platform.pci_intr_init) platform.pci_intr_init(); } @@ -377,10 +156,6 @@ irongate_probe(device_t dev) static int irongate_attach(device_t dev) { - u_int8_t value; - pcicfgregs southbridge; - - irongate_init(); if (!platform.iointr) /* XXX */ @@ -395,22 +170,6 @@ irongate_attach(device_t dev) /* no s/g support in this chipset, must use bounce-buffers */ chipset.sgmap = NULL; - /* - * XXX -- The SRM console doesn't properly initialize - * the AcerLabs M1533C southbridge. We must turn off 32-bit - * DMA support. - */ - - southbridge.hose = 0; - southbridge.bus = 0; - southbridge.slot = 7; - southbridge.func = 0; - if ((0x153310b9 == pci_cfgread(&southbridge, PCIR_DEVVENDOR, 4))) { - value = (u_int8_t)pci_cfgread(&southbridge, 0x42, 1); - value &= ~0x40; - pci_cfgwrite(&southbridge, 0x42, 0, 1); - } - bus_generic_attach(dev); return 0; diff --git a/sys/alpha/pci/irongate_pci.c b/sys/alpha/pci/irongate_pci.c index e8cf291..3b62716 100644 --- a/sys/alpha/pci/irongate_pci.c +++ b/sys/alpha/pci/irongate_pci.c @@ -34,14 +34,19 @@ #include <sys/bus.h> #include <machine/bus.h> #include <machine/md_var.h> +#include <machine/bwx.h> #include <sys/rman.h> #include <pci/pcivar.h> +#include <pci/pcireg.h> #include <alpha/pci/irongatereg.h> #include <alpha/pci/irongatevar.h> +#include "alphapci_if.h" +#include "pcib_if.h" -static devclass_t pcib_devclass; +#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa) +static devclass_t pcib_devclass; static int irongate_pcib_probe(device_t dev) @@ -49,7 +54,19 @@ irongate_pcib_probe(device_t dev) device_set_desc(dev, "AMD 751 PCI host bus adapter"); - device_add_child(dev, "pci", -1); + device_add_child(dev, "pci", 0); + + /* + * XXX -- The SRM console doesn't properly initialize + * the AcerLabs M1533C southbridge. We must turn off 32-bit + * DMA support. + */ + if ((0x153310b9 == PCIB_READ_CONFIG(dev, 0, 7, 0, + PCIR_DEVVENDOR, 4))) { + u_int8_t value = PCIB_READ_CONFIG(dev, 0, 7, 0, 0x42, 1); + value &= ~0x40; + PCIB_WRITE_CONFIG(dev, 0, 7, 0, 0x42, 0, 1); + } return 0; } @@ -57,13 +74,107 @@ irongate_pcib_probe(device_t dev) static int irongate_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result) { - if (which == PCIB_IVAR_HOSE) { + switch (which) { + case PCIB_IVAR_BUS: *result = 0; return 0; } return ENOENT; } +static void * +irongate_pcib_cvt_dense(device_t dev, vm_offset_t addr) +{ + addr &= 0xffffffffUL; + return (void *) KV(addr | IRONGATE_MEM); +} + +static void * +irongate_pcib_cvt_bwx(device_t dev, vm_offset_t addr) +{ + addr &= 0xffffffffUL; + return (void *) KV(addr | IRONGATE_MEM); +} + +static int +irongate_pcib_maxslots(device_t dev) +{ + return 31; +} + +static void +irongate_clear_abort(void) +{ + alpha_mb(); + alpha_pal_draina(); +} + +static int +irongate_check_abort(void) +{ + alpha_pal_draina(); + alpha_mb(); + + return 0; +} + +#define IRONGATE_CFGADDR(b, s, f, r) \ + KV(IRONGATE_CONF | ((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) + +#define CFGREAD(b, s, f, r, width, type, op) do { \ + vm_offset_t va; \ + type data; \ + va = IRONGATE_CFGADDR(b, s, f, r); \ + irongate_clear_abort(); \ + if (badaddr((caddr_t)va, width)) { \ + irongate_check_abort(); \ + return ~0; \ + } \ + data = ##op##(va); \ + if (irongate_check_abort()) \ + return ~0; \ + return data; \ +} while (0) + +#define CFGWRITE(b, s, f, r, data, width, op) do { \ + vm_offset_t va; \ + va = IRONGATE_CFGADDR(b, s, f, r); \ + irongate_clear_abort(); \ + if (badaddr((caddr_t)va, width)) \ + return; \ + ##op##(va, data); \ + irongate_check_abort(); \ +} while (0) + +static u_int32_t +irongate_pcib_read_config(device_t dev, int b, int s, int f, + int reg, int width) +{ + switch (width) { + case 1: + CFGREAD(b, s, f, reg, 1, u_int8_t, ldbu); + case 2: + CFGREAD(b, s, f, reg, 2, u_int16_t, ldwu); + case 4: + CFGREAD(b, s, f, reg, 4, u_int32_t, ldl); + } + return ~0; +} + +static void +irongate_pcib_write_config(device_t dev, int b, int s, int f, + int reg, u_int32_t val, int width) +{ + switch (width) { + case 1: + CFGWRITE(b, s, f, reg, val, 1, stb); + case 2: + CFGWRITE(b, s, f, reg, val, 2, stw); + case 4: + CFGWRITE(b, s, f, reg, val, 4, stl); + } +} + static device_method_t irongate_pcib_methods[] = { /* Device interface */ DEVMETHOD(device_probe, irongate_pcib_probe), @@ -79,17 +190,23 @@ static device_method_t irongate_pcib_methods[] = { DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + /* alphapci interface */ + DEVMETHOD(alphapci_cvt_dense, irongate_pcib_cvt_dense), + DEVMETHOD(alphapci_cvt_bwx, irongate_pcib_cvt_bwx), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, irongate_pcib_maxslots), + DEVMETHOD(pcib_read_config, irongate_pcib_read_config), + DEVMETHOD(pcib_write_config, irongate_pcib_write_config), { 0, 0 } }; - static driver_t irongate_pcib_driver = { "pcib", irongate_pcib_methods, 1, }; - DRIVER_MODULE(pcib, irongate, irongate_pcib_driver, pcib_devclass, 0, 0); diff --git a/sys/alpha/pci/lca.c b/sys/alpha/pci/lca.c index c1b8082..323c94c 100644 --- a/sys/alpha/pci/lca.c +++ b/sys/alpha/pci/lca.c @@ -59,97 +59,14 @@ struct lca_softc { #define LCA_SOFTC(dev) (struct lca_softc*) device_get_softc(dev) -static alpha_chipset_inb_t lca_inb; -static alpha_chipset_inw_t lca_inw; -static alpha_chipset_inl_t lca_inl; -static alpha_chipset_outb_t lca_outb; -static alpha_chipset_outw_t lca_outw; -static alpha_chipset_outl_t lca_outl; -static alpha_chipset_readb_t lca_readb; -static alpha_chipset_readw_t lca_readw; -static alpha_chipset_readl_t lca_readl; -static alpha_chipset_writeb_t lca_writeb; -static alpha_chipset_writew_t lca_writew; -static alpha_chipset_writel_t lca_writel; -static alpha_chipset_maxdevs_t lca_maxdevs; -static alpha_chipset_cfgreadb_t lca_cfgreadb; -static alpha_chipset_cfgreadw_t lca_cfgreadw; -static alpha_chipset_cfgreadl_t lca_cfgreadl; -static alpha_chipset_cfgwriteb_t lca_cfgwriteb; -static alpha_chipset_cfgwritew_t lca_cfgwritew; -static alpha_chipset_cfgwritel_t lca_cfgwritel; -static alpha_chipset_addrcvt_t lca_cvt_dense; static alpha_chipset_read_hae_t lca_read_hae; static alpha_chipset_write_hae_t lca_write_hae; static alpha_chipset_t lca_chipset = { - lca_inb, - lca_inw, - lca_inl, - lca_outb, - lca_outw, - lca_outl, - lca_readb, - lca_readw, - lca_readl, - lca_writeb, - lca_writew, - lca_writel, - lca_maxdevs, - lca_cfgreadb, - lca_cfgreadw, - lca_cfgreadl, - lca_cfgwriteb, - lca_cfgwritew, - lca_cfgwritel, - lca_cvt_dense, - NULL, lca_read_hae, lca_write_hae, }; -static u_int8_t -lca_inb(u_int32_t port) -{ - alpha_mb(); - return SPARSE_READ_BYTE(KV(LCA_PCI_SIO), port); -} - -static u_int16_t -lca_inw(u_int32_t port) -{ - alpha_mb(); - return SPARSE_READ_WORD(KV(LCA_PCI_SIO), port); -} - -static u_int32_t -lca_inl(u_int32_t port) -{ - alpha_mb(); - return SPARSE_READ_LONG(KV(LCA_PCI_SIO), port); -} - -static void -lca_outb(u_int32_t port, u_int8_t data) -{ - SPARSE_WRITE_BYTE(KV(LCA_PCI_SIO), port, data); - alpha_wmb(); -} - -static void -lca_outw(u_int32_t port, u_int16_t data) -{ - SPARSE_WRITE_WORD(KV(LCA_PCI_SIO), port, data); - alpha_wmb(); -} - -static void -lca_outl(u_int32_t port, u_int32_t data) -{ - SPARSE_WRITE_LONG(KV(LCA_PCI_SIO), port, data); - alpha_wmb(); -} - /* * The LCA HAE is write-only. According to NetBSD, this is where it starts. */ @@ -161,14 +78,14 @@ static u_int32_t lca_hae_mem = 0x80000000; */ #define REG1 (1UL << 24) -static __inline void -lca_set_hae_mem(u_int32_t *pa) +static u_int32_t +lca_set_hae_mem(void *arg, u_int32_t pa) { int s; u_int32_t msb; - if(*pa >= REG1){ - msb = *pa & 0xf8000000; - *pa -= msb; + if(pa >= REG1){ + msb = pa & 0xf8000000; + pa -= msb; s = splhigh(); if (msb != lca_hae_mem) { lca_hae_mem = msb; @@ -178,152 +95,7 @@ lca_set_hae_mem(u_int32_t *pa) } splx(s); } -} - -static u_int8_t -lca_readb(u_int32_t pa) -{ - alpha_mb(); - lca_set_hae_mem(&pa); - return SPARSE_READ_BYTE(KV(LCA_PCI_SPARSE), pa); -} - -static u_int16_t -lca_readw(u_int32_t pa) -{ - alpha_mb(); - lca_set_hae_mem(&pa); - return SPARSE_READ_WORD(KV(LCA_PCI_SPARSE), pa); -} - -static u_int32_t -lca_readl(u_int32_t pa) -{ - alpha_mb(); - lca_set_hae_mem(&pa); - return SPARSE_READ_LONG(KV(LCA_PCI_SPARSE), pa); -} - -static void -lca_writeb(u_int32_t pa, u_int8_t data) -{ - lca_set_hae_mem(&pa); - SPARSE_WRITE_BYTE(KV(LCA_PCI_SPARSE), pa, data); - alpha_wmb(); -} - -static void -lca_writew(u_int32_t pa, u_int16_t data) -{ - lca_set_hae_mem(&pa); - SPARSE_WRITE_WORD(KV(LCA_PCI_SPARSE), pa, data); - alpha_wmb(); -} - -static void -lca_writel(u_int32_t pa, u_int32_t data) -{ - lca_set_hae_mem(&pa); - SPARSE_WRITE_LONG(KV(LCA_PCI_SPARSE), pa, data); - alpha_wmb(); -} - -static int -lca_maxdevs(u_int b) -{ - return 12; /* XXX */ -} - -#define LCA_CFGOFF(b, s, f, r) \ - ((b) ? (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) \ - : ((1 << ((s) + 11)) | ((f) << 8) | (r))) - -#define LCA_TYPE1_SETUP(b,s) if ((b)) { \ - do { \ - (s) = splhigh(); \ - alpha_mb(); \ - REGVAL(LCA_IOC_CONF) = 1; \ - alpha_mb(); \ - } while(0); \ -} - -#define LCA_TYPE1_TEARDOWN(b,s) if ((b)) { \ - do { \ - alpha_mb(); \ - REGVAL(LCA_IOC_CONF) = 0; \ - alpha_mb(); \ - splx((s)); \ - } while(0); \ -} - -#define CFGREAD(b, s, f, r, width, type) \ - type val = ~0; \ - int ipl = 0; \ - vm_offset_t off = LCA_CFGOFF(b, s, f, r); \ - vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(LCA_PCI_CONF), off); \ - alpha_mb(); \ - LCA_TYPE1_SETUP(b,ipl); \ - if (!badaddr((caddr_t)kv, sizeof(type))) { \ - val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \ - } \ - LCA_TYPE1_TEARDOWN(b,ipl); \ - return val - -#define CFGWRITE(b, s, f, r, data, width, type) \ - int ipl = 0; \ - vm_offset_t off = LCA_CFGOFF(b, s, f, r); \ - vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(LCA_PCI_CONF), off); \ - alpha_mb(); \ - LCA_TYPE1_SETUP(b,ipl); \ - if (!badaddr((caddr_t)kv, sizeof(type))) { \ - SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \ - alpha_wmb(); \ - } \ - LCA_TYPE1_TEARDOWN(b,ipl); \ - return - -static u_int8_t -lca_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - CFGREAD(b, s, f, r, BYTE, u_int8_t); -} - -static u_int16_t -lca_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - CFGREAD(b, s, f, r, WORD, u_int16_t); -} - -static u_int32_t -lca_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - CFGREAD(b, s, f, r, LONG, u_int32_t); -} - -static void -lca_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data) -{ - CFGWRITE(b, s, f, r, data, BYTE, u_int8_t); -} - -static void -lca_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data) -{ - CFGWRITE(b, s, f, r, data, WORD, u_int16_t); -} - -static void -lca_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data) -{ - CFGWRITE(b, s, f, r, data, LONG, u_int16_t); -} - -static vm_offset_t -lca_cvt_dense(vm_offset_t addr) -{ - addr &= 0xffffffffUL; - return (addr | LCA_PCI_DENSE); - + return pa; } static u_int64_t @@ -336,7 +108,7 @@ static void lca_write_hae(u_int64_t hae) { u_int32_t pa = hae; - lca_set_hae_mem(&pa); + lca_set_hae_mem(0, pa); } static int lca_probe(device_t dev); @@ -382,7 +154,7 @@ lca_sgmap_invalidate(void) } static void -lca_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa) +lca_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa) { u_int64_t *sgtable = arg; int index = alpha_btop(ba - LCA_SGMAP_BASE); @@ -435,10 +207,18 @@ void lca_init() { static int initted = 0; + static struct swiz_space io_space, mem_space; if (initted) return; initted = 1; + swiz_init_space(&io_space, KV(LCA_PCI_SIO)); + swiz_init_space_hae(&mem_space, KV(LCA_PCI_SPARSE), + lca_set_hae_mem, 0); + + busspace_isa_io = (struct alpha_busspace *) &io_space; + busspace_isa_mem = (struct alpha_busspace *) &mem_space; + /* Type 0 PCI conf access. */ REGVAL64(LCA_IOC_CONF) = 0; diff --git a/sys/alpha/pci/lca_pci.c b/sys/alpha/pci/lca_pci.c index 1765c3b..e17d1e4 100644 --- a/sys/alpha/pci/lca_pci.c +++ b/sys/alpha/pci/lca_pci.c @@ -34,6 +34,15 @@ #include <machine/bus.h> #include <sys/rman.h> #include <pci/pcivar.h> +#include <machine/swiz.h> + +#include <alpha/pci/lcareg.h> +#include <alpha/pci/lcavar.h> + +#include "alphapci_if.h" +#include "pcib_if.h" + +#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa) static devclass_t pcib_devclass; @@ -50,13 +59,105 @@ lca_pcib_probe(device_t dev) static int lca_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result) { - if (which == PCIB_IVAR_HOSE) { + if (which == PCIB_IVAR_BUS) { *result = 0; return 0; } return ENOENT; } +static void * +lca_pcib_cvt_dense(device_t dev, vm_offset_t addr) +{ + addr &= 0xffffffffUL; + return (void *) KV(addr | LCA_PCI_DENSE); +} + +static int +lca_pcib_maxslots(device_t dev) +{ + return 31; +} + +#define LCA_CFGOFF(b, s, f, r) \ + ((b) ? (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) \ + : ((1 << ((s) + 11)) | ((f) << 8) | (r))) + +#define LCA_TYPE1_SETUP(b,s) if ((b)) { \ + do { \ + (s) = splhigh(); \ + alpha_mb(); \ + REGVAL(LCA_IOC_CONF) = 1; \ + alpha_mb(); \ + } while(0); \ +} + +#define LCA_TYPE1_TEARDOWN(b,s) if ((b)) { \ + do { \ + alpha_mb(); \ + REGVAL(LCA_IOC_CONF) = 0; \ + alpha_mb(); \ + splx((s)); \ + } while(0); \ +} + +#define CFGREAD(b, s, f, r, width, type) do { \ + type val = ~0; \ + int ipl = 0; \ + vm_offset_t off = LCA_CFGOFF(b, s, f, r); \ + vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(LCA_PCI_CONF), off); \ + alpha_mb(); \ + LCA_TYPE1_SETUP(b,ipl); \ + if (!badaddr((caddr_t)kv, sizeof(type))) { \ + val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \ + } \ + LCA_TYPE1_TEARDOWN(b,ipl); \ + return val; \ +} while (0) + +#define CFGWRITE(b, s, f, r, data, width, type) do { \ + int ipl = 0; \ + vm_offset_t off = LCA_CFGOFF(b, s, f, r); \ + vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(LCA_PCI_CONF), off); \ + alpha_mb(); \ + LCA_TYPE1_SETUP(b,ipl); \ + if (!badaddr((caddr_t)kv, sizeof(type))) { \ + SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \ + alpha_wmb(); \ + } \ + LCA_TYPE1_TEARDOWN(b,ipl); \ + return; \ +} while (0) + +u_int32_t +lca_pcib_read_config(device_t dev, int b, int s, int f, + int reg, int width) +{ + switch (width) { + case 1: + CFGREAD(b, s, f, reg, BYTE, u_int8_t); + case 2: + CFGREAD(b, s, f, reg, WORD, u_int16_t); + case 4: + CFGREAD(b, s, f, reg, LONG, u_int32_t); + } + return ~0; +} + +static void +lca_pcib_write_config(device_t dev, int b, int s, int f, + int reg, u_int32_t val, int width) +{ + switch (width) { + case 1: + CFGWRITE(b, s, f, reg, val, BYTE, u_int8_t); + case 2: + CFGWRITE(b, s, f, reg, val, WORD, u_int16_t); + case 4: + CFGWRITE(b, s, f, reg, val, LONG, u_int32_t); + } +} + static device_method_t lca_pcib_methods[] = { /* Device interface */ DEVMETHOD(device_probe, lca_pcib_probe), @@ -72,6 +173,14 @@ static device_method_t lca_pcib_methods[] = { DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + /* alphapci interface */ + DEVMETHOD(alphapci_cvt_dense, lca_pcib_cvt_dense), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, lca_pcib_maxslots), + DEVMETHOD(pcib_read_config, lca_pcib_read_config), + DEVMETHOD(pcib_write_config, lca_pcib_write_config), + { 0, 0 } }; diff --git a/sys/alpha/pci/lcavar.h b/sys/alpha/pci/lcavar.h index 1619539..2f22ade 100644 --- a/sys/alpha/pci/lcavar.h +++ b/sys/alpha/pci/lcavar.h @@ -26,4 +26,8 @@ * $FreeBSD$ */ +struct device; + extern void lca_init(void); +u_int32_t lca_pcib_read_config(struct device *dev, int b, int s, int f, + int reg, int width); diff --git a/sys/alpha/pci/mcpcia_pci.c b/sys/alpha/pci/mcpcia_pci.c deleted file mode 100644 index cbcf934..0000000 --- a/sys/alpha/pci/mcpcia_pci.c +++ /dev/null @@ -1,80 +0,0 @@ -/* $FreeBSD$ */ -/* - * Copyright (c) 2000 Matthew Jacob - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. - * - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> -#include <sys/bus.h> -#include <machine/bus.h> -#include <sys/rman.h> -#include <pci/pcivar.h> - -static devclass_t pcib_devclass; - -static int -mcpcia_pcib_probe(device_t dev) -{ - device_set_desc(dev, "MCPCIA PCI host bus adapter"); - device_add_child(dev, "pci", device_get_unit(dev) << 4); - return (0); -} - -static int -mcpcia_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result) -{ - if (which == PCIB_IVAR_HOSE) { - *result = *(int*) device_get_ivars(dev); - return 0; - } - return ENOENT; -} - -static device_method_t mcpcia_pcib_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, mcpcia_pcib_probe), - DEVMETHOD(device_attach, bus_generic_attach), - - /* Bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_read_ivar, mcpcia_pcib_read_ivar), - DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), - DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - - { 0, 0 } -}; - -static driver_t mcpcia_pcib_driver = { - "pcib", mcpcia_pcib_methods, 1 -}; - -DRIVER_MODULE(pcib, mcpcia, mcpcia_pcib_driver, pcib_devclass, 0, 0); diff --git a/sys/alpha/pci/pcibus.c b/sys/alpha/pci/pcibus.c index 5bed15e..8aaf9fb 100644 --- a/sys/alpha/pci/pcibus.c +++ b/sys/alpha/pci/pcibus.c @@ -45,11 +45,15 @@ #include <alpha/pci/pcibus.h> #include <alpha/isa/isavar.h> +#include "alphapci_if.h" #include "isa.h" #define ISA_IRQ_OFFSET 0xe0 #define ISA_IRQ_LEN 0x10 +struct alpha_busspace *busspace_isa_io; +struct alpha_busspace *busspace_isa_mem; + char chipset_type[10]; int chipset_bwx = 0; long chipset_ports = 0; @@ -71,73 +75,6 @@ SYSCTL_LONG(_hw_chipset, OID_AUTO, dense, CTLFLAG_RD, &chipset_dense, 0, SYSCTL_LONG(_hw_chipset, OID_AUTO, hae_mask, CTLFLAG_RD, &chipset_hae_mask, 0, "PCI chipset mask for HAE register"); -#ifdef notyet - -/* return max number of devices on the bus */ -int -pci_maxdevs(pcicfgregs *cfg) -{ - return chipset.maxdevs(cfg->bus); -} - -#endif - -/* read configuration space register */ - -int -pci_cfgread(pcicfgregs *cfg, int reg, int bytes) -{ - switch (bytes) { - case 1: - return chipset.cfgreadb(cfg->hose, cfg->bus, - cfg->slot, cfg->func, reg); - case 2: - return chipset.cfgreadw(cfg->hose, cfg->bus, - cfg->slot, cfg->func, reg); - case 4: - return chipset.cfgreadl(cfg->hose, cfg->bus, - cfg->slot, cfg->func, reg); - } - return ~0; -} - - -/* write configuration space register */ - -void -pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes) -{ - switch (bytes) { - case 1: - return chipset.cfgwriteb(cfg->hose, cfg->bus, - cfg->slot, cfg->func, reg, data); - case 2: - return chipset.cfgwritew(cfg->hose, cfg->bus, - cfg->slot, cfg->func, reg, data); - case 4: - return chipset.cfgwritel(cfg->hose, cfg->bus, - cfg->slot, cfg->func, reg, data); - } -} - -vm_offset_t -pci_cvt_to_dense(vm_offset_t sparse) -{ - if(chipset.cvt_to_dense) - return ALPHA_PHYS_TO_K0SEG(chipset.cvt_to_dense(sparse)); - else - return NULL; -} - -vm_offset_t -pci_cvt_to_bwx(vm_offset_t sparse) -{ - if(chipset.cvt_to_bwx) - return ALPHA_PHYS_TO_K0SEG(chipset.cvt_to_bwx(sparse)); - else - return NULL; -} - void alpha_platform_assign_pciintr(pcicfgregs *cfg) { @@ -274,6 +211,7 @@ pci_alloc_resource(device_t bus, device_t child, int type, int *rid, { struct rman *rm; struct resource *rv; + void *va; switch (type) { case SYS_RES_IRQ: @@ -290,11 +228,8 @@ pci_alloc_resource(device_t bus, device_t child, int type, int *rid, break; case SYS_RES_IOPORT: - rm = &port_rman; - break; - case SYS_RES_MEMORY: - rm = &mem_rman; + rm = ALPHAPCI_GET_RMAN(bus, type); break; default: @@ -305,21 +240,19 @@ pci_alloc_resource(device_t bus, device_t child, int type, int *rid, if (rv == 0) return 0; + rman_set_bustag(rv, ALPHAPCI_GET_BUSTAG(bus, type)); + rman_set_bushandle(rv, rv->r_start); switch (type) { case SYS_RES_MEMORY: - rman_set_bustag(rv, ALPHA_BUS_SPACE_MEM); - rman_set_bushandle(rv, rv->r_start); + va = 0; if (flags & PCI_RF_DENSE) - rman_set_virtual(rv, (void *) pci_cvt_to_dense(rv->r_start)); + va = ALPHAPCI_CVT_DENSE(bus, rv->r_start); else if (flags & PCI_RF_BWX) - rman_set_virtual(rv, (void *) pci_cvt_to_bwx(rv->r_start)); + va = ALPHAPCI_CVT_BWX(bus, rv->r_start); else - rman_set_virtual(rv, (void *) rv->r_start); /* maybe NULL? */ - break; + va = (void *) rv->r_start; /* maybe NULL? */ + rman_set_virtual(rv, va); - case SYS_RES_IOPORT: - rman_set_bustag(rv, ALPHA_BUS_SPACE_IO); - rman_set_bushandle(rv, rv->r_start); break; } @@ -347,54 +280,32 @@ pci_release_resource(device_t bus, device_t child, int type, int rid, return (rman_release_resource(r)); } -void -memcpy_fromio(void *d, u_int32_t s, size_t size) -{ - char *cp = d; - - while (size--) - *cp++ = readb(s++); -} - -void -memcpy_toio(u_int32_t d, void *s, size_t size) +struct alpha_busspace * +pci_get_bustag(device_t dev, int type) { - char *cp = s; - - while (size--) - writeb(d++, *cp++); -} + switch (type) { + case SYS_RES_IOPORT: + return busspace_isa_io; -void -memcpy_io(u_int32_t d, u_int32_t s, size_t size) -{ - while (size--) - writeb(d++, readb(s++)); -} + case SYS_RES_MEMORY: + return busspace_isa_mem; + } -void -memset_io(u_int32_t d, int val, size_t size) -{ - while (size--) - writeb(d++, val); + return 0; } -void -memsetw(void *d, int val, size_t size) +struct rman * +pci_get_rman(device_t dev, int type) { - u_int16_t *sp = d; + switch (type) { + case SYS_RES_IOPORT: + return &port_rman; - while (size--) - *sp++ = val; -} + case SYS_RES_MEMORY: + return &mem_rman; + } -void -memsetw_io(u_int32_t d, int val, size_t size) -{ - while (size--) { - writew(d, val); - d += sizeof(u_int16_t); - } + return 0; } #include "opt_ddb.h" diff --git a/sys/alpha/pci/pcibus.h b/sys/alpha/pci/pcibus.h index 27c5ffa..aa3e105 100644 --- a/sys/alpha/pci/pcibus.h +++ b/sys/alpha/pci/pcibus.h @@ -37,3 +37,5 @@ int pci_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *r); int pci_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r); +struct alpha_busspace *pci_get_bustag(device_t dev, int type); +struct rman *pci_get_rman(device_t dev, int type); diff --git a/sys/alpha/pci/swiz.c b/sys/alpha/pci/swiz.c new file mode 100644 index 0000000..01b3059 --- /dev/null +++ b/sys/alpha/pci/swiz.c @@ -0,0 +1,154 @@ +/*- + * Copyright (c) 2000 Doug Rabson + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/kobj.h> + +#include <machine/bus.h> +#include <machine/swiz.h> + +static u_int8_t +swiz_read_1(struct alpha_busspace *space, size_t offset) +{ + struct swiz_space *swiz = (struct swiz_space *) space; + alpha_mb(); + if (swiz->sethae) + offset = swiz->sethae(swiz->arg, offset); + return SPARSE_READ_BYTE(swiz->base, offset); +} + +static u_int16_t +swiz_read_2(struct alpha_busspace *space, size_t offset) +{ + struct swiz_space *swiz = (struct swiz_space *) space; + alpha_mb(); + if (swiz->sethae) + offset = swiz->sethae(swiz->arg, offset); + return SPARSE_READ_WORD(swiz->base, offset); +} + +static u_int32_t +swiz_read_4(struct alpha_busspace *space, size_t offset) +{ + struct swiz_space *swiz = (struct swiz_space *) space; + alpha_mb(); + if (swiz->sethae) + offset = swiz->sethae(swiz->arg, offset); + return SPARSE_READ_LONG(swiz->base, offset); +} + +static void +swiz_write_1(struct alpha_busspace *space, size_t offset, u_int8_t data) +{ + struct swiz_space *swiz = (struct swiz_space *) space; + if (swiz->sethae) + offset = swiz->sethae(swiz->arg, offset); + SPARSE_WRITE_BYTE(swiz->base, offset, data); + alpha_mb(); +} + +static void +swiz_write_2(struct alpha_busspace *space, size_t offset, u_int16_t data) +{ + struct swiz_space *swiz = (struct swiz_space *) space; + if (swiz->sethae) + offset = swiz->sethae(swiz->arg, offset); + SPARSE_WRITE_WORD(swiz->base, offset, data); + alpha_mb(); +} + +static void +swiz_write_4(struct alpha_busspace *space, size_t offset, u_int32_t data) +{ + struct swiz_space *swiz = (struct swiz_space *) space; + if (swiz->sethae) + offset = swiz->sethae(swiz->arg, offset); + SPARSE_WRITE_LONG(swiz->base, offset, data); + alpha_mb(); +} + +static struct alpha_busspace_ops swiz_space_ops = { + swiz_read_1, + swiz_read_2, + swiz_read_4, + + busspace_generic_read_multi_1, + busspace_generic_read_multi_2, + busspace_generic_read_multi_4, + + busspace_generic_read_region_1, + busspace_generic_read_region_2, + busspace_generic_read_region_4, + + swiz_write_1, + swiz_write_2, + swiz_write_4, + + busspace_generic_write_multi_1, + busspace_generic_write_multi_2, + busspace_generic_write_multi_4, + + busspace_generic_write_region_1, + busspace_generic_write_region_2, + busspace_generic_write_region_4, + + busspace_generic_set_multi_1, + busspace_generic_set_multi_2, + busspace_generic_set_multi_4, + + busspace_generic_set_region_1, + busspace_generic_set_region_2, + busspace_generic_set_region_4, + + busspace_generic_copy_region_1, + busspace_generic_copy_region_2, + busspace_generic_copy_region_4, + + busspace_generic_barrier, +}; + +void +swiz_init_space(struct swiz_space *swiz, u_int64_t base) +{ + swiz->ops = &swiz_space_ops; + swiz->base = base; + swiz->sethae = 0; + swiz->arg = 0; +} + +void swiz_init_space_hae(struct swiz_space *swiz, u_int64_t base, + swiz_sethae_fn sethae, void *arg) +{ + swiz->ops = &swiz_space_ops; + swiz->base = base; + swiz->sethae = sethae; + swiz->arg = arg; +} + diff --git a/sys/alpha/pci/t2.c b/sys/alpha/pci/t2.c index 554fc48..db7deae 100644 --- a/sys/alpha/pci/t2.c +++ b/sys/alpha/pci/t2.c @@ -66,110 +66,27 @@ struct t2_softc { #define T2_SOFTC(dev) (struct t2_softc*) device_get_softc(dev) -static alpha_chipset_inb_t t2_inb; -static alpha_chipset_inw_t t2_inw; -static alpha_chipset_inl_t t2_inl; -static alpha_chipset_outb_t t2_outb; -static alpha_chipset_outw_t t2_outw; -static alpha_chipset_outl_t t2_outl; -static alpha_chipset_readb_t t2_readb; -static alpha_chipset_readw_t t2_readw; -static alpha_chipset_readl_t t2_readl; -static alpha_chipset_writeb_t t2_writeb; -static alpha_chipset_writew_t t2_writew; -static alpha_chipset_writel_t t2_writel; -static alpha_chipset_maxdevs_t t2_maxdevs; -static alpha_chipset_cfgreadb_t t2_cfgreadb; -static alpha_chipset_cfgreadw_t t2_cfgreadw; -static alpha_chipset_cfgreadl_t t2_cfgreadl; -static alpha_chipset_cfgwriteb_t t2_cfgwriteb; -static alpha_chipset_cfgwritew_t t2_cfgwritew; -static alpha_chipset_cfgwritel_t t2_cfgwritel; -static alpha_chipset_addrcvt_t t2_cvt_dense; static alpha_chipset_read_hae_t t2_read_hae; static alpha_chipset_write_hae_t t2_write_hae; static alpha_chipset_t t2_chipset = { - t2_inb, - t2_inw, - t2_inl, - t2_outb, - t2_outw, - t2_outl, - t2_readb, - t2_readw, - t2_readl, - t2_writeb, - t2_writew, - t2_writel, - t2_maxdevs, - t2_cfgreadb, - t2_cfgreadw, - t2_cfgreadl, - t2_cfgwriteb, - t2_cfgwritew, - t2_cfgwritel, - t2_cvt_dense, - NULL, t2_read_hae, t2_write_hae, }; -static u_int8_t -t2_inb(u_int32_t port) -{ - alpha_mb(); - return SPARSE_READ_BYTE(KV(T2_PCI_SIO), port); -} - -static u_int16_t -t2_inw(u_int32_t port) -{ - alpha_mb(); - return SPARSE_READ_WORD(KV(T2_PCI_SIO), port); -} - -static u_int32_t -t2_inl(u_int32_t port) -{ - alpha_mb(); - return SPARSE_READ_LONG(KV(T2_PCI_SIO), port); -} - -static void -t2_outb(u_int32_t port, u_int8_t data) -{ - SPARSE_WRITE_BYTE(KV(T2_PCI_SIO), port, data); - alpha_wmb(); -} - -static void -t2_outw(u_int32_t port, u_int16_t data) -{ - SPARSE_WRITE_WORD(KV(T2_PCI_SIO), port, data); - alpha_wmb(); -} - -static void -t2_outl(u_int32_t port, u_int32_t data) -{ - SPARSE_WRITE_LONG(KV(T2_PCI_SIO), port, data); - alpha_wmb(); -} - static u_int32_t t2_hae_mem; #define REG1 (1UL << 24) -static __inline void -t2_set_hae_mem(u_int32_t *pa) +static u_int32_t +t2_set_hae_mem(void *arg, u_int32_t pa) { int s; u_int32_t msb; - if(*pa >= REG1){ - msb = *pa & 0xf8000000; - *pa -= msb; + if(pa >= REG1){ + msb = pa & 0xf8000000; + pa -= msb; msb >>= 27; /* t2 puts high bits in the bottom of the register */ s = splhigh(); if (msb != t2_hae_mem) { @@ -180,72 +97,7 @@ t2_set_hae_mem(u_int32_t *pa) } splx(s); } -} - -static u_int8_t -t2_readb(u_int32_t pa) -{ - alpha_mb(); - t2_set_hae_mem(&pa); - return SPARSE_READ_BYTE(KV(T2_PCI_SPARSE), pa); -} - -static u_int16_t -t2_readw(u_int32_t pa) -{ - alpha_mb(); - t2_set_hae_mem(&pa); - return SPARSE_READ_WORD(KV(T2_PCI_SPARSE), pa); -} - -static u_int32_t -t2_readl(u_int32_t pa) -{ - alpha_mb(); - t2_set_hae_mem(&pa); - return SPARSE_READ_LONG(KV(T2_PCI_SPARSE), pa); -} - -static void -t2_writeb(u_int32_t pa, u_int8_t data) -{ - t2_set_hae_mem(&pa); - SPARSE_WRITE_BYTE(KV(T2_PCI_SPARSE), pa, data); - alpha_wmb(); -} - -static void -t2_writew(u_int32_t pa, u_int16_t data) -{ - t2_set_hae_mem(&pa); - SPARSE_WRITE_WORD(KV(T2_PCI_SPARSE), pa, data); - alpha_wmb(); -} - -static void -t2_writel(u_int32_t pa, u_int32_t data) -{ - t2_set_hae_mem(&pa); - SPARSE_WRITE_LONG(KV(T2_PCI_SPARSE), pa, data); - alpha_wmb(); -} - -static int -t2_maxdevs(u_int b) -{ - return 12; /* XXX */ -} - - - -/* XXX config space access? */ - -static vm_offset_t -t2_cvt_dense(vm_offset_t addr) -{ - addr &= 0xffffffffUL; - return (addr | T2_PCI_DENSE); - + return pa; } static u_int64_t @@ -258,94 +110,7 @@ static void t2_write_hae(u_int64_t hae) { u_int32_t pa = hae; - t2_set_hae_mem(&pa); -} - -#define T2_CFGOFF(b, s, f, r) \ - ((b) ? (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) \ - : ((1 << ((s) + 11)) | ((f) << 8) | (r))) - -#define T2_TYPE1_SETUP(b,s,old_hae3) if((b)) { \ - do { \ - (s) = splhigh(); \ - (old_hae3) = REGVAL(T2_HAE0_3); \ - alpha_mb(); \ - REGVAL(T2_HAE0_3) = (old_hae3) | (1<<30); \ - alpha_mb(); \ - } while(0); \ -} - -#define T2_TYPE1_TEARDOWN(b,s,old_hae3) if((b)) { \ - do { \ - alpha_mb(); \ - REGVAL(T2_HAE0_3) = (old_hae3); \ - alpha_mb(); \ - splx((s)); \ - } while(0); \ -} - -#define SWIZ_CFGREAD(b, s, f, r, width, type) \ - type val = ~0; \ - int ipl = 0; \ - u_int32_t old_hae3 = 0; \ - vm_offset_t off = T2_CFGOFF(b, s, f, r); \ - vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(T2_PCI_CONF), off); \ - alpha_mb(); \ - T2_TYPE1_SETUP(b,ipl,old_hae3); \ - if (!badaddr((caddr_t)kv, sizeof(type))) { \ - val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \ - } \ - T2_TYPE1_TEARDOWN(b,ipl,old_hae3); \ - return val; - -#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) \ - int ipl = 0; \ - u_int32_t old_hae3 = 0; \ - vm_offset_t off = T2_CFGOFF(b, s, f, r); \ - vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(T2_PCI_CONF), off); \ - alpha_mb(); \ - T2_TYPE1_SETUP(b,ipl,old_hae3); \ - if (!badaddr((caddr_t)kv, sizeof(type))) { \ - SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \ - alpha_wmb(); \ - } \ - T2_TYPE1_TEARDOWN(b,ipl,old_hae3); \ - return; - -static u_int8_t -t2_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - SWIZ_CFGREAD(b, s, f, r, BYTE, u_int8_t); -} - -static u_int16_t -t2_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - SWIZ_CFGREAD(b, s, f, r, WORD, u_int16_t); -} - -static u_int32_t -t2_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - SWIZ_CFGREAD(b, s, f, r, LONG, u_int32_t); -} - -static void -t2_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data) -{ - SWIZ_CFGWRITE(b, s, f, r, data, BYTE, u_int8_t); -} - -static void -t2_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data) -{ - SWIZ_CFGWRITE(b, s, f, r, data, WORD, u_int16_t); -} - -static void -t2_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data) -{ - SWIZ_CFGWRITE(b, s, f, r, data, LONG, u_int32_t); + t2_set_hae_mem(0, pa); } static int t2_probe(device_t dev); @@ -407,7 +172,7 @@ t2_sgmap_invalidate(void) } static void -t2_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa) +t2_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa) { u_int64_t *sgtable = arg; int index = alpha_btop(ba - T2_SGMAP_BASE); @@ -468,10 +233,18 @@ void t2_init() { static int initted = 0; + static struct swiz_space io_space, mem_space; if (initted) return; initted = 1; + swiz_init_space(&io_space, KV(T2_PCI_SIO)); + swiz_init_space_hae(&mem_space, KV(T2_PCI_SPARSE), + t2_set_hae_mem, 0); + + busspace_isa_io = (kobj_t) &io_space; + busspace_isa_mem = (kobj_t) &mem_space; + chipset = t2_chipset; } diff --git a/sys/alpha/pci/t2_pci.c b/sys/alpha/pci/t2_pci.c index 2213bb3..5d3eb21 100644 --- a/sys/alpha/pci/t2_pci.c +++ b/sys/alpha/pci/t2_pci.c @@ -34,6 +34,15 @@ #include <machine/bus.h> #include <sys/rman.h> #include <pci/pcivar.h> +#include <machine/swiz.h> + +#include <alpha/pci/t2reg.h> +#include <alpha/pci/t2var.h> + +#include "alphapci_if.h" +#include "pcib_if.h" + +#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa) static devclass_t pcib_devclass; @@ -53,13 +62,108 @@ t2_pcib_probe(device_t dev) static int t2_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result) { - if (which == PCIB_IVAR_HOSE) { + if (which == PCIB_IVAR_BUS) { *result = 0; return 0; } return ENOENT; } +static void * +t2_pcib_cvt_dense(device_t dev, vm_offset_t addr) +{ + addr &= 0xffffffffUL; + return (void *) KV(addr | T2_PCI_DENSE); +} + +static int +t2_pcib_maxslots(device_t dev) +{ + return 31; +} + +#define T2_CFGOFF(b, s, f, r) \ + ((b) ? (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) \ + : ((1 << ((s) + 11)) | ((f) << 8) | (r))) + +#define T2_TYPE1_SETUP(b,s,old_hae3) if((b)) { \ + do { \ + (s) = splhigh(); \ + (old_hae3) = REGVAL(T2_HAE0_3); \ + alpha_mb(); \ + REGVAL(T2_HAE0_3) = (old_hae3) | (1<<30); \ + alpha_mb(); \ + } while(0); \ +} + +#define T2_TYPE1_TEARDOWN(b,s,old_hae3) if((b)) { \ + do { \ + alpha_mb(); \ + REGVAL(T2_HAE0_3) = (old_hae3); \ + alpha_mb(); \ + splx((s)); \ + } while(0); \ +} + +#define SWIZ_CFGREAD(b, s, f, r, width, type) do { \ + type val = ~0; \ + int ipl = 0; \ + u_int32_t old_hae3 = 0; \ + vm_offset_t off = T2_CFGOFF(b, s, f, r); \ + vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(T2_PCI_CONF), off); \ + alpha_mb(); \ + T2_TYPE1_SETUP(b,ipl,old_hae3); \ + if (!badaddr((caddr_t)kv, sizeof(type))) { \ + val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \ + } \ + T2_TYPE1_TEARDOWN(b,ipl,old_hae3); \ + return val; \ +} while (0) + +#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) do { \ + int ipl = 0; \ + u_int32_t old_hae3 = 0; \ + vm_offset_t off = T2_CFGOFF(b, s, f, r); \ + vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(T2_PCI_CONF), off); \ + alpha_mb(); \ + T2_TYPE1_SETUP(b,ipl,old_hae3); \ + if (!badaddr((caddr_t)kv, sizeof(type))) { \ + SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \ + alpha_wmb(); \ + } \ + T2_TYPE1_TEARDOWN(b,ipl,old_hae3); \ + return; \ +} while (0) + +static u_int32_t +t2_pcib_read_config(device_t dev, int b, int s, int f, + int reg, int width) +{ + switch (width) { + case 1: + SWIZ_CFGREAD(b, s, f, reg, BYTE, u_int8_t); + case 2: + SWIZ_CFGREAD(b, s, f, reg, WORD, u_int16_t); + case 4: + SWIZ_CFGREAD(b, s, f, reg, LONG, u_int32_t); + } + return ~0; +} + +static void +t2_pcib_write_config(device_t dev, int b, int s, int f, + int reg, u_int32_t val, int width) +{ + switch (width) { + case 1: + SWIZ_CFGWRITE(b, s, f, reg, val, BYTE, u_int8_t); + case 2: + SWIZ_CFGWRITE(b, s, f, reg, val, WORD, u_int16_t); + case 4: + SWIZ_CFGWRITE(b, s, f, reg, val, LONG, u_int32_t); + } +} + static device_method_t t2_pcib_methods[] = { /* Device interface */ DEVMETHOD(device_probe, t2_pcib_probe), @@ -75,6 +179,14 @@ static device_method_t t2_pcib_methods[] = { DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + /* alphapci interface */ + DEVMETHOD(alphapci_cvt_dense, t2_pcib_cvt_dense), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, t2_pcib_maxslots), + DEVMETHOD(pcib_read_config, t2_pcib_read_config), + DEVMETHOD(pcib_write_config, t2_pcib_write_config), + { 0, 0 } }; diff --git a/sys/alpha/pci/t2var.h b/sys/alpha/pci/t2var.h index ef47d0b..cadfa48 100644 --- a/sys/alpha/pci/t2var.h +++ b/sys/alpha/pci/t2var.h @@ -26,4 +26,6 @@ * $FreeBSD$ */ +extern vm_offset_t t2_csr_base; + extern void t2_init(void); diff --git a/sys/alpha/pci/tsunami.c b/sys/alpha/pci/tsunami.c index 41f67a5..4f43e5c 100644 --- a/sys/alpha/pci/tsunami.c +++ b/sys/alpha/pci/tsunami.c @@ -67,302 +67,17 @@ static volatile tsunami_pchip *pchip[2] = {pchip0, pchip1}; #define TSUNAMI_SOFTC(dev) (struct tsunami_softc*) device_get_softc(dev) -static alpha_chipset_inb_t tsunami_inb; -static alpha_chipset_inw_t tsunami_inw; -static alpha_chipset_inl_t tsunami_inl; -static alpha_chipset_outb_t tsunami_outb; -static alpha_chipset_outw_t tsunami_outw; -static alpha_chipset_outl_t tsunami_outl; -static alpha_chipset_readb_t tsunami_readb; -static alpha_chipset_readw_t tsunami_readw; -static alpha_chipset_readl_t tsunami_readl; -static alpha_chipset_writeb_t tsunami_writeb; -static alpha_chipset_writew_t tsunami_writew; -static alpha_chipset_writel_t tsunami_writel; -static alpha_chipset_maxdevs_t tsunami_maxdevs; -static alpha_chipset_cfgreadb_t tsunami_cfgreadb; -static alpha_chipset_cfgreadw_t tsunami_cfgreadw; -static alpha_chipset_cfgreadl_t tsunami_cfgreadl; -static alpha_chipset_cfgwriteb_t tsunami_cfgwriteb; -static alpha_chipset_cfgwritew_t tsunami_cfgwritew; -static alpha_chipset_cfgwritel_t tsunami_cfgwritel; -static alpha_chipset_addrcvt_t tsunami_cvt_dense, tsunami_cvt_bwx; - static alpha_chipset_read_hae_t tsunami_read_hae; static alpha_chipset_write_hae_t tsunami_write_hae; static alpha_chipset_t tsunami_chipset = { - tsunami_inb, - tsunami_inw, - tsunami_inl, - tsunami_outb, - tsunami_outw, - tsunami_outl, - tsunami_readb, - tsunami_readw, - tsunami_readl, - tsunami_writeb, - tsunami_writew, - tsunami_writel, - tsunami_maxdevs, - tsunami_cfgreadb, - tsunami_cfgreadw, - tsunami_cfgreadl, - tsunami_cfgwriteb, - tsunami_cfgwritew, - tsunami_cfgwritel, - tsunami_cvt_dense, - tsunami_cvt_bwx, tsunami_read_hae, tsunami_write_hae, }; -/* - * This setup will only allow for one additional hose - */ - -#define ADDR_TO_HOSE(x) ((x) >> 31) -#define STRIP_HOSE(x) ((x) & 0x7fffffff) - static void tsunami_intr_enable __P((int)); static void tsunami_intr_disable __P((int)); -static u_int8_t -tsunami_inb(u_int32_t port) -{ - int hose = ADDR_TO_HOSE(port); - port = STRIP_HOSE(port); - alpha_mb(); - return ldbu(KV(TSUNAMI_IO(hose) + port)); -} - -static u_int16_t -tsunami_inw(u_int32_t port) -{ - int hose = ADDR_TO_HOSE(port); - port = STRIP_HOSE(port); - alpha_mb(); - return ldwu(KV(TSUNAMI_IO(hose) + port)); -} - -static u_int32_t -tsunami_inl(u_int32_t port) -{ - int hose = ADDR_TO_HOSE(port); - port = STRIP_HOSE(port); - alpha_mb(); - return ldl(KV(TSUNAMI_IO(hose) + port)); -} - -static void -tsunami_outb(u_int32_t port, u_int8_t data) -{ - int hose = ADDR_TO_HOSE(port); - port = STRIP_HOSE(port); - stb(KV(TSUNAMI_IO(hose) + port), data); - alpha_mb(); -} - -static void -tsunami_outw(u_int32_t port, u_int16_t data) -{ - int hose = ADDR_TO_HOSE(port); - port = STRIP_HOSE(port); - stw(KV(TSUNAMI_IO(hose) + port), data); - alpha_mb(); -} - -static void -tsunami_outl(u_int32_t port, u_int32_t data) -{ - int hose = ADDR_TO_HOSE(port); - port = STRIP_HOSE(port); - stl(KV(TSUNAMI_IO(hose) + port), data); - alpha_mb(); -} - -static u_int8_t -tsunami_readb(u_int32_t pa) -{ - int hose = ADDR_TO_HOSE(pa); - pa = STRIP_HOSE(pa); - alpha_mb(); - return ldbu(KV(TSUNAMI_MEM(hose) + pa)); -} - -static u_int16_t -tsunami_readw(u_int32_t pa) -{ - int hose = ADDR_TO_HOSE(pa); - pa = STRIP_HOSE(pa); - alpha_mb(); - return ldwu(KV(TSUNAMI_MEM(hose) + pa)); -} - -static u_int32_t -tsunami_readl(u_int32_t pa) -{ - int hose = ADDR_TO_HOSE(pa); - pa = STRIP_HOSE(pa); - alpha_mb(); - return ldl(KV(TSUNAMI_MEM(hose) + pa)); -} - -static void -tsunami_writeb(u_int32_t pa, u_int8_t data) -{ - int hose = ADDR_TO_HOSE(pa); - pa = STRIP_HOSE(pa); - stb(KV(TSUNAMI_MEM(hose) + pa), data); - alpha_mb(); -} - -static void -tsunami_writew(u_int32_t pa, u_int16_t data) -{ - int hose = ADDR_TO_HOSE(pa); - pa = STRIP_HOSE(pa); - stw(KV(TSUNAMI_MEM(hose) + pa), data); - alpha_mb(); -} - -static void -tsunami_writel(u_int32_t pa, u_int32_t data) -{ - int hose = ADDR_TO_HOSE(pa); - pa = STRIP_HOSE(pa); - stl(KV(TSUNAMI_MEM(hose) + pa), data); - alpha_mb(); -} - -static int -tsunami_maxdevs(u_int b) -{ - return 12; /* XXX */ -} - -static void -tsunami_clear_abort(void) -{ - alpha_mb(); - alpha_pal_draina(); -} - -static int -tsunami_check_abort(void) -{ -/* u_int32_t errbits;*/ - int ba = 0; - - alpha_pal_draina(); - alpha_mb(); -#if 0 - errbits = REGVAL(TSUNAMI_CSR_TSUNAMI_ERR); - if (errbits & (TSUNAMI_ERR_RCVD_MAS_ABT|TSUNAMI_ERR_RCVD_TAR_ABT)) - ba = 1; - - if (errbits) { - REGVAL(TSUNAMI_CSR_TSUNAMI_ERR) = errbits; - alpha_mb(); - alpha_pal_draina(); - } -#endif - return ba; -} - -#define TSUNAMI_CFGADDR(b, s, f, r, h) \ - KV(TSUNAMI_CONF(h) | ((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) - -#define CFGREAD(h, b, s, f, r, op, width, type) \ - int bus; \ - vm_offset_t va; \ - type data; \ - if (h == (u_int8_t)-1) \ - h = tsunami_hose_from_bus(b); \ - bus = tsunami_bus_within_hose(h, b); \ - va = TSUNAMI_CFGADDR(bus, s, f, r, h); \ - tsunami_clear_abort(); \ - if (badaddr((caddr_t)va, width)) { \ - tsunami_check_abort(); \ - return ~0; \ - } \ - data = ##op##(va); \ - if (tsunami_check_abort()) \ - return ~0; \ - return data; - -#define CFWRITE(h, b, s, f, r, data, op, width) \ - int bus; \ - vm_offset_t va; \ - if (h == (u_int8_t)-1) \ - h = tsunami_hose_from_bus(b); \ - bus = tsunami_bus_within_hose(h, b); \ - va = TSUNAMI_CFGADDR(bus, s, f, r, h); \ - tsunami_clear_abort(); \ - if (badaddr((caddr_t)va, width)) \ - return; \ - ##op##(va, data); \ - tsunami_check_abort(); - - - - -static u_int8_t -tsunami_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - CFGREAD(h, b, s, f, r, ldbu, 1, u_int8_t) -} - -static u_int16_t -tsunami_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - CFGREAD(h, b, s, f, r, ldwu, 2, u_int16_t) -} - -static u_int32_t -tsunami_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r) -{ - CFGREAD(h, b, s, f, r, ldl, 4, u_int32_t) -} - -static void -tsunami_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data) -{ - CFWRITE(h, b, s, f, r, data, stb, 1) -} - -static void -tsunami_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data) -{ - CFWRITE(h, b, s, f, r, data, stw, 2) -} - -static void -tsunami_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data) -{ - CFWRITE(h, b, s, f, r, data, stl, 4) -} - - -vm_offset_t -tsunami_cvt_bwx(vm_offset_t addr) -{ - int hose; - vm_offset_t laddr; - laddr = addr & 0xffffffffUL; - hose = ADDR_TO_HOSE(laddr); - laddr = STRIP_HOSE(addr); - laddr |= TSUNAMI_MEM(hose); - return (KV(laddr)); -} - -vm_offset_t -tsunami_cvt_dense(vm_offset_t addr) -{ - return tsunami_cvt_bwx(addr); -} - - /* * There doesn't appear to be an hae on this platform */ @@ -394,10 +109,6 @@ static device_method_t tsunami_methods[] = { /* Bus interface */ DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_alloc_resource, pci_alloc_resource), - DEVMETHOD(bus_release_resource, pci_release_resource), - DEVMETHOD(bus_activate_resource, pci_activate_resource), - DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource), DEVMETHOD(bus_setup_intr, tsunami_setup_intr), DEVMETHOD(bus_teardown_intr, tsunami_teardown_intr), @@ -478,7 +189,7 @@ tsunami_sgmap_invalidate(void) } static void -tsunami_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa) +tsunami_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa) { u_int64_t *sgtable = arg; int index = alpha_btop(ba - TSUNAMI_SGMAP_BASE); @@ -522,10 +233,21 @@ void tsunami_init() { static int initted = 0; + static struct bwx_space io_space; + static struct bwx_space mem_space; if (initted) return; initted = 1; + /* + * Define two temporary spaces for bootstrap i/o on hose 0. + */ + bwx_init_space(&io_space, KV(TSUNAMI_IO(0))); + bwx_init_space(&mem_space, KV(TSUNAMI_MEM(0))); + + busspace_isa_io = (kobj_t) &io_space; + busspace_isa_mem = (kobj_t) &mem_space; + chipset = tsunami_chipset; platform.pci_intr_enable = tsunami_intr_enable; platform.pci_intr_disable = tsunami_intr_disable; @@ -539,7 +261,6 @@ static int tsunami_probe(device_t dev) { device_t child; - int *hose; int i; if (tsunami0) return ENXIO; @@ -554,18 +275,13 @@ tsunami_probe(device_t dev) isa_init_intr(); for(i = 0; i < tsunami_num_pchips; i++) { - hose = malloc(sizeof(int), M_DEVBUF, M_NOWAIT); - *hose = i; child = device_add_child(dev, "pcib", i); - device_set_ivars(child, hose); pchip_init(pchip[i], i); } return 0; } - - static int tsunami_attach(device_t dev) { diff --git a/sys/alpha/pci/tsunami_pci.c b/sys/alpha/pci/tsunami_pci.c index 17d7be2..ebf8855 100644 --- a/sys/alpha/pci/tsunami_pci.c +++ b/sys/alpha/pci/tsunami_pci.c @@ -38,111 +38,213 @@ #include <pci/pcivar.h> #include <alpha/pci/tsunamireg.h> #include <alpha/pci/tsunamivar.h> +#include <alpha/pci/pcibus.h> +#include <machine/resource.h> +#include <machine/bwx.h> +#include "alphapci_if.h" +#include "pcib_if.h" + +struct tsunami_hose_softc { + struct bwx_space io; /* accessor for ports */ + struct bwx_space mem; /* accessor for memory */ + struct rman io_rman; /* resource manager for ports */ + struct rman mem_rman; /* resource manager for memory */ +}; static devclass_t pcib_devclass; -int tsunami_hoses[TSUNAMI_MAXHOSES+1] = {1,-1,-1,-1,-1}; -int tsunami_maxhoseno = 0; +static int +tsunami_pcib_probe(device_t dev) +{ + struct tsunami_hose_softc *sc = device_get_softc(dev); + device_t child; -extern int tsunami_num_pchips; + device_set_desc(dev, "21271 PCI host bus adapter"); -/* - * This comment attempts to explain why and how we are mapping from - * the DEQ assigned bus numbers to the FreeBSD assigned numbers. - * - * FreeBSD must number buses with monotonically increasing numbers for a - * variety of reasons (pciconf, newbus, etc). - * - * DEQ numbers them (from what I can tell) on a per-hose bases. And - * for some reason they seem to always leave bus 1 unused. - * - * When generating config space addrs, we need to know if we are - * directly on the primary bus on that hose, or if we are behind a ppb. - * We keep track of this by assigning hoses monotonically increasing - * numbers. This fits nicely with DEQ not using bus number 1; I - * assume that is what it as intended for. I guess we'll see if they - * come out with a system using more than one pchip.. - * - * Next, we must attempt to map the FreeBSD assigned numbers to the - * numbers assigned by DEQ in order to generate proper config space - * addrs. We store the next number past the 0th bus of our hose and - * do subtraction to determine what the DEQ number should have been, - * given a FreeBSD bus number. This is disgusting & quite possibly - * wrong. - */ + child = device_add_child(dev, "pci", -1); + + bwx_init_space(&sc->io, KV(TSUNAMI_IO(device_get_unit(dev)))); + bwx_init_space(&sc->mem, KV(TSUNAMI_MEM(device_get_unit(dev)))); + + sc->io_rman.rm_start = 0; + sc->io_rman.rm_end = ~0u; + sc->io_rman.rm_type = RMAN_ARRAY; + sc->io_rman.rm_descr = "I/O ports"; + if (rman_init(&sc->io_rman) + || rman_manage_region(&sc->io_rman, 0x0, (1L << 32))) + panic("tsunami_pcib_probe: io_rman"); + + sc->mem_rman.rm_start = 0; + sc->mem_rman.rm_end = ~0u; + sc->mem_rman.rm_type = RMAN_ARRAY; + sc->mem_rman.rm_descr = "I/O memory"; + if (rman_init(&sc->mem_rman) + || rman_manage_region(&sc->mem_rman, 0x0, (1L << 32))) + panic("tsunami_pcib_probe: mem_rman"); -int -tsunami_bus_within_hose(int hose, int bus) + /* + * Replace the temporary bootstrap spaces with real onys. This + * isn't stictly necessary but it keeps things tidy. + */ + if (device_get_unit(dev) == 0) { + busspace_isa_io = (kobj_t) &sc->io; + busspace_isa_mem = (kobj_t) &sc->mem; + } + + return 0; +} + +static int +tsunami_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result) { - if (hose == bus) - return 0; - else - return ( (bus - tsunami_hoses[hose]) + 1); + if (which == PCIB_IVAR_BUS) { + *result = 0; + } + return ENOENT; } -/* - * this function supports pciconf ioctls - */ +static void * +tsunami_pcib_cvt_dense(device_t dev, vm_offset_t addr) +{ + int h = device_get_unit(dev); + addr &= 0xffffffffUL; + return (void *) KV(addr | TSUNAMI_MEM(h)); +} + +static void * +tsunami_pcib_cvt_bwx(device_t dev, vm_offset_t addr) +{ + int h = device_get_unit(dev); + addr &= 0xffffffffUL; + return (void *) KV(addr | TSUNAMI_MEM(h)); +} -int -tsunami_hose_from_bus(int bus) +static kobj_t +tsunami_pcib_get_bustag(device_t dev, int type) { - int i; + struct tsunami_hose_softc *sc = device_get_softc(dev); - if (bus < tsunami_maxhoseno) - return bus; + switch (type) { + case SYS_RES_IOPORT: + return (kobj_t) &sc->io; - for (i = 1; i <= TSUNAMI_MAXHOSES && tsunami_hoses[i] != -1; i++){ - if(tsunami_hoses[i] >= bus) - return i-1; + case SYS_RES_MEMORY: + return (kobj_t) &sc->mem; } - return i-1; + return 0; } +static struct rman * +tsunami_pcib_get_rman(device_t dev, int type) +{ + struct tsunami_hose_softc *sc = device_get_softc(dev); + + switch (type) { + case SYS_RES_IOPORT: + return &sc->io_rman; + + case SYS_RES_MEMORY: + return &sc->mem_rman; + } + + return 0; +} static int -tsunami_pcib_probe(device_t dev) +tsunami_pcib_maxslots(device_t dev) { - static int error; - device_t child; - int lastbus; + return 31; +} - device_set_desc(dev, "21271 PCI host bus adapter"); +static void +tsunami_clear_abort(void) +{ + alpha_mb(); + alpha_pal_draina(); +} - child = device_add_child(dev, "pci", -1); +static int +tsunami_check_abort(void) +{ +/* u_int32_t errbits;*/ + int ba = 0; - if (tsunami_maxhoseno) { - lastbus = (device_get_unit(child) - 1); - if (lastbus == 0) /* didn't have a ppb on hose 0 */ - lastbus++; - tsunami_hoses[tsunami_maxhoseno] = lastbus; + alpha_pal_draina(); + alpha_mb(); +#if 0 + errbits = REGVAL(TSUNAMI_CSR_TSUNAMI_ERR); + if (errbits & (TSUNAMI_ERR_RCVD_MAS_ABT|TSUNAMI_ERR_RCVD_TAR_ABT)) + ba = 1; + + if (errbits) { + REGVAL(TSUNAMI_CSR_TSUNAMI_ERR) = errbits; + alpha_mb(); + alpha_pal_draina(); } - if ((error = device_delete_child(dev, child))) - panic("tsunami_pcib_probe: device_delete_child failed\n"); - - child = device_add_child(dev, "pci", tsunami_maxhoseno); - - if (tsunami_maxhoseno != device_get_unit(child)) { - printf("tsunami_pcib_probe: wanted unit %d ", - tsunami_maxhoseno); - printf(" got unit %d\n", device_get_unit(child)); - panic("tsunami_pcib_probe: incorrect bus numbering"); +#endif + return ba; +} + +#define TSUNAMI_CFGADDR(b, s, f, r, h) \ + KV(TSUNAMI_CONF(h) | ((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) + +#define CFGREAD(h, b, s, f, r, op, width, type) do { \ + vm_offset_t va; \ + type data; \ + va = TSUNAMI_CFGADDR(b, s, f, r, h); \ + tsunami_clear_abort(); \ + if (badaddr((caddr_t)va, width)) { \ + tsunami_check_abort(); \ + return ~0; \ + } \ + data = ##op##(va); \ + if (tsunami_check_abort()) \ + return ~0; \ + return data; \ +} while (0) + +#define CFGWRITE(h, b, s, f, r, data, op, width) do { \ + vm_offset_t va; \ + va = TSUNAMI_CFGADDR(b, s, f, r, h); \ + tsunami_clear_abort(); \ + if (badaddr((caddr_t)va, width)) \ + return; \ + ##op##(va, data); \ + tsunami_check_abort(); \ +} while (0) + +static u_int32_t +tsunami_pcib_read_config(device_t dev, int b, int s, int f, + int reg, int width) +{ + int h = device_get_unit(dev); + switch (width) { + case 1: + CFGREAD(h, b, s, f, reg, ldbu, 1, u_int8_t); + case 2: + CFGREAD(h, b, s, f, reg, ldwu, 2, u_int16_t); + case 4: + CFGREAD(h, b, s, f, reg, ldl, 4, u_int32_t); } - tsunami_maxhoseno++; - return 0; + return ~0; } -static int -tsunami_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result) +static void +tsunami_pcib_write_config(device_t dev, int b, int s, int f, + int reg, u_int32_t val, int width) { - if (which == PCIB_IVAR_HOSE) { - *result = *(int*) device_get_ivars(dev); - return 0; + int h = device_get_unit(dev); + switch (width) { + case 1: + CFGWRITE(h, b, s, f, reg, val, stb, 1); + case 2: + CFGWRITE(h, b, s, f, reg, val, stw, 2); + case 4: + CFGWRITE(h, b, s, f, reg, val, stl, 4); } - return ENOENT; } static device_method_t tsunami_pcib_methods[] = { @@ -153,13 +255,24 @@ static device_method_t tsunami_pcib_methods[] = { /* Bus interface */ DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_read_ivar, tsunami_pcib_read_ivar), - DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_alloc_resource, pci_alloc_resource), + DEVMETHOD(bus_release_resource, pci_release_resource), + DEVMETHOD(bus_activate_resource, pci_activate_resource), + DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource), DEVMETHOD(bus_setup_intr, alpha_platform_pci_setup_intr), DEVMETHOD(bus_teardown_intr, alpha_platform_pci_teardown_intr), + /* alphapci interface */ + DEVMETHOD(alphapci_cvt_dense, tsunami_pcib_cvt_dense), + DEVMETHOD(alphapci_cvt_bwx, tsunami_pcib_cvt_bwx), + DEVMETHOD(alphapci_get_bustag, tsunami_pcib_get_bustag), + DEVMETHOD(alphapci_get_rman, tsunami_pcib_get_rman), + + /* pcib interface */ + DEVMETHOD(pcib_maxslots, tsunami_pcib_maxslots), + DEVMETHOD(pcib_read_config, tsunami_pcib_read_config), + DEVMETHOD(pcib_write_config, tsunami_pcib_write_config), + { 0, 0 } }; @@ -167,7 +280,7 @@ static device_method_t tsunami_pcib_methods[] = { static driver_t tsunami_pcib_driver = { "pcib", tsunami_pcib_methods, - 1, + sizeof(struct tsunami_hose_softc), }; |