Diff for /wikisrc/tutorials/bus_space_tutorial.mdwn between versions 1.3 and 1.4

version 1.3, 2013/06/23 14:16:27 version 1.4, 2013/06/23 14:34:32
Line 5 Line 5
 ### Why was this tutorial created?  ### Why was this tutorial created?
   
 -   Introductory-level documentation is scarce  -   Introductory-level documentation is scarce
   
 -   Writing device drivers is often considered black magic  -   Writing device drivers is often considered black magic
   
 -   Reading the man pages won’t give you the big picture  -   Reading the man pages won’t give you the big picture
   
 -   BSD systems are always in need of new drivers  -   BSD systems are always in need of new drivers
   
 -   Device drivers are fun  -   Device drivers are fun
   
 ### What won’t be covered here?  ### What won’t be covered here?
Line 19 Line 15
 We don’t have much time, so several ~~advanced~~ topics were omitted:  We don’t have much time, so several ~~advanced~~ topics were omitted:
   
 -   Interrupt handling  -   Interrupt handling
   
 -   Direct Memory Access and the bus\_dma framework  -   Direct Memory Access and the bus\_dma framework
   
 -   Power management  -   Power management
   
 -   Driver detachment  -   Driver detachment
   
 -   Drivers as kernel modules  -   Drivers as kernel modules
   
 -   Examples for buses other than PCI  -   Examples for buses other than PCI
   
 -   Pretty much everything else...  -   Pretty much everything else...
   
 However, once you finish this tutorial, you should be able to pursue  However, once you finish this tutorial, you should be able to pursue
Line 39  this knowledge yourself. Line 29  this knowledge yourself.
   
 -   The interface between user space and hardware, implemented as a part  -   The interface between user space and hardware, implemented as a part
     of the kernel      of the kernel
   
 -   The NetBSD drivers are written mostly in C  -   The NetBSD drivers are written mostly in C
   
 -   Sometimes they have machine dependent assembler parts, but this is a  -   Sometimes they have machine dependent assembler parts, but this is a
     rare case      rare case
   
 ### What do you need to write a driver?  ### What do you need to write a driver?
   
 -   C programming skills  -   C programming skills
   
 -   Hardware documentation (or the ability to reverse engineer the  -   Hardware documentation (or the ability to reverse engineer the
     hardware)      hardware)
   
 -   A reference driver implementation will help but is not essential  -   A reference driver implementation will help but is not essential
   
 -   A NetBSD installation and kernel source, or a cross-build  -   A NetBSD installation and kernel source, or a cross-build
     environment (the latter is usually preferred for development of      environment (the latter is usually preferred for development of
     drivers)      drivers)
   
 -   A lot of time, coffee and patience  -   A lot of time, coffee and patience
   
 ### Why is writing the device drivers considered difficult?  ### Why is writing the device drivers considered difficult?
   
 -   It’s not as difficult as you may expect, in fact during this  -   It’s not as difficult as you may expect, in fact during this
     tutorial we’ll prove that it’s quite easy      tutorial we’ll prove that it’s quite easy
   
 -   You need to think on a very low level  -   You need to think on a very low level
   
     -   Good understanding of computer architecture is a must      -   Good understanding of computer architecture is a must
   
 -   Often documentation is the main problem – writing the driver is not  -   Often documentation is the main problem – writing the driver is not
     possible if you don’t understand how the device works      possible if you don’t understand how the device works
   
     -   No access to documentation (uncooperative hardware vendors,      -   No access to documentation (uncooperative hardware vendors,
         vendors out of business)          vendors out of business)
   
     -   Documentation is incomplete or plain wrong      -   Documentation is incomplete or plain wrong
   
     -   Reverse engineering can solve these problems but it’s a very      -   Reverse engineering can solve these problems but it’s a very
         time consuming process          time consuming process
   
 The NetBSD driver model  ## The NetBSD driver model
 =======================  
   
 ### The NetBSD kernel basics  ### The NetBSD kernel basics
   
 -   NetBSD has a classic monolithic UNIX-like kernel - all drivers are  -   NetBSD has a classic monolithic UNIX-like kernel - all drivers are
     running in the same address space      running in the same address space
   
 -   Thanks to the above, communication between drivers and other kernel  -   Thanks to the above, communication between drivers and other kernel
     layers is simple      layers is simple
   
 -   However, it also means that one badly written driver can affect the  -   However, it also means that one badly written driver can affect the
     whole kernel      whole kernel
   
 -   Numerous in-kernel frameworks standardise the way drivers are  -   Numerous in-kernel frameworks standardise the way drivers are
     written (bus\_space, autoconf, etc.)      written (bus\_space, autoconf, etc.)
   
 ### The NetBSD source directory structure  ### The NetBSD source directory structure
   
 -   We’ll only cover parts interesting for a device driver programmer  -   We’ll only cover parts interesting for a device driver programmer
   
 -   src/sys/  -   src/sys/
   
     - kernel source directory      - kernel source directory
   
 -   src/sys/dev/  -   src/sys/dev/
   
     - machine-independent device drivers      - machine-independent device drivers
   
 -   src/sys/arch/  -   src/sys/arch/
   
     - port-specific or architecture-specific parts (such as the      - port-specific or architecture-specific parts (such as the
     low-level system initialisation procedures or machine-dependent      low-level system initialisation procedures or machine-dependent
     drivers)      drivers)
   
 -   src/sys/arch/\$PORTNAME/conf/  -   src/sys/arch/\$PORTNAME/conf/
   
     - kernel configuration files for a given port      - kernel configuration files for a given port
   
 ### Kernel autoconfiguration framework - autoconf(9)  ### Kernel autoconfiguration framework - autoconf(9)
   
 -   Autoconfiguration is the process of matching hardware devices with  -   Autoconfiguration is the process of matching hardware devices with
     an appropriate device driver      an appropriate device driver
   
 -   The kernel message buffer (dmesg) contains information about  -   The kernel message buffer (dmesg) contains information about
     autoconfiguration of devices      autoconfiguration of devices
   
 -   driver0 at bus0: Foo hardware  -   driver0 at bus0: Foo hardware
   
     -   Instance 0 of the driver has attached to instance 0 of the      -   Instance 0 of the driver has attached to instance 0 of the
         particular bus          particular bus
   
     -   Such messages often carry additional bus-specific information      -   Such messages often carry additional bus-specific information
         about the exact location of the device (like the device and          about the exact location of the device (like the device and
         function number on the PCI bus)          function number on the PCI bus)
   
 -   driver0: some message  -   driver0: some message
   
     -   Additional information about the driver state or device      -   Additional information about the driver state or device
         configuration          configuration
   
