Date: Tue, 8 Aug 2006 00:18:29 +0300 From: Niki Denev <nike_d@cytexbg.com> To: John Baldwin <jhb@freebsd.org> Cc: freebsd-hackers@freebsd.org Subject: Re: jkh weird problem (reading pci device memory) Message-ID: <200608080018.29945.nike_d@cytexbg.com> In-Reply-To: <200608071527.50711.jhb@freebsd.org> References: <44D4A5DC.7080403@cytexbg.com> <200608071527.50711.jhb@freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608080018.29945.nike_d>