Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 19 Jun 2004 17:00:12 -0600 (MDT)
From:      "M. Warner Losh" <imp@bsdimp.com>
To:        infamous42md@hotpop.com
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: lkm i/o port allocation problems
Message-ID:  <20040619.170012.20320023.imp@bsdimp.com>
In-Reply-To: <20040618221344.1848e9db.infamous42md@hotpop.com>
References:  <20040618221344.1848e9db.infamous42md@hotpop.com>

next in thread | previous in thread | raw e-mail | index | archive | help
: /*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

Do you have another driver at this range of ports?  It is on my
machine:

	sio1 at port 0x2f8-0x2ff irq 3 on isa0

so you have to ensure that you don't have sio binding to this device.
You'll get bus_alloc_resource returning NULL in this case.

: 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???

I don't understand this statement at all.  Just because the ISA bus
thinks your driver might have the resources, doesn't mean that your
driver actually has them.  The information is there because many
devices might be at the same location (think aha and bt).

: and now, even after i
: reboot my computer, whenever i try to load my module i immediately get the above
: error message.

What error message.  You included none in your comments.

: 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

Maybe sio1 has claimed this device already.  Maybe your system has
pnpbios/acpi listing the device?  That's the usual reason...

: 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?

No.  You don't have to do this.  In fact, you shouldn't generally do
this in your driver.  You should either bind to the PNP ID (which gets
reprobed on every driver add), or you should add hints to the boot
loader.

: b/c after i load my module
: once, the next time i try to load it this call always fails. 

That's because one usually doesn't need to do this :-).

: 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),

You rarely need identify.  In this case it is contraindicated.

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

Don't use uprintf.  You will find that when you add the driver to the
boot process, you'll get a panic here because there's no controlling
terminal...

: 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);
:         
: }

This isn't necessary.  I'd not use it at all.

: 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;
: }

Chances are good this is failing because there's another device
already servicing the device that has this range.  This may mean that
you will have to have your driver loaded at boot time so it doesn't do
that and you may also have to hack sio to return an indefinite probe
(some non-0 negative number).

There's something called the softc.  You should store store the
resource in the softc for the driver, not in a global.

: 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;
: }


Apart from the uprintf and sotfc comments above, there's nothign
really wrong here.

: /*
:  * 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);
: }

You don't need this at all.  In fact, it may be causing you problems.
Delete it.

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


Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040619.170012.20320023.imp>