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
This commit is contained in:
John-Mark Gurney 2003-06-22 01:26:08 +00:00
parent d98ddc4615
commit dffca5a624
5 changed files with 132 additions and 12 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -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;