lkm i/o port allocation problems

infamous41md at hotpop.com infamous41md at hotpop.com
Sat Jun 19 02:29:07 GMT 2004


/*I am trying to figure out how to port over an infrared reciever driver
from linux to freebsd. i have been reading the developers book, as well as the
source for sio/ep and several other char drivers that use i/o ports.  i can't
seem to get my i/o port allocation to work.  whenever i request the region w/
bus_alloc_resource() it returns NULL to me the first time i load my module.
however, once i try again, i get the message:

ser0 at port 0x2f8-0x2ff on isa0

ser is the name of my module.  so it seems that even tho the alloc call is
failing, somehow i still have the region to myself???  and now, even after i
reboot my computer, whenever i try to load my module i immediately get the above
error message.  so it seems that somehow, even tho it is restarted, it never
lets go of the i/o region??  this module is not called at start time, it is only
loaded when i give kldload command

my other problem is that in order to get the probe/attach functions to be
called, i used the identify function in which i call the BUS_ADD_CHILD()
function as i saw ep driver do. is this correct?  b/c after i load my module
once, the next time i try to load it this call always fails.  is this correct
way to do this? if not, how do i get the probe function to be called, b/c it
wasn't being called when i loaded my module.  here is the code, it is very short
as i chopped out the extra stuff. if someone could please take a quick look im
sure it would be obvious what i've done wrong, but i can't see what the problem
is.  i've been digging thru the resource allocation functions and they're just
to complex for me to understand atm.  thanks very much for any help.
*/

#include <sys/types.h>
#include <sys/errno.h>
#include <sys/param.h>		/* defines used in kernel.h */
#include <sys/kernel.h>		/* types used in module initialization */
#include <sys/module.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/conf.h>   /* cdevsw struct */
#include <sys/malloc.h>
#include <sys/rman.h>
#include <sys/systm.h>		/* uprintf */
#include <sys/uio.h>    /* uio struct */

#include <isa/isavar.h>
#include <isa/pnpvar.h>

/*  device structure    */
static struct resource *rp;

char    ser_driver_name[] = "ser";
devclass_t  ser_devclass;

/*  isa stuff   */
static int	ser_isa_attach(device_t);
static int	ser_isa_detach(device_t);
static int	ser_isa_probe(device_t);
static void ser_isa_ident(driver_t *, device_t); 

static device_method_t ser_isa_methods[] = {
	/* Device interface */
	DEVMETHOD(device_probe,		ser_isa_probe),
	DEVMETHOD(device_attach,	ser_isa_attach),
	DEVMETHOD(device_detach,	ser_isa_detach),
	DEVMETHOD(device_identify,	ser_isa_ident),

	{ 0, 0 }
};

static driver_t ser_isa_driver = {
	ser_driver_name,
	ser_isa_methods,
	0,
};

static struct isa_pnp_id ser_ids[] = {
	{ 0, NULL}
};

static int ser_isa_probe(device_t dev)
{
    uprintf("probing\n");
        
    return 0;
}

static void ser_isa_ident(driver_t *driv, device_t dev)
{
    int ret  = 0;
    device_t    child;

    uprintf("identing\n");
    
    child = BUS_ADD_CHILD(dev, 0, "ser", 0);
    if(child == NULL){
        uprintf("bus add child == NULL\n");
        return;
    }

    device_set_driver(child, driv);

    /*  allocate i/o ports */
    if( (ret = bus_set_resource(child, SYS_RES_IOPORT, 0, 0x2f8, 8)) )
        uprintf("bus set bad, ret = %d\n", ret);
        
}

static int ser_isa_attach(device_t dev)
{
    int rid;

    uprintf("attaching\n");

    rid = 0;
    rp = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 8, RF_ACTIVE);
    if(rp == NULL){
        uprintf("bus alloc bad\n");
    }else{
        uprintf("allocated bus resources\n");
    }
    
    return 0;
}

static int ser_isa_detach(device_t dev)
{
    /*  give back i/o region */
    if(rp){
        if(bus_release_resource(dev, SYS_RES_IOPORT, 0, rp) == 0)
            uprintf("releasd resources\n");
        else
            uprintf("error releasein\n");
    }

    uprintf("detached\n");
    return 0;
}

/*
 * Load handler that deals with the loading and unloading of a KLD.
 */
static int
mdev_loader(struct module * m, int what, void *arg)
{
	int   err = 0;

	switch (what) {
	case MOD_LOAD:		/* kldload */
		break;
	case MOD_UNLOAD:
		break;
	default:
		err = EINVAL;
		break;
	}
	return (err);
}

DRIVER_MODULE(ser, isa, ser_isa_driver, ser_devclass, mdev_loader, 0);


-- 
-sean
-- 
-sean



More information about the freebsd-hackers mailing list