Clean up the following igor warnings:
- wrap long line - add blank line after previous line - use tabs instead of spaces - straggling <tag> Event: vBSDcon FreeBSD Hackathon
This commit is contained in:
parent
e6a8ba37d0
commit
6c190c76c3
Notes:
svn2git
2020-12-08 03:00:23 +00:00
svn path=/head/; revision=53377
1 changed files with 83 additions and 78 deletions
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
$FreeBSD$
|
$FreeBSD$
|
||||||
-->
|
-->
|
||||||
<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:id="pci">
|
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
|
||||||
|
xml:id="pci">
|
||||||
<title>PCI Devices</title>
|
<title>PCI Devices</title>
|
||||||
|
|
||||||
<indexterm><primary>PCI bus</primary></indexterm>
|
<indexterm><primary>PCI bus</primary></indexterm>
|
||||||
|
@ -20,9 +22,10 @@
|
||||||
to any of them.</para>
|
to any of them.</para>
|
||||||
|
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>Sample Driver Source (<filename>mypci.c</filename>)</title>
|
<title>Sample Driver Source
|
||||||
|
(<filename>mypci.c</filename>)</title>
|
||||||
|
|
||||||
<programlisting>/*
|
<programlisting>/*
|
||||||
* Simple KLD to play with the PCI functions.
|
* Simple KLD to play with the PCI functions.
|
||||||
*
|
*
|
||||||
* Murray Stokely
|
* Murray Stokely
|
||||||
|
@ -232,7 +235,7 @@ DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);</programlisting>
|
||||||
<sect2>
|
<sect2>
|
||||||
<title><filename>Makefile</filename> for Sample Driver</title>
|
<title><filename>Makefile</filename> for Sample Driver</title>
|
||||||
|
|
||||||
<programlisting># Makefile for mypci driver
|
<programlisting># Makefile for mypci driver
|
||||||
|
|
||||||
KMOD= mypci
|
KMOD= mypci
|
||||||
SRCS= mypci.c
|
SRCS= mypci.c
|
||||||
|
@ -251,13 +254,16 @@ SRCS+= device_if.h bus_if.h pci_if.h
|
||||||
|
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>Additional Resources</title>
|
<title>Additional Resources</title>
|
||||||
|
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
<listitem><simpara><link xlink:href="http://www.pcisig.org/">PCI
|
<listitem>
|
||||||
Special Interest Group</link></simpara></listitem>
|
<simpara><link xlink:href="http://www.pcisig.org/">PCI
|
||||||
|
Special Interest Group</link></simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
<listitem><simpara>PCI System Architecture, Fourth Edition by
|
<listitem><simpara>PCI System Architecture, Fourth Edition by
|
||||||
Tom Shanley, et al.</simpara></listitem>
|
Tom Shanley, et al.</simpara>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
@ -265,7 +271,8 @@ SRCS+= device_if.h bus_if.h pci_if.h
|
||||||
<sect1 xml:id="pci-bus">
|
<sect1 xml:id="pci-bus">
|
||||||
<title>Bus Resources</title>
|
<title>Bus Resources</title>
|
||||||
|
|
||||||
<indexterm><primary>PCI bus</primary><secondary>resources</secondary></indexterm>
|
<indexterm><primary>PCI
|
||||||
|
bus</primary><secondary>resources</secondary></indexterm>
|
||||||
<para>FreeBSD provides an object-oriented mechanism for requesting
|
<para>FreeBSD provides an object-oriented mechanism for requesting
|
||||||
resources from a parent bus. Almost all devices will be a child
|
resources from a parent bus. Almost all devices will be a child
|
||||||
member of some sort of bus (PCI, ISA, USB, SCSI, etc) and these
|
member of some sort of bus (PCI, ISA, USB, SCSI, etc) and these
|
||||||
|
@ -275,18 +282,20 @@ SRCS+= device_if.h bus_if.h pci_if.h
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>Base Address Registers</title>
|
<title>Base Address Registers</title>
|
||||||
|
|
||||||
<indexterm><primary>PCI bus</primary><secondary>Base Address Registers</secondary></indexterm>
|
<indexterm><primary>PCI bus</primary><secondary>Base Address
|
||||||
|
Registers</secondary></indexterm>
|
||||||
|
|
||||||
<para>To do anything particularly useful with a PCI device you
|
<para>To do anything particularly useful with a PCI device you
|
||||||
will need to obtain the <emphasis>Base Address
|
will need to obtain the <emphasis>Base Address
|
||||||
Registers</emphasis> (BARs) from the PCI Configuration space.
|
Registers</emphasis> (BARs) from the PCI Configuration
|
||||||
The PCI-specific details of obtaining the BAR are abstracted in
|
space. The PCI-specific details of obtaining the BAR are
|
||||||
the <function>bus_alloc_resource()</function> function.</para>
|
abstracted in the <function>bus_alloc_resource()</function>
|
||||||
|
function.</para>
|
||||||
|
|
||||||
<para>For example, a typical driver might have something similar
|
<para>For example, a typical driver might have something similar
|
||||||
to this in the <function>attach()</function> function:</para>
|
to this in the <function>attach()</function> function:</para>
|
||||||
|
|
||||||
<programlisting> sc->bar0id = PCIR_BAR(0);
|
<programlisting> sc->bar0id = PCIR_BAR(0);
|
||||||
sc->bar0res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bar0id,
|
sc->bar0res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bar0id,
|
||||||
0, ~0, 1, RF_ACTIVE);
|
0, ~0, 1, RF_ACTIVE);
|
||||||
if (sc->bar0res == NULL) {
|
if (sc->bar0res == NULL) {
|
||||||
|
@ -309,34 +318,33 @@ SRCS+= device_if.h bus_if.h pci_if.h
|
||||||
sc->bar1_bh = rman_get_bushandle(sc->bar1res);</programlisting>
|
sc->bar1_bh = rman_get_bushandle(sc->bar1res);</programlisting>
|
||||||
|
|
||||||
<para>Handles for each base address register are kept in the
|
<para>Handles for each base address register are kept in the
|
||||||
<varname remap="structname">softc</varname> structure so that they can be
|
<varname remap="structname">softc</varname> structure so that
|
||||||
used to write to the device later.</para>
|
they can be used to write to the device later.</para>
|
||||||
|
|
||||||
<para>These handles can then be used to read or write from the
|
<para>These handles can then be used to read or write from the
|
||||||
device registers with the <function>bus_space_*</function>
|
device registers with the <function>bus_space_*</function>
|
||||||
functions. For example, a driver might contain a shorthand
|
functions. For example, a driver might contain a shorthand
|
||||||
function to read from a board specific register like this:</para>
|
function to read from a board specific register like
|
||||||
|
this:</para>
|
||||||
|
|
||||||
<programlisting>uint16_t
|
<programlisting>uint16_t
|
||||||
board_read(struct ni_softc *sc, uint16_t address)
|
board_read(struct ni_softc *sc, uint16_t address)
|
||||||
{
|
{
|
||||||
return bus_space_read_2(sc->bar1_bt, sc->bar1_bh, address);
|
return bus_space_read_2(sc->bar1_bt, sc->bar1_bh, address);
|
||||||
}
|
}</programlisting>
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
<para>Similarly, one could write to the registers with:</para>
|
<para>Similarly, one could write to the registers with:</para>
|
||||||
|
|
||||||
<programlisting>void
|
<programlisting>void
|
||||||
board_write(struct ni_softc *sc, uint16_t address, uint16_t value)
|
board_write(struct ni_softc *sc, uint16_t address, uint16_t value)
|
||||||
{
|
{
|
||||||
bus_space_write_2(sc->bar1_bt, sc->bar1_bh, address, value);
|
bus_space_write_2(sc->bar1_bt, sc->bar1_bh, address, value);
|
||||||
}
|
}</programlisting>
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
<para>These functions exist in 8bit, 16bit, and 32bit versions
|
<para>These functions exist in 8bit, 16bit, and 32bit versions
|
||||||
and you should use
|
and you should use
|
||||||
<function>bus_space_{read|write}_{1|2|4}</function>
|
<function>bus_space_{read|write}_{1|2|4}</function>
|
||||||
accordingly.</para>
|
accordingly.</para>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>In FreeBSD 7.0 and later, you can use the
|
<para>In FreeBSD 7.0 and later, you can use the
|
||||||
|
@ -345,31 +353,33 @@ board_write(struct ni_softc *sc, uint16_t address, uint16_t value)
|
||||||
<function>bus_*</function> functions take a <type>struct
|
<function>bus_*</function> functions take a <type>struct
|
||||||
resource *</type> pointer instead of a bus tag and handle.
|
resource *</type> pointer instead of a bus tag and handle.
|
||||||
Thus, you could drop the bus tag and bus handle members from
|
Thus, you could drop the bus tag and bus handle members from
|
||||||
the <varname remap="structname">softc</varname> and rewrite the
|
the <varname remap="structname">softc</varname> and rewrite
|
||||||
<function>board_read()</function> function as:</para>
|
the <function>board_read()</function> function as:</para>
|
||||||
|
|
||||||
<programlisting>uint16_t
|
<programlisting>uint16_t
|
||||||
board_read(struct ni_softc *sc, uint16_t address)
|
board_read(struct ni_softc *sc, uint16_t address)
|
||||||
{
|
{
|
||||||
return (bus_read(sc->bar1res, address));
|
return (bus_read(sc->bar1res, address));
|
||||||
}
|
}</programlisting>
|
||||||
</programlisting>
|
|
||||||
</note>
|
</note>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>Interrupts</title>
|
<title>Interrupts</title>
|
||||||
|
|
||||||
<indexterm><primary>PCI bus</primary><secondary>interrupts</secondary></indexterm>
|
<indexterm><primary>PCI
|
||||||
|
bus</primary><secondary>interrupts</secondary></indexterm>
|
||||||
|
|
||||||
<para>Interrupts are allocated from the object-oriented bus code
|
<para>Interrupts are allocated from the object-oriented bus code
|
||||||
in a way similar to the memory resources. First an IRQ
|
in a way similar to the memory resources. First an IRQ
|
||||||
resource must be allocated from the parent bus, and then the
|
resource must be allocated from the parent bus, and then the
|
||||||
interrupt handler must be set up to deal with this IRQ.</para>
|
interrupt handler must be set up to deal with this IRQ.</para>
|
||||||
|
|
||||||
<para>Again, a sample from a device
|
<para>Again, a sample from a device
|
||||||
<function>attach()</function> function says more than
|
<function>attach()</function> function says more than
|
||||||
words.</para>
|
words.</para>
|
||||||
|
|
||||||
<programlisting>/* Get the IRQ resource */
|
<programlisting>/* Get the IRQ resource */
|
||||||
|
|
||||||
sc->irqid = 0x0;
|
sc->irqid = 0x0;
|
||||||
sc->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &(sc->irqid),
|
sc->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &(sc->irqid),
|
||||||
|
@ -387,67 +397,62 @@ board_read(struct ni_softc *sc, uint16_t address)
|
||||||
if (error) {
|
if (error) {
|
||||||
printf("Couldn't set up irq\n");
|
printf("Couldn't set up irq\n");
|
||||||
goto fail4;
|
goto fail4;
|
||||||
}
|
}</programlisting>
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
<para>Some care must be taken in the detach routine of the
|
<para>Some care must be taken in the detach routine of the
|
||||||
driver. You must quiesce the device's interrupt stream, and
|
driver. You must quiesce the device's interrupt stream, and
|
||||||
remove the interrupt handler. Once
|
remove the interrupt handler. Once
|
||||||
<function>bus_teardown_intr()</function> has returned, you
|
<function>bus_teardown_intr()</function> has returned, you
|
||||||
know that your interrupt handler will no longer be called and
|
know that your interrupt handler will no longer be called and
|
||||||
that all threads that might have been executing this interrupt handler
|
that all threads that might have been executing this interrupt
|
||||||
have returned. Since this function can sleep, you must not hold
|
handler have returned. Since this function can sleep, you
|
||||||
any mutexes when calling this function.</para>
|
must not hold any mutexes when calling this function.</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>DMA</title>
|
<title>DMA</title>
|
||||||
|
|
||||||
<indexterm><primary>PCI bus</primary><secondary>DMA</secondary></indexterm>
|
<indexterm><primary>PCI
|
||||||
|
bus</primary><secondary>DMA</secondary></indexterm>
|
||||||
|
|
||||||
<para>This section is obsolete, and present only for historical
|
<para>This section is obsolete, and present only for historical
|
||||||
reasons. The proper methods for dealing with these issues is to
|
reasons. The proper methods for dealing with these issues is
|
||||||
use the <function>bus_space_dma*()</function> functions instead.
|
to use the <function>bus_space_dma*()</function> functions
|
||||||
This paragraph can be removed when this section is updated to reflect
|
instead. This paragraph can be removed when this section is
|
||||||
that usage. However, at the moment, the API is in a bit of
|
updated to reflect that usage. However, at the moment, the
|
||||||
flux, so once that settles down, it would be good to update this
|
API is in a bit of flux, so once that settles down, it would
|
||||||
section to reflect that.</para>
|
be good to update this section to reflect that.</para>
|
||||||
|
|
||||||
<para>On the PC, peripherals that want to do bus-mastering DMA
|
<para>On the PC, peripherals that want to do bus-mastering DMA
|
||||||
must deal with physical addresses. This is a problem since
|
must deal with physical addresses. This is a problem since
|
||||||
FreeBSD uses virtual memory and deals almost exclusively with
|
FreeBSD uses virtual memory and deals almost exclusively with
|
||||||
virtual addresses. Fortunately, there is a function,
|
virtual addresses. Fortunately, there is a function,
|
||||||
<function>vtophys()</function> to help.</para>
|
<function>vtophys()</function> to help.</para>
|
||||||
|
|
||||||
<programlisting>#include <vm/vm.h>
|
<programlisting>#include <vm/vm.h>
|
||||||
#include <vm/pmap.h>
|
#include <vm/pmap.h>
|
||||||
|
|
||||||
#define vtophys(virtual_address) (...)
|
#define vtophys(virtual_address) (...)</programlisting>
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
<para>The solution is a bit different on the alpha however, and
|
<para>The solution is a bit different on the alpha however, and
|
||||||
what we really want is a function called
|
what we really want is a function called
|
||||||
<function>vtobus()</function>.</para>
|
<function>vtobus()</function>.</para>
|
||||||
|
|
||||||
<programlisting>#if defined(__alpha__)
|
<programlisting>#if defined(__alpha__)
|
||||||
#define vtobus(va) alpha_XXX_dmamap((vm_offset_t)va)
|
#define vtobus(va) alpha_XXX_dmamap((vm_offset_t)va)
|
||||||
#else
|
#else
|
||||||
#define vtobus(va) vtophys(va)
|
#define vtobus(va) vtophys(va)
|
||||||
#endif
|
#endif</programlisting>
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>Deallocating Resources</title>
|
<title>Deallocating Resources</title>
|
||||||
|
|
||||||
<para>It is very important to deallocate all of the resources
|
<para>It is very important to deallocate all of the resources
|
||||||
that were allocated during <function>attach()</function>.
|
that were allocated during <function>attach()</function>.
|
||||||
Care must be taken to deallocate the correct stuff even on a
|
Care must be taken to deallocate the correct stuff even on a
|
||||||
failure condition so that the system will remain usable while
|
failure condition so that the system will remain usable while
|
||||||
your driver dies.</para>
|
your driver dies.</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
Loading…
Reference in a new issue