Of all the gin joints in all the towns in all the world, Mike Smith had
to walk into mine and say:
> >
> > I am feeling a little dense today, how do you allocate a
> > dma channel for a PCI busmaster device with newbus?
>
> It's a bus master, so you don't.
The logical conclusion is that Larry really does have a question, but
he asked it badly. Since he asked it so badly that we really don't know
what he meant, we should attempt to throw information at him in the hopes
that we'll end up telling him what he wants. This is not as efficient
as asking the question correctly the first time, but communication seems
to be a lost art these days, so what can you do.
First of all, with newbus, you now have pci_read_config() and
pci_write_config() instead of pci_conf_read() and pci_conf_write().
The former accept a device_t and let you specify the register
width (as opposed to forcing to you to use 32-bit accesses all
the time). You may need to enable bus mastering and PIO/memory mapping
mode in the PCI command register as before. Once you do that, you
have to allocate the "resources" that you need. The first resource
is the register access space. This can be either an I/O address in
iospace or a memory base address. The second is the interrupt. You
need to keep track of these resources in your softc structure.
They are allocated with bus_alloc_resource(). For PCI devices,
you used to use pci_map_port() or pci_map_mem(); now you use
bus_alloc_resource() instead, which ultimately has the same effect.
When you allocate the register space resource, you have to pass a
pointer to a resource ID, which for PCI devices is the register to
use. For the SYS_RES_IOPORT resource type, you specify the PCI
iobase address register. For SYS_RES_MEMORY, you specify the
the memory base address register.
Once you have allocated the iospace resource, you can then use
rman_get_bustag() and rman_get_bushandle() to get the bustag and
bushandle that you can use with the bus_space_read()/bus_space_write()
routines to read/write the device registers. The bustag and bushandle
should be treated as opaque; they will let you read from iospace or
memory mapped space depending on the resource type that you allocated.
You also use bus_space_alloc() to allocate the interrupt resource
using SYS_RES_IRQ (the resource ID is 0). To actually map the interrupt
to a handler function, you need to use bus_setup_intr().
Resources can be released with bus_release_resource(), and the interrupt
handler can be detached with bus_teardown_intr(). This allows you to
unload drivers.
For bus master DMA, you can still use vtophys() to map kernel virtual
addresses to physical addresses as before. Ideally one should use
the busdma routines for that, however I haven't figured out how to
use them with network device drivers yet, and nobody has come forward
with a nice simple example that shows how to do it (and no, I don't
mean a NetBSD driver: I mean an example which will actually work in
FreeBSD).
The fxp, xl, sf, sk, ti and other drivers have been newbused and use
bus master DMA; hopefully these should provide decent examples.
-Bill
--
=============================================================================
-Bill Paul (212) 854-6020 | System Manager, Master of Unix-Fu
Work: [EMAIL PROTECTED] | Center for Telecommunications Research
Home: [EMAIL PROTECTED] | Columbia University, New York City
=============================================================================
"It is not I who am crazy; it is I who am mad!" - Ren Hoek, "Space Madness"
=============================================================================
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message