bus_.*_resource() and rid
John Baldwin
jhb at freebsd.org
Thu Sep 10 22:33:00 UTC 2015
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
More information about the freebsd-hackers
mailing list