jkh weird problem (reading pci device memory)
Niki Denev
nike_d at cytexbg.com
Mon Aug 7 21:21:46 UTC 2006
On Monday 07 August 2006 22:27, John Baldwin wrote:
> 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));
>
I tried this, but for some reason it gave me different result than the loop
i'm using right now.
maybe i'm not doing something right, i'll check again.
> 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);
Yes, i'm aware of this problem, and if everything goes well i will
try to make it big-endian friendly, but for now it's easier for me to deal
with less code :)
>
> (Note this also uses the shorter bus_read functions which just take a
> struct resouce *.)
>
Cool! this looks much more convenient. Maybe they must be noted in the manual
page?
> 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:
>
Thanks! The card really needed a delay to setup it's memory right, and i
was reading it too soon. (which is also a mistake, because in the original
linux driver the config table read is done later from the interrupt handler,
when the card has had the time to init it's memory properly.)
> /* XXX: Doesn't it want to print rman_get_size() / 1024 instead? */
> device_printf(dev, "card has %uKB memory\n", sc->card_type);
the "KB" suffix here is a typo :-/
> 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);
> }
Thanks for the useful info!
Best Regards,
Niki Denev
More information about the freebsd-hackers
mailing list