diff options
author | jmg <jmg@FreeBSD.org> | 2003-06-22 01:26:08 +0000 |
---|---|---|
committer | jmg <jmg@FreeBSD.org> | 2003-06-22 01:26:08 +0000 |
commit | e6efd8ec4391d9b20c677c9b0a816b41e4036b17 (patch) | |
tree | 3d354a8901826de77f4cef10d8ec211e9bbddb94 /sys/sparc64 | |
parent | 752ed0a2b93a05db0bf35585d603eac4ae2bd079 (diff) | |
download | FreeBSD-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.h | 27 | ||||
-rw-r--r-- | sys/sparc64/include/cpufunc.h | 9 | ||||
-rw-r--r-- | sys/sparc64/pci/psycho.c | 31 | ||||
-rw-r--r-- | sys/sparc64/sparc64/support.S | 52 | ||||
-rw-r--r-- | sys/sparc64/sparc64/trap.c | 25 |
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; |