jkh weird problem (reading pci device memory)
John Baldwin
jhb at freebsd.org
Mon Aug 7 19:29:43 UTC 2006
On Saturday 05 August 2006 10:06, Niki Denev wrote:
> for(i=0; i < sizeof(config_table_t); i++) {
> r = bus_space_read_1(sc->bar.tag, sc->bar.hdl, i);
> *((u_int8_t *)&sc->cfg_table + i) = r;
> }
Note that you can replace this with:
bus_space_read_multi_1(sc->bar.tag, sc->bar.hdl, 0,
(u_int8_t *)&sc->cfg_table, sizeof(config_table_t));
However, if you are really reading in a table with more than just chars, you
might want to read the individual fields and byteswap them as needed (if you
care about portability to a big-endian arch like sparc). That is, if your
device stores the table as little-endian and you had:
typedef struct _config_table {
uint32_t signature;
uint16_t version;
uint8_t dummy;
} config_table_t;
You would do this instead:
sc->cfg_table.signature = letoh32(bus_read_4(sc->bar.res, 0));
sc->cfg_table.version = letoh16(bus_read_2(sc->bar.res, 4));
sc->cfg_table.dummy = bus_read_1(sc->bar.res, 5);
(Note this also uses the shorter bus_read functions which just take a struct
resouce *.)
I have no idea why the printf's make a difference, unless perhaps your card
needs a bit of a delay after it is inserted before it's firmware is fully up
and running. In that case you might want to insert a delay. Something like
this:
/* XXX: Doesn't it want to print rman_get_size() / 1024 instead? */
device_printf(dev, "card has %uKB memory\n", sc->card_type);
count = 0;
while (letoh32(bus_read_4(sc->bar.res, 0)) != CONFIG_MAGIC) {
/* If it's not up after a half-second, give up. */
if (count > 50) {
device_printf(dev, "ConfigTable Bad!\n");
return (ENXIO);
}
count++;
/* Wait 10 ms. */
DELAY(10000);
}
--
John Baldwin
More information about the freebsd-hackers
mailing list