Diff for /wikisrc/tutorials/bus_space_tutorial.mdwn between versions 1.12 and 1.13

version 1.12, 2013/06/29 12:41:13 version 1.13, 2016/03/17 11:38:49
Line 6 Line 6
   
 -   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?
   
 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
Line 46  this knowledge yourself. Line 46  this knowledge yourself.
   
 ### 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
Line 73  this knowledge yourself. Line 73  this knowledge yourself.
   
 ### 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/
Line 134  this knowledge yourself. Line 134  this knowledge yourself.
   
 ### The bus\_space(9) framework  ### The bus\_space(9) framework
   
 -   “The goal of the bus\_space functions is to allow a single driver  -   "The goal of the bus\_space functions is to allow a single driver
     source file to manipulate a set of devices on different system      source file to manipulate a set of devices on different system
     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      implementations present the same interface
 > At least they should, some functions are missing on less popular ports  > At least they should, some functions are missing on less popular ports
   
Line 175  this knowledge yourself. Line 175  this knowledge yourself.
     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
Line 185  this knowledge yourself. Line 185  this knowledge yourself.
 -   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
Line 198  this knowledge yourself. Line 198  this knowledge yourself.
 -   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
   
Line 265  Bit |R/W |Description Line 265  Bit |R/W |Description
   
 ### 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
Line 285  Bit |R/W |Description Line 285  Bit |R/W |Description
 -   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
   
 ### Modifying the PCI device database - example  ### Modifying the PCI device database - example
   
Line 317  Bit |R/W |Description Line 317  Bit |R/W |Description
     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
   
Line 359  Bit |R/W |Description Line 359  Bit |R/W |Description
         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
Line 372  Bit |R/W |Description Line 372  Bit |R/W |Description
     -   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.
   
 ### Adding the new PCI driver - main driver cont’d  ### Adding the new PCI driver - main driver cont'd
   
 -   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
   
 ### Adding the new PCI driver - main driver example  ### Adding the new PCI driver - main driver example
Line 401  Bit |R/W |Description Line 401  Bit |R/W |Description
 <!-- -->  <!-- -->
   
     #include <sys/cdefs.h>      #include <sys/cdefs.h>
     __KERNEL_RCSID(0, "$NetBSD: bus_space_tutorial.mdwn,v 1.11 2013/06/29 12:38:29 ryoon Exp $");      __KERNEL_RCSID(0, "$NetBSD: bus_space_tutorial.mdwn,v 1.12 2013/06/29 12:41:13 ryoon 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 520  Bit |R/W |Description Line 520  Bit |R/W |Description
 ### 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
   
Line 549  Bit |R/W |Description Line 549  Bit |R/W |Description
   
 -   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
   
 -   bus\_space\_tag\_t  -   bus\_space\_tag\_t
   
     – type used to describe a particular bus, usually passed to the      - type used to describe a particular bus, usually passed to the
        driver from MI bus structures         driver from MI bus structures
   
 -   bus\_space\_handle\_t  -   bus\_space\_handle\_t
   
     – used to describe a mapped range of bus space, usually created with      - used to describe a mapped range of bus space, usually created with
        the bus\_space\_map() function         the bus\_space\_map() function
   
 -   bus\_addr\_t  -   bus\_addr\_t
   
     – address on the bus      - address on the bus
   
 -   bus\_size\_t  -   bus\_size\_t
   
     – an amount of space on the bus      - an amount of space on the bus
   
 -   Contents of these types are MD, so avoid modifying from within the  -   Contents of these types are MD, so avoid modifying from within the
     driver      driver
 > although you’ll often have to use bus\_size\_t  > although you'll often have to use bus\_size\_t
   
 ### Why do we need to “map” the resources?  ### Why do we need to "map" the resources?
   
 -   “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
   
 ### Mapping the hardware resources  ### Mapping the hardware resources
Line 593  Bit |R/W |Description Line 593  Bit |R/W |Description
   
 -   bus\_space\_map  -   bus\_space\_map
   
     – creates a mapping from the physical address to a kernel virtual      - creates a mapping from the physical address to a kernel virtual
     address      address
   
 -   space  -   space
   
     – represents the bus on which the mapping will be created      - represents the bus on which the mapping will be created
   
 -   address  -   address
   
     – typically represents the physical address for which a mapping will      - typically represents the physical address for which a mapping will
        be created         be created
   
 -   size  -   size
   
     – describes the amount of bus space to be mapped      - describes the amount of bus space to be mapped
   
 -   handlep  -   handlep
   
     – pointer to mapped space (filled after successful mapping)      - pointer to mapped space (filled after successful mapping)
   
 -   Separate space and address  -   Separate space and address
   
Line 627  Bit |R/W |Description Line 627  Bit |R/W |Description
   
 -   pci\_mapreg\_map  -   pci\_mapreg\_map
   
     – creates mapping from physical address present in specified BAR      - creates mapping from physical address present in specified BAR
     register to kernel virtual address      register to kernel virtual address
   
 -   pa  -   pa
   
     – struct describing PCI attachment details (passed through aux)      - struct describing PCI attachment details (passed through aux)
   
 -   reg  -   reg
   
     – BAR register number      - BAR register number
   
 -   type  -   type
   
     – Select mapping type (I/O, memory)      - Select mapping type (I/O, memory)
   
 -   busflags  -   busflags
   
     – Passed to bbus_space_map flags argument      - Passed to bbus_space_map flags argument
   
 -   tagp  -   tagp
   
     – pointer to bus_space_tag      - pointer to bus_space_tag
   
 -   handlep  -   handlep
   
     – pointer to a mapped space      - pointer to a mapped space
   
 -   basep  -   basep
   
     – address of a mapped space      - address of a mapped space
   
 -   sizep  -   sizep
   
     – size of mapped space (equivalent to BAR size)      - size of mapped space (equivalent to BAR size)
   
 -   The last four parameters are filled after successful mapping  -   The last four parameters are filled after successful mapping
   
Line 912  Data |Read function  |Write function Line 912  Data |Read function  |Write function
     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)
Line 938  Data |Read function  |Write function Line 938  Data |Read function  |Write function
 -   [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 975  Data |Read function  |Write function Line 975  Data |Read function  |Write function
     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
Line 1116  Data |Read function  |Write function Line 1116  Data |Read function  |Write function
   
 -   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      per-port manner
 > It’s also possible to define a major in a machine-independent way in src/sys/conf/majors  > It's also possible to define a major in a machine-independent way in src/sys/conf/majors
 -   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\*
Line 1132  Data |Read function  |Write function Line 1132  Data |Read function  |Write function
 -   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
   
Line 1206  Data |Read function  |Write function Line 1206  Data |Read function  |Write function
 ### 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 1262  Data |Read function  |Write function Line 1262  Data |Read function  |Write function
 -   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>
   
   
   
   
   
   
   

Removed from v.1.12  
changed lines
  Added in v.1.13


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