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$
|
||||
-->
|
||||
<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>
|
||||
|
||||
<indexterm><primary>PCI bus</primary></indexterm>
|
||||
|
@ -20,9 +22,10 @@
|
|||
to any of them.</para>
|
||||
|
||||
<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.
|
||||
*
|
||||
* Murray Stokely
|
||||
|
@ -232,7 +235,7 @@ DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);</programlisting>
|
|||
<sect2>
|
||||
<title><filename>Makefile</filename> for Sample Driver</title>
|
||||
|
||||
<programlisting># Makefile for mypci driver
|
||||
<programlisting># Makefile for mypci driver
|
||||
|
||||
KMOD= mypci
|
||||
SRCS= mypci.c
|
||||
|
@ -251,13 +254,16 @@ SRCS+= device_if.h bus_if.h pci_if.h
|
|||
|
||||
<sect2>
|
||||
<title>Additional Resources</title>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><simpara><link xlink:href="http://www.pcisig.org/">PCI
|
||||
Special Interest Group</link></simpara></listitem>
|
||||
<listitem>
|
||||
<simpara><link xlink:href="http://www.pcisig.org/">PCI
|
||||
Special Interest Group</link></simpara>
|
||||
</listitem>
|
||||
|
||||
<listitem><simpara>PCI System Architecture, Fourth Edition by
|
||||
Tom Shanley, et al.</simpara></listitem>
|
||||
|
||||
Tom Shanley, et al.</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
@ -265,7 +271,8 @@ SRCS+= device_if.h bus_if.h pci_if.h
|
|||
<sect1 xml:id="pci-bus">
|
||||
<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
|
||||
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
|
||||
|
@ -275,18 +282,20 @@ SRCS+= device_if.h bus_if.h pci_if.h
|
|||
<sect2>
|
||||
<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
|
||||
will need to obtain the <emphasis>Base Address
|
||||
Registers</emphasis> (BARs) from the PCI Configuration space.
|
||||
The PCI-specific details of obtaining the BAR are abstracted in
|
||||
the <function>bus_alloc_resource()</function> function.</para>
|
||||
will need to obtain the <emphasis>Base Address
|
||||
Registers</emphasis> (BARs) from the PCI Configuration
|
||||
space. The PCI-specific details of obtaining the BAR are
|
||||
abstracted in the <function>bus_alloc_resource()</function>
|
||||
function.</para>
|
||||
|
||||
<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,
|
||||
0, ~0, 1, RF_ACTIVE);
|
||||
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>
|
||||
|
||||
<para>Handles for each base address register are kept in the
|
||||
<varname remap="structname">softc</varname> structure so that they can be
|
||||
used to write to the device later.</para>
|
||||
<varname remap="structname">softc</varname> structure so that
|
||||
they can be used to write to the device later.</para>
|
||||
|
||||
<para>These handles can then be used to read or write from the
|
||||
device registers with the <function>bus_space_*</function>
|
||||
functions. For example, a driver might contain a shorthand
|
||||
function to read from a board specific register like this:</para>
|
||||
device registers with the <function>bus_space_*</function>
|
||||
functions. For example, a driver might contain a shorthand
|
||||
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)
|
||||
{
|
||||
return bus_space_read_2(sc->bar1_bt, sc->bar1_bh, address);
|
||||
}
|
||||
</programlisting>
|
||||
}</programlisting>
|
||||
|
||||
<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)
|
||||
{
|
||||
bus_space_write_2(sc->bar1_bt, sc->bar1_bh, address, value);
|
||||
}
|
||||
</programlisting>
|
||||
}</programlisting>
|
||||
|
||||
<para>These functions exist in 8bit, 16bit, and 32bit versions
|
||||
and you should use
|
||||
<function>bus_space_{read|write}_{1|2|4}</function>
|
||||
accordingly.</para>
|
||||
and you should use
|
||||
<function>bus_space_{read|write}_{1|2|4}</function>
|
||||
accordingly.</para>
|
||||
|
||||
<note>
|
||||
<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
|
||||
resource *</type> pointer instead of a bus tag and handle.
|
||||
Thus, you could drop the bus tag and bus handle members from
|
||||
the <varname remap="structname">softc</varname> and rewrite the
|
||||
<function>board_read()</function> function as:</para>
|
||||
the <varname remap="structname">softc</varname> and rewrite
|
||||
the <function>board_read()</function> function as:</para>
|
||||
|
||||
<programlisting>uint16_t
|
||||
<programlisting>uint16_t
|
||||
board_read(struct ni_softc *sc, uint16_t address)
|
||||
{
|
||||
return (bus_read(sc->bar1res, address));
|
||||
}
|
||||
</programlisting>
|
||||
}</programlisting>
|
||||
</note>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<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
|
||||
in a way similar to the memory resources. First an IRQ
|
||||
resource must be allocated from the parent bus, and then the
|
||||
interrupt handler must be set up to deal with this IRQ.</para>
|
||||
in a way similar to the memory resources. First an IRQ
|
||||
resource must be allocated from the parent bus, and then the
|
||||
interrupt handler must be set up to deal with this IRQ.</para>
|
||||
|
||||
<para>Again, a sample from a device
|
||||
<function>attach()</function> function says more than
|
||||
words.</para>
|
||||
<function>attach()</function> function says more than
|
||||
words.</para>
|
||||
|
||||
<programlisting>/* Get the IRQ resource */
|
||||
<programlisting>/* Get the IRQ resource */
|
||||
|
||||
sc->irqid = 0x0;
|
||||
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) {
|
||||
printf("Couldn't set up irq\n");
|
||||
goto fail4;
|
||||
}
|
||||
</programlisting>
|
||||
}</programlisting>
|
||||
|
||||
<para>Some care must be taken in the detach routine of the
|
||||
driver. You must quiesce the device's interrupt stream, and
|
||||
remove the interrupt handler. Once
|
||||
<function>bus_teardown_intr()</function> has returned, you
|
||||
know that your interrupt handler will no longer be called and
|
||||
that all threads that might have been executing this interrupt handler
|
||||
have returned. Since this function can sleep, you must not hold
|
||||
any mutexes when calling this function.</para>
|
||||
|
||||
driver. You must quiesce the device's interrupt stream, and
|
||||
remove the interrupt handler. Once
|
||||
<function>bus_teardown_intr()</function> has returned, you
|
||||
know that your interrupt handler will no longer be called and
|
||||
that all threads that might have been executing this interrupt
|
||||
handler have returned. Since this function can sleep, you
|
||||
must not hold any mutexes when calling this function.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<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
|
||||
reasons. The proper methods for dealing with these issues is to
|
||||
use the <function>bus_space_dma*()</function> functions instead.
|
||||
This paragraph can be removed when this section is updated to reflect
|
||||
that usage. However, at the moment, the API is in a bit of
|
||||
flux, so once that settles down, it would be good to update this
|
||||
section to reflect that.</para>
|
||||
reasons. The proper methods for dealing with these issues is
|
||||
to use the <function>bus_space_dma*()</function> functions
|
||||
instead. This paragraph can be removed when this section is
|
||||
updated to reflect that usage. However, at the moment, the
|
||||
API is in a bit of flux, so once that settles down, it would
|
||||
be good to update this section to reflect that.</para>
|
||||
|
||||
<para>On the PC, peripherals that want to do bus-mastering DMA
|
||||
must deal with physical addresses. This is a problem since
|
||||
FreeBSD uses virtual memory and deals almost exclusively with
|
||||
virtual addresses. Fortunately, there is a function,
|
||||
<function>vtophys()</function> to help.</para>
|
||||
must deal with physical addresses. This is a problem since
|
||||
FreeBSD uses virtual memory and deals almost exclusively with
|
||||
virtual addresses. Fortunately, there is a function,
|
||||
<function>vtophys()</function> to help.</para>
|
||||
|
||||
<programlisting>#include <vm/vm.h>
|
||||
<programlisting>#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#define vtophys(virtual_address) (...)
|
||||
</programlisting>
|
||||
#define vtophys(virtual_address) (...)</programlisting>
|
||||
|
||||
<para>The solution is a bit different on the alpha however, and
|
||||
what we really want is a function called
|
||||
<function>vtobus()</function>.</para>
|
||||
what we really want is a function called
|
||||
<function>vtobus()</function>.</para>
|
||||
|
||||
<programlisting>#if defined(__alpha__)
|
||||
<programlisting>#if defined(__alpha__)
|
||||
#define vtobus(va) alpha_XXX_dmamap((vm_offset_t)va)
|
||||
#else
|
||||
#define vtobus(va) vtophys(va)
|
||||
#endif
|
||||
</programlisting>
|
||||
|
||||
#endif</programlisting>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Deallocating Resources</title>
|
||||
|
||||
<para>It is very important to deallocate all of the resources
|
||||
that were allocated during <function>attach()</function>.
|
||||
Care must be taken to deallocate the correct stuff even on a
|
||||
failure condition so that the system will remain usable while
|
||||
your driver dies.</para>
|
||||
|
||||
that were allocated during <function>attach()</function>.
|
||||
Care must be taken to deallocate the correct stuff even on a
|
||||
failure condition so that the system will remain usable while
|
||||
your driver dies.</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
</chapter>
|
||||
|
|
Loading…
Reference in a new issue