Skip site navigation (1)Skip section navigation (2)
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>