Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 10 Sep 2015 14:24:20 -0700
From:      John Baldwin <jhb@freebsd.org>
To:        freebsd-hackers@freebsd.org
Cc:        "Pokala, Ravi" <rpokala@panasas.com>
Subject:   Re: bus_.*_resource() and rid
Message-ID:  <1685918.WyYIclYTSg@ralph.baldwin.cx>
In-Reply-To: <D214E963.145154%rpokala@panasas.com>
References:  <D214E963.145154%rpokala@panasas.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wednesday, September 09, 2015 02:37:04 AM Pokala, Ravi wrote:
> Hi folks,
> 
> I'm modifying a home-grown device driver; this is the first time I've
> played around in device-probe and -attach, so I'm a bit out of my element
> here. This is an LPC device attached to a PCI-ISA bridge (aka the LPC
> controller). It's accessed through IOPORT, and the BIOS sets up enough
> stuff that we can look for it.
> 
> One thing that's confusing me is the "rid" which is passed to a bunch of
> the bus_.*_resource() functions. I've looked at bus_set_resource(9),
> bus_alloc_resource(9), and section 10.5 of the Architecture Handbook[1],
> and I'm still confused.
> 
> bus_alloc_resource(9) says:
> 
>      rid points to a bus specific handle that identifies the resource being
>      allocated.  For ISA this is an index into an array of resources that
> have
>      been setup for this device by either the PnP mechanism, or via the
> hints
>      mechanism. ...
> 
> 
> But there's no indication as to how we get that index. One possibility is
> that the value passed in doesn't matter; bus_alloc_resource() sets it
> correctly and the caller can use the new value. However, that doesn't
> appear to be the case, since lots of times rid is ignored after the call
> to bus_alloc_resource().
> 
> For the sake of discussion, here are stripped-down versions of our probe
> and attach functions:
> 
> xxx_probe_unit(device_t dev)
> {
> 	uint32_t ioport_base;
> 	uint32_t ioport_size;
> 	int rc;
> 
> 	/* Device identification stuff; details unimportant, but we determine
> 	 * ioport_base and ioport_size.
> 	 */
> 
> 	rc = bus_set_resource(
> 	    /* dev */ dev,
> 	    /* type */ SYS_RES_IOPORT,
> 	    /* rid */ 0,
> 	    /* start */ ioport_base,
> 	    /* count */ ioport_size);
> }
> 
> Most of those args are obvious, but I have no idea why rid is 0. It looks
> like lots of drivers pass in a rid of 0, and the original author might
> have just shrugged and gone with "convention".
> 
> xxx_attach_unit(device_t dev)
> {
> 	struct xxx_softc *sc;
> 	int rid;
> 	struct resource res;
> 
> 	sc = device_get_softc(dev);
> 
> 	/* Device configuration stuff; details unimportant. */
> 
> 	rid = 0;
> 	res = bus_alloc_resource(
> 	    /* dev */ dev,
> 	    /* type */ SYS_RES_IOPORT,
> 	    /* rid */ &rid,
> 	    /* start */ 0,
> 	    /* end */ ~0,
> 	    /* count */ sc->ioport_size,
> 	    /* flags */ RF_ACTIVE);
> 
> 	/* save stuff for use with bus_space_{read,write}_1() */
> 	sc->iobase_addr = rman_get_start(res);
> 	sc->iobase_bustag = rman_get_bustag(res);
> 	sc->iobase_bushandle = rman_get_bushandle(res);
> 	sc->dev = dev;
> }
> 
> Again, most things are fairly obvious, but I have no idea why rid is 0.
> It's passed by reference to bus_alloc_resource(), but the
> potentially-altered value is never stored or used.
> 
> The lazy part of me says to just go with blindly passing in 0, because it
> works. However, the new device I'm adding support for will have multiple
> IOPORT ranges associated with it, so I'm not sure if passing 0 is the
> right thing.
> 
> Any help would be appreciated.

Each bus decides how to manage RIDs.  For PCI devices, RIDs are the
address of the corresponding BAR for memory and I/O port resources and
follow a different convention for interrupts (0 == INTx, 1...N == MSI/MSI-X).
For ISA devices (and ACPI) RIDs are 0...N.  If a device is enumerated via
the firmware (e.g. ACPI DSDT entry with _CRS or PNPBIOS data for non-ACPI)
then the firmware assigned resources are set for you by the parent bus and
start at 0 (if you have two I/O port resources you'd have the second one at
rid 1).

If you are doing this on the LPC, then that it is actually a PCI device,
and I don't know if the PCI bus is really going to let you create a rid 
at 0 via bus_set_resource().  Hmm, it should, but it's kind of a bit
hacky.  It might be somewhat cleaner if instead you treat this as an 
ISA device that is a child of isa0 below the LPC device.  You can use an
identify routine that looks at the grandparent isab0 device and then
allocates this.

However, a rid of 0 "should" work.  You can check the resource list of the
device in kgdb to see if there's a valid resource entry for rid 0.  You could
also try calling bus_get_resource() in your attach routine to see if the
bus_set_resource() "worked".

-- 
John Baldwin



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