summaryrefslogtreecommitdiffstats
path: root/sys/alpha/pci/apecs_pci.c
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>2000-08-28 21:48:13 +0000
committerdfr <dfr@FreeBSD.org>2000-08-28 21:48:13 +0000
commitdd8b44b3958fa67d802cbbec7c7d82f7fb476229 (patch)
tree61496c144b3ecd15192a2e07e755754e18346bc9 /sys/alpha/pci/apecs_pci.c
parent9ed8ded4d312c58a27de9402fd9802e78a591cb9 (diff)
downloadFreeBSD-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/apecs_pci.c')
-rw-r--r--sys/alpha/pci/apecs_pci.c115
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 }
};
OpenPOWER on IntegriCloud