diff options
Diffstat (limited to 'sys/alpha/pci/apecs_pci.c')
-rw-r--r-- | sys/alpha/pci/apecs_pci.c | 115 |
1 files changed, 114 insertions, 1 deletions
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 } }; |