summaryrefslogtreecommitdiffstats
path: root/sys/sparc64
diff options
context:
space:
mode:
authorjmg <jmg@FreeBSD.org>2003-06-22 01:26:08 +0000
committerjmg <jmg@FreeBSD.org>2003-06-22 01:26:08 +0000
commite6efd8ec4391d9b20c677c9b0a816b41e4036b17 (patch)
tree3d354a8901826de77f4cef10d8ec211e9bbddb94 /sys/sparc64
parent752ed0a2b93a05db0bf35585d603eac4ae2bd079 (diff)
downloadFreeBSD-src-e6efd8ec4391d9b20c677c9b0a816b41e4036b17.zip
FreeBSD-src-e6efd8ec4391d9b20c677c9b0a816b41e4036b17.tar.gz
add support for peeking at pci busses on UltraSparc systems. This prevents
data access errors when trying to read/write to non-existant PCI devices. fix the psycho bridge to use peek for probing devices. This no longer fakes it if the OFW node doesn't exist (and the reg == 0). Reviewed by: jake, tmm
Diffstat (limited to 'sys/sparc64')
-rw-r--r--sys/sparc64/include/bus.h27
-rw-r--r--sys/sparc64/include/cpufunc.h9
-rw-r--r--sys/sparc64/pci/psycho.c31
-rw-r--r--sys/sparc64/sparc64/support.S52
-rw-r--r--sys/sparc64/sparc64/trap.c25
5 files changed, 132 insertions, 12 deletions
diff --git a/sys/sparc64/include/bus.h b/sys/sparc64/include/bus.h
index e3ca847..2a3e5a6 100644
--- a/sys/sparc64/include/bus.h
+++ b/sys/sparc64/include/bus.h
@@ -811,6 +811,33 @@ bus_space_copy_region_stream_8(bus_space_tag_t t, bus_space_handle_t h1,
bus_space_write_stream_8(t, h1, o1, bus_space_read_8(t, h2, o2));
}
+static __inline int
+bus_space_peek_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int8_t *a)
+{
+
+ __BUS_DEBUG_ACCESS(h, o, "peek", 1);
+ return (fasword8(bus_type_asi[t->bst_type], (caddr_t)(h + o), a));
+}
+
+static __inline int
+bus_space_peek_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int16_t *a)
+{
+
+ __BUS_DEBUG_ACCESS(h, o, "peek", 2);
+ return (fasword16(bus_type_asi[t->bst_type], (caddr_t)(h + o), a));
+}
+
+static __inline int
+bus_space_peek_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
+ u_int32_t *a)
+{
+
+ __BUS_DEBUG_ACCESS(h, o, "peek", 4);
+ return (fasword32(bus_type_asi[t->bst_type], (caddr_t)(h + o), a));
+}
+
/* Back-compat functions for old ISA drivers */
extern bus_space_tag_t isa_io_bt;
extern bus_space_handle_t isa_io_hdl;
diff --git a/sys/sparc64/include/cpufunc.h b/sys/sparc64/include/cpufunc.h
index 86e7ae5..4c2c9f8 100644
--- a/sys/sparc64/include/cpufunc.h
+++ b/sys/sparc64/include/cpufunc.h
@@ -136,6 +136,15 @@ STNC_GEN(u_long, stxa);
#define stwa(va, asi, val) ST_GENERIC(va, asi, val, stwa)
#define stxa(va, asi, val) ST_GENERIC(va, asi, val, stxa)
+/*
+ * Attempt to read from addr, val. If a Data Access Error trap happens,
+ * they return -1 and the contents of val is undefined. A return of 0
+ * means no trap happened, and the contents of val is valid.
+ */
+int fasword8(u_long asi, void *addr, uint8_t *val);
+int fasword16(u_long asi, void *addr, uint16_t *val);
+int fasword32(u_long asi, void *addr, uint32_t *val);
+
#define membar(mask) do { \
__asm __volatile("membar %0" : : "n" (mask) : "memory"); \
} while (0)
diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c
index 798cfad..4d5a3a3 100644
--- a/sys/sparc64/pci/psycho.c
+++ b/sys/sparc64/pci/psycho.c
@@ -57,6 +57,7 @@
#include <machine/nexusvar.h>
#include <machine/ofw_upa.h>
#include <machine/resource.h>
+#include <machine/cpu.h>
#include <sys/rman.h>
@@ -872,33 +873,39 @@ psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
bus_space_handle_t bh;
u_long offset = 0;
u_int32_t r, devid;
+ u_int8_t byte;
+ u_int16_t shrt;
+ u_int32_t wrd;
int i;
- /*
- * The psycho bridge does not tolerate accesses to unconfigured PCI
- * devices' or function's config space, so look up the device in the
- * firmware device tree first, and if it is not present, return a value
- * that will make the detection code think that there is no device here.
- * This is ugly...
- */
- if (reg == 0 && ofw_pci_find_node(bus, slot, func) == 0)
- return (0xffffffff);
sc = (struct psycho_softc *)device_get_softc(dev);
offset = PSYCHO_CONF_OFF(bus, slot, func, reg);
bh = sc->sc_bh[PCI_CS_CONFIG];
switch (width) {
case 1:
- r = bus_space_read_1(sc->sc_cfgt, bh, offset);
+ i = bus_space_peek_1(sc->sc_cfgt, bh, offset, &byte);
+ r = byte;
break;
case 2:
- r = bus_space_read_2(sc->sc_cfgt, bh, offset);
+ i = bus_space_peek_2(sc->sc_cfgt, bh, offset, &shrt);
+ r = shrt;
break;
case 4:
- r = bus_space_read_4(sc->sc_cfgt, bh, offset);
+ i = bus_space_peek_4(sc->sc_cfgt, bh, offset, &wrd);
+ r = wrd;
break;
default:
panic("psycho_read_config: bad width");
}
+
+ if (i) {
+#ifdef PSYCHO_DEBUG
+ printf("psycho read data error reading: %d.%d.%d: 0x%x\n",
+ bus, slot, func, reg);
+#endif
+ r = -1;
+ }
+
if (reg == PCIR_INTPIN && r == 0) {
/* Check for DQT_BAD_INTPIN quirk. */
devid = psycho_read_config(dev, bus, slot, func,
diff --git a/sys/sparc64/sparc64/support.S b/sys/sparc64/sparc64/support.S
index 2d1c8cb..57ca637 100644
--- a/sys/sparc64/sparc64/support.S
+++ b/sys/sparc64/sparc64/support.S
@@ -527,6 +527,58 @@ ENTRY(fs_fault)
mov -1, %o0
END(fsfault)
+ .globl fas_nofault_begin
+fas_nofault_begin:
+
+/*
+ * int fasword8(u_long asi, uint64_t addr, uint8_t *val)
+ */
+ENTRY(fasword8)
+ wr %o0, 0, %asi
+ membar #Sync
+ lduba [%o1] %asi, %o3
+ membar #Sync
+ stb %o3, [%o2]
+ retl
+ clr %o0
+END(fasword8)
+
+/*
+ * int fasword16(u_long asi, uint64_t addr, uint16_t *val)
+ */
+ENTRY(fasword16)
+ wr %o0, 0, %asi
+ membar #Sync
+ lduha [%o1] %asi, %o3
+ membar #Sync
+ sth %o3, [%o2]
+ retl
+ clr %o0
+END(fasword16)
+
+/*
+ * int fasword32(u_long asi, uint64_t addr, uint32_t *val)
+ */
+ENTRY(fasword32)
+ wr %o0, 0, %asi
+ membar #Sync
+ lduwa [%o1] %asi, %o3
+ membar #Sync
+ stw %o3, [%o2]
+ retl
+ clr %o0
+END(fasword32)
+
+ .globl fas_nofault_end
+fas_nofault_end:
+ nop
+
+ .globl fas_fault
+ENTRY(fas_fault)
+ retl
+ mov -1, %o0
+END(fas_fault)
+
.globl fpu_fault_begin
fpu_fault_begin:
nop
diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c
index 6f800f6..9ced771 100644
--- a/sys/sparc64/sparc64/trap.c
+++ b/sys/sparc64/sparc64/trap.c
@@ -101,6 +101,10 @@ extern char fs_nofault_end[];
extern char fs_nofault_intr_begin[];
extern char fs_nofault_intr_end[];
+extern char fas_fault[];
+extern char fas_nofault_begin[];
+extern char fas_nofault_end[];
+
extern char *syscallnames[];
const char *trap_msg[] = {
@@ -329,6 +333,27 @@ trap(struct trapframe *tf)
}
error = 1;
break;
+ case T_DATA_ERROR:
+ /*
+ * handle PCI poke/peek as per UltraSPARC IIi
+ * User's Manual 16.2.1.
+ *
+ * XXX - We really should make sure that tpc is
+ * pointing to the membar #Sync we are expecting.
+ */
+#define MEMBARSYNC_INST ((u_int32_t)0x8143e040)
+ if (tf->tf_tpc > (u_long)fas_nofault_begin &&
+ tf->tf_tpc < (u_long)fas_nofault_end &&
+ *(u_int32_t *)tf->tf_tpc == MEMBARSYNC_INST &&
+ ((u_int32_t *)tf->tf_tpc)[-2] == MEMBARSYNC_INST) {
+ tf->tf_tpc = (u_long)fas_fault;
+ tf->tf_tnpc = tf->tf_tpc + 4;
+ error = 0;
+ break;
+ }
+#undef MEMBARSYNC_INST
+ error = 1;
+ break;
default:
error = 1;
break;
OpenPOWER on IntegriCloud