Line 183  The NetBSD driver model Line 143  The NetBSD driver model
     architectures, and to allow a single driver object file to      architectures, and to allow a single driver object file to
     manipulate a set of devices on multiple bus types on a single      manipulate a set of devices on multiple bus types on a single
     architecture.”      architecture.”
   
 -   Provides a set of functions implementing common operations on the  -   Provides a set of functions implementing common operations on the
     bus like mapping, reading, writing, copying, etc.      bus like mapping, reading, writing, copying, etc.
   
 -   The bus\_space(9) is implemented at the machine-dependent level  -   The bus\_space(9) is implemented at the machine-dependent level
     (typically it’s a part of architecture-specific code), but all      (typically it’s a part of architecture-specific code), but all
     implementations present the same interface[^1]      implementations present the same interface[^1]
Line 194  The NetBSD driver model Line 152  The NetBSD driver model
 ### Machine independent drivers  ### Machine independent drivers
   
 -   If possible drivers should work on any hardware platform  -   If possible drivers should work on any hardware platform
   
 -   High quality, machine-independent (MI) drivers are an important  -   High quality, machine-independent (MI) drivers are an important
     factor that adds to NetBSD portability      factor that adds to NetBSD portability
   
 -   Some drivers are completely MI, some have MD or bus dependent  -   Some drivers are completely MI, some have MD or bus dependent
     attachments and some are completely MD      attachments and some are completely MD
   
     -   A driver for a typical PCI card will be completely MI      -   A driver for a typical PCI card will be completely MI
   
     -   A driver for the components of a SoC will usually be completely      -   A driver for the components of a SoC will usually be completely
         MD          MD
   
 -   The bus\_space abstraction helps to achieve portability,  -   The bus\_space abstraction helps to achieve portability,
     transparently handling endianness issues and hiding bus      transparently handling endianness issues and hiding bus
     implementation details from the device driver      implementation details from the device driver
   
 -   Even if we have MI drivers, writing the drivers is always  -   Even if we have MI drivers, writing the drivers is always
     significant part of effort needed to port NetBSD to new hardware      significant part of effort needed to port NetBSD to new hardware
   
 Example driver from scratch  ## Example driver from scratch
 ===========================  
   
 ### Development environment  ### Development environment
   
 -   Out of scope of this course, but very well documented  -   Out of scope of this course, but very well documented
   
 -   Cross compiling is an easy task with the build.sh script  -   Cross compiling is an easy task with the build.sh script
   
 -   Described in [Part V of the NetBSD  -   Described in [Part V of the NetBSD
     Guide](http://www.netbsd.org/docs/guide/en/part-compile.html)      Guide](http://www.netbsd.org/docs/guide/en/part-compile.html)
   
 -   Check out the NetBSD sources  -   Check out the NetBSD sources
   
 -   \$ build.sh -m cobalt tools  -   \$ build.sh -m cobalt tools
   
     will build compiler, assembler, linker, etc. for cobalt port      will build compiler, assembler, linker, etc. for cobalt port
   
 -   \$ build.sh -m cobalt kernel=GENERIC  -   \$ build.sh -m cobalt kernel=GENERIC
   
     will build the GENERIC kernel for cobalt      will build the GENERIC kernel for cobalt
   
 -   Call build.sh with a -u parameter to update (won’t rebuilding  -   Call build.sh with a -u parameter to update (won’t rebuilding
     everything)      everything)
   
 -   build.sh  -   build.sh
   
     is calling nbconfig and nbmake tools, no magic involved      is calling nbconfig and nbmake tools, no magic involved
   
 ### Quick introduction to GXemul  ### Quick introduction to GXemul
   
 -   A framework for full-system computer architecture emulation,  -   A framework for full-system computer architecture emulation,
     excellent for educational purposes      excellent for educational purposes
   
 -   Capable of emulating several real machines supported by NetBSD  -   Capable of emulating several real machines supported by NetBSD
   
 -   We’ll emulate a [Cobalt](http://en.wikipedia.org/wiki/Cobalt_Qube),  -   We’ll emulate a [Cobalt](http://en.wikipedia.org/wiki/Cobalt_Qube),
     MIPS-based micro server with PCI bus      MIPS-based micro server with PCI bus
   
 -   I’ve modified GXemul and implemented an emulation of an additional  -   I’ve modified GXemul and implemented an emulation of an additional
     PCI device      PCI device
   
 -   It will be used to show (almost) a real-life example of the driver  -   It will be used to show (almost) a real-life example of the driver
     development process      development process
   
 ### Our hardware - functional description  ### Our hardware - functional description
   
 -   Business applications often use arithmetic operations like addition  -   Business applications often use arithmetic operations like addition
   
 -   Fake Cards Inc. responded to market needs and created a new product,  -   Fake Cards Inc. responded to market needs and created a new product,
     Advanced Addition Accelerator      Advanced Addition Accelerator
   
 -   Pointy Haired Bosses will certainly buy it to accelerate their  -   Pointy Haired Bosses will certainly buy it to accelerate their
     business applications, so let’s create a driver for NetBSD!      business applications, so let’s create a driver for NetBSD!
   
 ### Our hardware - technical details  ### Our hardware - technical details
   
 -   Overview  -   Overview
   
     -   Implemented as a PCI device      -   Implemented as a PCI device
   
     -   Arithmetic unit capable of addition of two numbers      -   Arithmetic unit capable of addition of two numbers
   
     -   Four[^2] registers in the PCI memory space      -   Four[^2] registers in the PCI memory space
   
 -   PCI configuration space  -   PCI configuration space
   
     -   Identified by the PCI vendor ID 0xfabc and product ID 0x0001      -   Identified by the PCI vendor ID 0xfabc and product ID 0x0001
   
     -   Base Address Register 0x10 used to configure the engine address      -   Base Address Register 0x10 used to configure the engine address
   
     -   4 x 32-bit registers = 16 bytes      -   4 x 32-bit registers = 16 bytes
   
     -   Other configuration registers irrelevant      -   Other configuration registers irrelevant
   
 [faaop]  
   
 ### Our hardware - technical details (memory mapped register set)  ### Our hardware - technical details (memory mapped register set)
   
 -   Advanced Addition Acceleration registers  -   Advanced Addition Acceleration registers
   
    Register Name   Offset                          Description  <table>
   --------------- -------- -----------------------------------------------------------  <tr><th>Register Name</th><th>Offset</th><th>Description</th></tr>
       COMMAND       0x4           Register used to issue commands to the engine  <tr><td>COMMAND</td><td>0x4</td><td>Register used to issue commands to the engine</td></tr>
        DATA         0x8      Register used to load data to internal engine registers  <tr><td>DATA</td><td>0x8</td><td>Register used to load data to internal engine registers</td></tr>
       RESULT        0xC     Register used to store the result of arithmetic operation  <tr><td>RESULT</td><td>0xC</td><td>Register used to store the result of arithmetic operation</td></tr>
   </table>
   
 -   COMMAND register  -   COMMAND register
   
    Bit   R/W                                Description  <table>
   ----- ----- -----------------------------------------------------------------------  <tr><th>Bit</th><th>R/W</th><th>Description</th></tr>
     0     W    Execute ADD operation on values loaded into internal register A and B  <tr><td>0</td><td>W</td><td>Execute ADD operation on values loaded into internal register A and B</td></tr>
     1    R/W        Select internal register A for access through DATA register  <tr><td>1</td><td>R/W</td><td>Select internal register A for access through DATA register</td></tr>
     2    R/W        Select internal register B for access through DATA register  <tr><td>2</td><td>R/W</td><td>Select internal register B for access through DATA register</td></tr>
   </table>
   
 -   Selecting internal register A and B at the same time will lead to  -   Selecting internal register A and B at the same time will lead to
     undefined behaviour      undefined behaviour
Line 315  Example driver from scratch Line 242  Example driver from scratch
   
 -   DATA register  -   DATA register
   
    Bit    R/W                     Description  <table>
   ------ ----- --------------------------------------------------  <tr><th>Bit</th><th>R/W</th><th>Description</th></tr>
    0:31   R/W   Read/write the value in internal engine register  <tr><td>0:31</td><td>R/W</td><td>Read/write the value in internal engine register</td></tr>
   </table>
   
 -   RESULT register  -   RESULT register
   
    Bit    R/W                Description  <table>
   ------ ----- ----------------------------------------  <tr><th>Bit</th><th>R/W</th><th>Description</th></tr>
    0:31    R    Holds the result of last ADD operation  <tr><td>0:31</td><td>R</td><td>Holds the result of last ADD operation</td></tr>
   </table>
   
 ### Our hardware - technical details (operation algorithm)  ### Our hardware - technical details (operation algorithm)
   
 -   Select the internal register A for access (write 0x2 into COMMAND  -   Select the internal register A for access (write 0x2 into COMMAND
     register)      register)
   
 -   Write the first number into DATA register  -   Write the first number into DATA register
   
 -   Select the internal register B for access (write 0x4 into COMMAND  -   Select the internal register B for access (write 0x4 into COMMAND
     register)      register)
   
 -   Write the second number into DATA register  -   Write the second number into DATA register
   
 -   Issue the ADD operation (write 0x1 into COMMAND register)  -   Issue the ADD operation (write 0x1 into COMMAND register)
   
 -   Read the result from RESULT register  -   Read the result from RESULT register
   
 ### Adding a new driver to the NetBSD kernel  ### Adding a new driver to the NetBSD kernel
   
 -   We’ll discuss the steps needed to add a new MI PCI device driver to  -   We’ll discuss the steps needed to add a new MI PCI device driver to
     the NetBSD kernel      the NetBSD kernel
   
     -   Add the vendor and device ID to the database of PCI IDs      -   Add the vendor and device ID to the database of PCI IDs
   
     -   Create a set of the driver source files in      -   Create a set of the driver source files in
         src/sys/dev/\$BUSNAME/          src/sys/dev/\$BUSNAME/
   
     -   Add the new driver to src/sys/dev/\$BUSNAME/\$BUSNAME.files file      -   Add the new driver to src/sys/dev/\$BUSNAME/\$BUSNAME.files file
   
     -   Add the new driver to DEVNAMES[^3] file      -   Add the new driver to DEVNAMES[^3] file
   
 ### Modifying the PCI device database  ### Modifying the PCI device database
Line 362  Example driver from scratch Line 282  Example driver from scratch
     not configured      not configured
   
 -   The kernel does not know anything about this vendor and device  -   The kernel does not know anything about this vendor and device
   
 -   Add it to the PCI device database - src/sys/dev/pci/pcidevs  -   Add it to the PCI device database - src/sys/dev/pci/pcidevs
   
 -   vendor VENDORNAME 0xVENDORID Long Vendor Name  -   vendor VENDORNAME 0xVENDORID Long Vendor Name
   
 -   product VENDORNAME PRODUCTNAME 0xPRODUCTID Long Product Name  -   product VENDORNAME PRODUCTNAME 0xPRODUCTID Long Product Name
   
 -   To regenerate pcidevs\*.h run awk -f devlist2h.awk pcidevs or  -   To regenerate pcidevs\*.h run awk -f devlist2h.awk pcidevs or
     Makefile.pcidevs if you’re on NetBSD      Makefile.pcidevs if you’re on NetBSD
   
Line 402  Example driver from scratch Line 318  Example driver from scratch
     not configured      not configured
   
 -   Now the kernel knows the vendor and product ID  -   Now the kernel knows the vendor and product ID
   
 -   But there’s still no driver for this device  -   But there’s still no driver for this device
   
 ### Adding the new PCI driver  ### Adding the new PCI driver
   
 -   Choose a name - short, easy to remember, avoid numbers  -   Choose a name - short, easy to remember, avoid numbers
   
     -   faa      -   faa
   
         looks like a good name, but you can choose any name you like          looks like a good name, but you can choose any name you like
   
 -   Create a set of new files in src/sys/dev/pci  -   Create a set of new files in src/sys/dev/pci
   
     -   faa.c      -   faa.c
   
         - main driver code          - main driver code
   
     -   faareg.h      -   faareg.h
   
         - register definitions[^4]          - register definitions[^4]
   
     -   faavar.h      -   faavar.h
   
         - driver structures and functions used in other parts of the          - driver structures and functions used in other parts of the
         kernel[^5]          kernel[^5]
   
 -   Modify driver definitions  -   Modify driver definitions
   
     -   src/sys/dev/pci/files.pci      -   src/sys/dev/pci/files.pci
   
     -   src/sys/dev/DEVNAMES      -   src/sys/dev/DEVNAMES
   
 -   Configure the kernel to use the newly added driver -  -   Configure the kernel to use the newly added driver -
     src/sys/arch/\$PORTNAME/conf/GENERIC      src/sys/arch/\$PORTNAME/conf/GENERIC
   
Line 441  Example driver from scratch Line 343  Example driver from scratch
   
 -   Kernel includes are at the beginning, followed by machine-specific  -   Kernel includes are at the beginning, followed by machine-specific
     and bus-specific includes      and bus-specific includes
   
 -   Should also include faareg.h and faavar.h files  -   Should also include faareg.h and faavar.h files
   
 -   A minimal driver needs just two functions  -   A minimal driver needs just two functions
   
     -   faa\_match      -   faa\_match
   
         (or faa\_probe for some buses)          (or faa\_probe for some buses)
   
     -   faa\_attach      -   faa\_attach
   
 -   The CFATTACH\_DECL\_NEW macro plugs the above functions into  -   The CFATTACH\_DECL\_NEW macro plugs the above functions into
     autoconf(9) mechanism      autoconf(9) mechanism
   
Line 459  Example driver from scratch Line 355  Example driver from scratch
   
 -   static int faa\_match(device\_t parent, cfdata\_t match, void  -   static int faa\_match(device\_t parent, cfdata\_t match, void
     \*aux);      \*aux);
   
     -   Check if the driver should attach to a given device (for example      -   Check if the driver should attach to a given device (for example
         in case of PCI bus, it will be used to check vendor and product          in case of PCI bus, it will be used to check vendor and product
         ID)          ID)
   
     -   parent      -   parent
   
         - pointer to parent’s driver device structure          - pointer to parent’s driver device structure
   
     -   match      -   match
   
         - pointer to autoconf(9) details structure          - pointer to autoconf(9) details structure
   
     -   aux      -   aux
   
         - despite the name the most important argument, usually contains          - despite the name the most important argument, usually contains
         bus-specific structure describing device details          bus-specific structure describing device details
   
 -   static void faa\_attach(device\_t parent, device\_t self, void  -   static void faa\_attach(device\_t parent, device\_t self, void
     \*aux);      \*aux);
   
     -   Attach the driver to a given device      -   Attach the driver to a given device
   
     -   parent      -   parent
   
         - same as with match function          - same as with match function
   
     -   self      -   self
   
         - pointer to driver’s device structure          - pointer to driver’s device structure
   
     -   aux      -   aux
   
         - same as with match function          - same as with match function
   
 -   See definitions of these functions in the  -   See definitions of these functions in the
     [driver(9)](http://netbsd.gw.com/cgi-bin/man-cgi?driver+9+NetBSD-current)      [driver(9)](http://netbsd.gw.com/cgi-bin/man-cgi?driver+9+NetBSD-current)
     man page.      man page.
Line 502  Example driver from scratch Line 383  Example driver from scratch
   
 -   CFATTACH\_DECL\_NEW(faa, sizeof(struct faa\_softc), faa\_match,  -   CFATTACH\_DECL\_NEW(faa, sizeof(struct faa\_softc), faa\_match,
     faa\_attach, NULL, NULL);      faa\_attach, NULL, NULL);
   
     -   driver name      -   driver name
   
     -   size of softc structure containing state of driver’s instance      -   size of softc structure containing state of driver’s instance
   
     -   match/probe function      -   match/probe function
   
     -   attach function      -   attach function
   
     -   detach function      -   detach function
   
     -   activate function      -   activate function
   
 -   The “\_NEW” name is unfortunate  -   The “\_NEW” name is unfortunate
   
 -   Pass NULL for unimplemented functions  -   Pass NULL for unimplemented functions
   
 -   We won’t cover detach and activate now, as they are not needed for a  -   We won’t cover detach and activate now, as they are not needed for a
     simple driver      simple driver
   
Line 529  Example driver from scratch Line 401  Example driver from scratch
 <!-- -->  <!-- -->
   
     #include <sys/cdefs.h>      #include <sys/cdefs.h>
     __KERNEL_RCSID(0, "$NetBSD: bus_space_tutorial.mdwn,v 1.2 2013/06/23 14:10:19 mspo Exp $");      __KERNEL_RCSID(0, "$NetBSD: bus_space_tutorial.mdwn,v 1.3 2013/06/23 14:16:27 mspo Exp $");
     #include <sys/param.h>      #include <sys/param.h>
     #include <sys/device.h>      #include <sys/device.h>
     #include <dev/pci/pcivar.h>      #include <dev/pci/pcivar.h>
Line 602  Example driver from scratch Line 474  Example driver from scratch
 ### Adding the new PCI driver - registering the driver  ### Adding the new PCI driver - registering the driver
   
 -   See config(5)  -   See config(5)
   
 -   src/sys/dev/pci/files.pci  -   src/sys/dev/pci/files.pci
   
 <!-- -->  <!-- -->
Line 640  Example driver from scratch Line 511  Example driver from scratch
   
 -   The above definition means that an instance of faa may be attached  -   The above definition means that an instance of faa may be attached
     to any PCI bus, any device, any function      to any PCI bus, any device, any function
   
 -   The exact position of the rule in the configuration file is not  -   The exact position of the rule in the configuration file is not
     important in this case      important in this case
   
 -   See  -   See
     [config(5)](http://netbsd.gw.com/cgi-bin/man-cgi?config+5+NetBSD-current)      [config(5)](http://netbsd.gw.com/cgi-bin/man-cgi?config+5+NetBSD-current)
     for a description of the device definition language      for a description of the device definition language
Line 651  Example driver from scratch Line 520  Example driver from scratch
 ### Adding the new PCI driver - example  ### Adding the new PCI driver - example
   
 -   The driver should compile now  -   The driver should compile now
   
 -   The driver’s match function will check if the driver is able to work  -   The driver’s match function will check if the driver is able to work
     with a given device      with a given device
   
 -   Since it is not implemented, the kernel will not attach the driver  -   Since it is not implemented, the kernel will not attach the driver
   
 ### Matching the PCI device  ### Matching the PCI device
   
 -   Modify the faa\_match function to match the specified PCI device  -   Modify the faa\_match function to match the specified PCI device
   
 -   Use PCI\_VENDOR and PCI\_PRODUCT macros to obtain the IDs  -   Use PCI\_VENDOR and PCI\_PRODUCT macros to obtain the IDs
   
 <!-- -->  <!-- -->
Line 683  Example driver from scratch Line 549  Example driver from scratch
   
 -   The driver has successfully matched and attached to the PCI device  -   The driver has successfully matched and attached to the PCI device
     but still is not doing anything useful      but still is not doing anything useful
   
 -   Let’s fill the attach function and actually program the hardware  -   Let’s fill the attach function and actually program the hardware
   
 ### Variable types used with bus\_space  ### Variable types used with bus\_space
Line 713  Example driver from scratch Line 578  Example driver from scratch
   
 -   “The bus space must be mapped before it can be used, and should be  -   “The bus space must be mapped before it can be used, and should be
     unmapped when it is no longer needed”      unmapped when it is no longer needed”
   
 -   It’s a machine-dependent process but it’s also conveniently hidden  -   It’s a machine-dependent process but it’s also conveniently hidden
     from the programmer by the bus\_space framework      from the programmer by the bus\_space framework
   
Line 1040  Example driver from scratch Line 904  Example driver from scratch
   
 -   Now that the core functionality of the kernel driver is working, it  -   Now that the core functionality of the kernel driver is working, it
     should be exposed to user space      should be exposed to user space
   
 -   The interface between kernel driver and userspace can be designed in  -   The interface between kernel driver and userspace can be designed in
     many different ways      many different ways
   
 -   The classic UNIX way of interfacing between the kernel and user  -   The classic UNIX way of interfacing between the kernel and user
     space is a device file      space is a device file
   
 -   Even when using device files there is no single interfacing method  -   Even when using device files there is no single interfacing method
     that fits all use cases      that fits all use cases
   
 -   It’s up to the programmer to define the communication protocol  -   It’s up to the programmer to define the communication protocol
   
 ### Device files  ### Device files
   
 -   crw-r—– 1 root wheel 101, 1 Aug 12 21:53 /dev/file  -   crw-r—– 1 root wheel 101, 1 Aug 12 21:53 /dev/file
   
 -   The kernel identifies which driver should service the request to  -   The kernel identifies which driver should service the request to
     this file by using major and minor numbers (101 and 1 in the example      this file by using major and minor numbers (101 and 1 in the example
     above)      above)
   
 -   The major number identifies the driver  -   The major number identifies the driver
   
 -   The minor number usually identifies the driver instance, although  -   The minor number usually identifies the driver instance, although
     the driver is free to use it in any other way      the driver is free to use it in any other way
   
 -   In NetBSD device files are created statically  -   In NetBSD device files are created statically
   
     -   By the MAKEDEV script during installation or boot      -   By the MAKEDEV script during installation or boot
   
     -   Manually by using the mknod utility      -   Manually by using the mknod utility
   
 ### Operations on device files  ### Operations on device files
Line 1076  Example driver from scratch Line 930  Example driver from scratch
 -   [open(2)](http://netbsd.gw.com/cgi-bin/man-cgi?read++NetBSD-current)  -   [open(2)](http://netbsd.gw.com/cgi-bin/man-cgi?read++NetBSD-current)
     and      and
     [close(2)](http://netbsd.gw.com/cgi-bin/man-cgi?read++NetBSD-current)      [close(2)](http://netbsd.gw.com/cgi-bin/man-cgi?read++NetBSD-current)
   
 -   [read(2)](http://netbsd.gw.com/cgi-bin/man-cgi?read++NetBSD-current)  -   [read(2)](http://netbsd.gw.com/cgi-bin/man-cgi?read++NetBSD-current)
     and      and
     [write(2)](http://netbsd.gw.com/cgi-bin/man-cgi?write++NetBSD-current)      [write(2)](http://netbsd.gw.com/cgi-bin/man-cgi?write++NetBSD-current)
   
 -   [ioctl(2)](http://netbsd.gw.com/cgi-bin/man-cgi?write++NetBSD-current)  -   [ioctl(2)](http://netbsd.gw.com/cgi-bin/man-cgi?write++NetBSD-current)
   
 -   [poll(2)](http://netbsd.gw.com/cgi-bin/man-cgi?poll++NetBSD-current)  -   [poll(2)](http://netbsd.gw.com/cgi-bin/man-cgi?poll++NetBSD-current)
   
 -   [mmap(2)](http://netbsd.gw.com/cgi-bin/man-cgi?write++NetBSD-current)  -   [mmap(2)](http://netbsd.gw.com/cgi-bin/man-cgi?write++NetBSD-current)
   
 -   and more…  -   and more…
   
 -   Any mix of the above system calls might be used to interface between  -   Any mix of the above system calls might be used to interface between
     the kernel and user space      the kernel and user space
   
 -   We’ll implement an ioctl(2)-based communication mechanism  -   We’ll implement an ioctl(2)-based communication mechanism
   
 ### Adding cdevsw  ### Adding cdevsw
Line 1124  Example driver from scratch Line 971  Example driver from scratch
   
 -   The dev\_type\* macros are used to prototype the functions passed to  -   The dev\_type\* macros are used to prototype the functions passed to
     cdevsw      cdevsw
   
 -   Pass no followed by a function name to the appropriate cdevsw field  -   Pass no followed by a function name to the appropriate cdevsw field
     if it is not implemented      if it is not implemented
   
 -   There’s also bdevsw for block devices, but we won’t use it in this  -   There’s also bdevsw for block devices, but we won’t use it in this
     example      example
   
 -   The last member of the cdevsw structure defines the device flags,  -   The last member of the cdevsw structure defines the device flags,
     originally it was used to define the device type (still used for      originally it was used to define the device type (still used for
     disks, tape drives and ttys, for other devices pass D\_OTHER)      disks, tape drives and ttys, for other devices pass D\_OTHER)
Line 1176  Example driver from scratch Line 1020  Example driver from scratch
   
 -   The classic way of passing data is by using structures, their  -   The classic way of passing data is by using structures, their
     definitions are shared between the kernel and user space code      definitions are shared between the kernel and user space code
   
 -   The driver might support more than one ioctl, the \_IO\* macros are  -   The driver might support more than one ioctl, the \_IO\* macros are
     used to define the operation and associated structure used to      used to define the operation and associated structure used to
     exchange data      exchange data
Line 1260  Example driver from scratch Line 1103  Example driver from scratch
   
 -   The copy(9) functions are used to copy kernel space data from/to  -   The copy(9) functions are used to copy kernel space data from/to
     user space      user space
   
 -   copyout(kernel\_address, user space\_address, size);  -   copyout(kernel\_address, user space\_address, size);
   
 -   Actually on Cobalt we could just do data-\>result = faa\_add();  -   Actually on Cobalt we could just do data-\>result = faa\_add();
     instead of calling the copyout function, but that is a bad idea      instead of calling the copyout function, but that is a bad idea
   
 -   Some architectures (such as sparc64) have totally separate kernel  -   Some architectures (such as sparc64) have totally separate kernel
     and user address spaces $ \implies $ user space addresses are      and user address spaces $ \implies $ user space addresses are
     meaningless in the kernel      meaningless in the kernel
Line 1274  Example driver from scratch Line 1114  Example driver from scratch
   
 -   Device major numbers for hardware drivers are usually defined in a  -   Device major numbers for hardware drivers are usually defined in a
     per-port manner[^7]      per-port manner[^7]
   
 -   src/sys/arch/\$PORTNAME/conf/majors.\$PORTNAME  -   src/sys/arch/\$PORTNAME/conf/majors.\$PORTNAME
   
 -   src/sys/arch/cobalt/conf/majors.cobalt  -   src/sys/arch/cobalt/conf/majors.cobalt
   
 -   The following defines a new character device file called /dev/faa\*  -   The following defines a new character device file called /dev/faa\*
     with major number 101, but only if the faa driver is included in the      with major number 101, but only if the faa driver is included in the
     kernel (last argument)      kernel (last argument)
   
 -   device-major faa char 101 faa  -   device-major faa char 101 faa
   
 ### Creating the device node  ### Creating the device node
   
 -   The mknod utility can be used to create the device file manually  -   The mknod utility can be used to create the device file manually
   
 -   The driver name can be specified instead of the major number - it  -   The driver name can be specified instead of the major number - it
     will be automatically resolved into the correct major number      will be automatically resolved into the correct major number
   
 -   mknod name [b | c] [major | driver] minor  -   mknod name [b | c] [major | driver] minor
   
 -   mknod /dev/faa0 c faa 0  -   mknod /dev/faa0 c faa 0
   
 -   Created successfully  -   Created successfully
   
 -   crw-r–r– 1 root wheel 101, 0 Oct 8 2012 /dev/faa0  -   crw-r–r– 1 root wheel 101, 0 Oct 8 2012 /dev/faa0
   
 ### An example user space program  ### An example user space program
   
 -   The example program will open the device file and call ioctl(2) on  -   The example program will open the device file and call ioctl(2) on
     it      it
   
 -   As simple as possible, just to show how communication is done  -   As simple as possible, just to show how communication is done
   
 -   Using ioctls from the user space  -   Using ioctls from the user space
   
     -   Open the device file with O\_RDWR      -   Open the device file with O\_RDWR
   
     -   Call ioctl(2) with the operation number and structure as      -   Call ioctl(2) with the operation number and structure as
         parameters          parameters
   
Line 1368  Example driver from scratch Line 1195  Example driver from scratch
   
 -   The program is successfully accessing the faa driver through the  -   The program is successfully accessing the faa driver through the
     ioctl      ioctl
   
 -   The faa0:... line is a kernel message, normally only seen on the  -   The faa0:... line is a kernel message, normally only seen on the
     console terminal      console terminal
   
Line 1377  Example driver from scratch Line 1203  Example driver from scratch
 ### Avoiding common pitfalls  ### Avoiding common pitfalls
   
 -   Always free resources allocated in the match or probe functions  -   Always free resources allocated in the match or probe functions
   
 -   Always use bus\_space methods, don’t access the hardware using a  -   Always use bus\_space methods, don’t access the hardware using a
     pointer dereference      pointer dereference
   
 -   If possible test on more than one hardware architecture, some bugs  -   If possible test on more than one hardware architecture, some bugs
     may surface      may surface
   
 -   Don’t reinvent the wheel, try to use existing kernel frameworks as  -   Don’t reinvent the wheel, try to use existing kernel frameworks as
     much as possible      much as possible
   
 -   Use copy(9) (or uiomove(9) or store(9)/fetch(9)) to move data  -   Use copy(9) (or uiomove(9) or store(9)/fetch(9)) to move data
     between the kernel and user space      between the kernel and user space
   
Line 1394  Example driver from scratch Line 1216  Example driver from scratch
   
 -   Use aprint\_debug to print debug-level messages on console and log  -   Use aprint\_debug to print debug-level messages on console and log
     them (enabled by passing AB\_DEBUG from the boot loader)      them (enabled by passing AB\_DEBUG from the boot loader)
   
 -   Use the built-in DDB debugger  -   Use the built-in DDB debugger
   
     -   Enabled by the kernel option DDB      -   Enabled by the kernel option DDB
   
     -   A kernel panic will start DDB if the DDB\_ONPANIC=1 kernel      -   A kernel panic will start DDB if the DDB\_ONPANIC=1 kernel
         option is specified or the ddb.onpanic sysctl is set to 1.          option is specified or the ddb.onpanic sysctl is set to 1.
   
     -   Run \# sysctl -w kern.panic\_now=1 to trigger a panic manually      -   Run \# sysctl -w kern.panic\_now=1 to trigger a panic manually
         (DIAGNOSTIC option)          (DIAGNOSTIC option)
   
 -   Remote debugging is possible on some ports  -   Remote debugging is possible on some ports
   
     -   With KGDB through the serial port      -   With KGDB through the serial port
   
     -   With IPKDB through the network      -   With IPKDB through the network
   
 ## Summary  ## Summary
Line 1416  Example driver from scratch Line 1231  Example driver from scratch
 ### Further reading  ### Further reading
   
 -   Documentation, articles:  -   Documentation, articles:
   
     -   [A Machine-Independent DMA Framework for NetBSD, Jason R.      -   [A Machine-Independent DMA Framework for NetBSD, Jason R.
         Thorpe](http://www.netbsd.org/docs/kernel/bus_dma.pdf)          Thorpe](http://www.netbsd.org/docs/kernel/bus_dma.pdf)
   
     -   [Writing Drivers for NetBSD, Jochen      -   [Writing Drivers for NetBSD, Jochen
         Kunz](ftp://ftp.netbsd.org/pub/NetBSD/misc/ddwg/NetBSD-driver_writing-1.0.1e.pdf)          Kunz](ftp://ftp.netbsd.org/pub/NetBSD/misc/ddwg/NetBSD-driver_writing-1.0.1e.pdf)
   
     -   [NetBSD Documentation: Writing a pseudo      -   [NetBSD Documentation: Writing a pseudo
         device](http://www.netbsd.org/docs/kernel/pseudo/)          device](http://www.netbsd.org/docs/kernel/pseudo/)
   
     -   [autoconf(9)](http://netbsd.gw.com/cgi-bin/man-cgi?autoconf+9+NetBSD-current),      -   [autoconf(9)](http://netbsd.gw.com/cgi-bin/man-cgi?autoconf+9+NetBSD-current),
         [bus\_space(9)](http://netbsd.gw.com/cgi-bin/man-cgi?bus_space+9+NetBSD-current)          [bus\_space(9)](http://netbsd.gw.com/cgi-bin/man-cgi?bus_space+9+NetBSD-current)
         [bus\_dma(9)](http://netbsd.gw.com/cgi-bin/man-cgi?bus_dma+9+NetBSD-current)          [bus\_dma(9)](http://netbsd.gw.com/cgi-bin/man-cgi?bus_dma+9+NetBSD-current)
Line 1434  Example driver from scratch Line 1245  Example driver from scratch
         man pages, etc.          man pages, etc.
   
 -   Example source code of drivers:  -   Example source code of drivers:
   
     -   tdvfb      -   tdvfb
   
         , voodoofb are fairly good frame buffer driver examples with          voodoofb are fairly good frame buffer driver examples with
         documentation publicly available.          documentation publicly available.
   
     -   etsec      -   etsec
Line 1447  Example driver from scratch Line 1257  Example driver from scratch
 ### Get the source code  ### Get the source code
   
 -   Download the source code and materials for this tutorial  -   Download the source code and materials for this tutorial
   
 -   <https://github.com/rkujawa/busspace-tutorial>  -   <https://github.com/rkujawa/busspace-tutorial>
   
 -   <https://github.com/rkujawa/gxemul-tutorial>  -   <https://github.com/rkujawa/gxemul-tutorial>
   
 ### Questions?  ### Questions?

Removed from v.1.3  
changed lines
  Added in v.1.4


CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb