Reading acpi memory from a driver attached to hostb
Andre Albsmeier
Andre.Albsmeier at siemens.com
Fri Jul 24 16:17:46 UTC 2009
On Thu, 23-Jul-2009 at 16:06:11 -0400, John Baldwin wrote:
> On Thursday 23 July 2009 1:53:51 pm Andre Albsmeier wrote:
> > John, apparently you sent me an email (thanks a lot) which I never
> > received (we have to blame our company's spam filters which I do
> > not control). I'll comment on it here in my reply to Doug...
>
> Yes, I saw the bounces. Hopefully you see the list version of this.
Yes, I've been lucky this time.
>
> > > | Did you try
> > > | doing 'bus_alloc_resource(device_get_parent(device_get_parent(dev))' in
> your
> > > | driver that is a child of hostb0?
> >
> > I tried this, well, something similar: I had to do 4 times
> > device_get_parent() to end up at acpi0:
> >
> > mydriver -> hostb0 -> pci0 -> pcib0 -> acpi0
>
> You don't actually need to do that. pci0 will pass the request up to acpi0
That's what I hoped as well.
> eventually. You just need to ask pci0 to allocate it for you and it will see
> you are not a direct child and take the 'passthrough' case here:
>
> struct resource *
> pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
> u_long start, u_long end, u_long count, u_int flags)
> {
> ...
>
> if (device_get_parent(child) != dev)
> return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
> type, rid, start, end, count, flags));
> ...
> }
>
> Rather than trying to allocate the whole chunk of the ACPI resource, I would
> just do a specific allocation like so:
>
> rid = 0;
> res = BUS_ALLOC_RESOURCE(device_get_parent(device_get_parent(dev)),
> dev, SYS_RES_MEMORY, &rid, <the real start address>, <the real
> end address>, <the length>, RF_ACTIVE);
OK, I have modified my driver exactly this way, but still no success.
It seems my code didn't make it to the list (the attachment
was stripped) so I include it inline now. Testing is quite
simple, every feedback is welcome:
1. check if "devinfo -r" spits out some free "I/O memory addresses"
ranges under acpi0 with at minimum 4 bytes length.
2. select one of them and assign its start address to rstart in
eccmon_probe() at the line which reads now
u_long rstart = 0xfed14000;
(this is the address I use for testing)
3. compile, kldload and dmesg. I always get the message
"bus_alloc_resource() returned NULL".
Thanks,
-Andre
-------------------- eccmon.c start -------------------------------------
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <machine/bus.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <machine/pci_cfgreg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
struct eccmon_softc {
device_t dev;
int res_set; /* flag if bus_set_resource() was used successfully */
struct resource* res;
int rid;
};
/**********************/
/* eccmon_probe() */
/**********************/
static int eccmon_probe( const device_t const dev )
{
u_long rstart = 0xfed14000;
int ret;
struct resource* res;
int rid = 0;
device_printf( dev, "probe: started for %x:%x\n", pci_get_vendor( dev ) , pci_get_device( dev ) );
/*
* try to bus_alloc_resource the resource and give it back
*/
if( (res = BUS_ALLOC_RESOURCE( device_get_parent(device_get_parent(dev)), dev, SYS_RES_MEMORY, &rid, rstart, rstart+4, 4, RF_ACTIVE )) == NULL ) {
device_printf( dev, "bus_alloc_resource() returned NULL\n" );
return ENXIO;
}
if( (ret = BUS_RELEASE_RESOURCE( device_get_parent(device_get_parent(dev)), dev, SYS_RES_MEMORY, rid, res )) != 0 )
device_printf( dev, "bus_release_resource() returned %d\n", ret );
return ENXIO;
}
/***********************/
/* eccmon_attach() */
/***********************/
static int eccmon_attach( const device_t const dev )
{
device_printf( dev, "attach: started for %x:%x\n", pci_get_vendor( dev ) , pci_get_device( dev ) );
return ENXIO;
}
/***********************/
/* eccmon_detach() */
/***********************/
static int eccmon_detach( const device_t const dev )
{
device_printf( dev, "detach: started for %x:%x\n", pci_get_vendor( dev ) , pci_get_device( dev ) );
return 0;
}
/*************************/
/* eccmon_identify() */
/*************************/
static void eccmon_identify( driver_t *driver, device_t p )
{
device_printf( p, "identify: start: %x %x\n", pci_get_vendor( p ), pci_get_device( p ) );
device_printf( p, "identify on: %s %d\n", device_get_name( p ), device_get_unit(p) );
if( device_find_child( p, "eccmon", -1 ) == NULL &&
strcmp( device_get_name( p ), "hostb" ) == 0 &&
device_get_unit( p ) == 0 ) {
device_t child = device_add_child( p, "eccmon", -1 );
device_printf( p, "identify added child: %p\n", child );
}
}
/***********************/
/* driver(9) stuff */
/***********************/
static device_method_t eccmon_methods[] = {
DEVMETHOD( device_identify, eccmon_identify ),
DEVMETHOD( device_probe, eccmon_probe ),
DEVMETHOD( device_attach, eccmon_attach ),
DEVMETHOD( device_detach, eccmon_detach ),
{ 0, 0 }
};
static driver_t eccmon_driver = {
"eccmon",
eccmon_methods,
sizeof( struct eccmon_softc )
};
static devclass_t eccmon_devclass;
DRIVER_MODULE( eccmon, hostb, eccmon_driver, eccmon_devclass, NULL, NULL );
-------------------- eccmon.c end -------------------------------------
-------------------- Makefile start -------------------------------------
KMOD = eccmon
SRCS = eccmon.c device_if.h bus_if.h pci_if.h
NO_MAN = 1
CFLAGS+=-DDEVEL
.include <bsd.kmod.mk>
-------------------- Makefile end -------------------------------------
More information about the freebsd-hackers
mailing list