Date: Wed, 11 Apr 2007 10:37:03 -0500 From: Craig Boston <craig@tobuj.gank.org> To: Alan Garfield <alan@fromorbit.com> Cc: hackers@freebsd.org Subject: Re: Resources and ACPI Message-ID: <20070411153703.GC60020@nowhere> In-Reply-To: <1176302227.5057.12.camel@hiro.auspc.com.au> References: <200704110951.l3B9p4hT024402@sana.init-main.com> <461CCB3D.1090402@fromorbit.com> <20070411140214.GA60020@nowhere> <1176302227.5057.12.camel@hiro.auspc.com.au>
next in thread | previous in thread | raw e-mail | index | archive | help
Ok, well just for the record it's been a while since I've worked with busdma so my knowledge is more of a high level overview. Hopefully if I get anything wrong someone will step in and correct me. :) On Thu, Apr 12, 2007 at 12:37:07AM +1000, Alan Garfield wrote: > I've got a very machine specific device (eg. it's built into the PRS > controller on the motherboard) so I don't think I have to worry about > machine independence. Machine independence is just a side benefit of using busdma, really it's the standard "FreeBSD driver API" way of doing things. > At the moment I've got the io ports and irq's being hardcoded into the > driver, which seems icky to me. The acpi bus when the device is attached > outputs all the appropriate resources so _something_ knows what they > are. All I want is a way to access them and to know what they are. The question is, do you really need to know what they are? The way it's supposed to work is you do something like this. int rid; rid = i; /* Allocate the i-th IO port resource */ sc->io[i] = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); /* Get a tag for use with bus_space */ sc->iot[i] = rman_get_bustag(sc->io[i]); /* Get a handle describing the resource */ sc->ioh[i] = rman_get_bushandle(sc->io[i]); bus_alloc_resource_any tells the OS to use the "default" resource allocation, which for a device that's enumerated through ACPI will be the values that you're seeing through acpi. The rman_get_* functions retrieve the tag and handle associated with the resource for use with the bus_space_* functions. AFAIK these are valid until you call bus_release_resource on sc->io[i], at which point they should be discarded. Then to read or write to registers within your IO range, you would do something like this: bus_space_write_1(sc->iot[0], sc->ioh[0], offset, value); /* Write a single byte to (your first IO port) + offset */ value = bus_space_read_2(sc->iot[1], sc->ioh[1], offset); /* Read a word from (your second IO port) + offset */ When you use bus_space_*, you don't need to know the exact starting address of your ports like you would with outb(). You only need to know the offset within the range that your device uses, the API automatically takes care of the rest. Many drivers wrap bus_space_read_* and write_* in a set of macros that automatically fill in the tag and handler, for convenience. If you really want to know the address, for example to print out for debugging messages: start = rman_get_start(sc->io[i]); size = rman_get_size(sc->io[i]); The "io 0x??? - 0x??? irq X" messages that are printed when the device attaches are normally handled by your parent bus, so you normally don't even need to worry about what the actual port base is. For an IRQ you typically call bus_setup_intr() with your resource pointer and handler function. If you need to know the IRQ number for some reason, rman_get_start() should work on that as well. There are lots of examples of using the busdma API in the kernel tree (virtually every driver). Hope this helps, Craig
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070411153703.GC60020>