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