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