Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 28 May 1996 17:37:25 GMT
From:      James Raynard <fdocs@jraynard.demon.co.uk>
To:        jfieber@indiana.edu
Cc:        doc@freebsd.org
Subject:   Re: tutorial device witers guide
Message-ID:  <199605281737.RAA09291@jraynard.demon.co.uk>
In-Reply-To:  <Pine.NEB.3.93.960527100909.3237C-100000@Fieber-John.campusview.indiana.edu> (message from John Fieber on Mon, 27 May 1996 10:12:13 -0500 (EST))

next in thread | previous in thread | raw e-mail | index | archive | help

>   http://www.freebsd.org/tutorials/ddwg/ddwg.sgml

Here's a diff which corrects a number of typos in this document, as
well as inserting a few "pauses for breath" where appropriate.

One thing I left out, as it's really a matter of style, but shouldn't
acronyms, such as ide and scsi, be capitalised?

*** ddwg.sgml.orig	Tue May 28 16:34:58 1996
--- ddwg.sgml		Tue May 28 17:18:55 1996
***************
*** 113,119 ****
  
  <sect3> XXioctl()
  <p>
! It's argument list is as follows:
  <code>
  int
  XXioctl(dev_t dev, int cmd, caddr_t arg, int flag, struct proc *p)
--- 113,119 ----
  
  <sect3> XXioctl()
  <p>
! Its argument list is as follows:
  <code>
  int
  XXioctl(dev_t dev, int cmd, caddr_t arg, int flag, struct proc *p)
***************
*** 136,148 ****
  <tt/_IOWR(g,n,t)/ for operations that write to a device, and then
  read data back. &nl;
  
! Here <tt/g/ refers to a <em/group/ this is an 8-bit value, typically
! indicitive of the device, for example 't' is used in tty ioctls.
  <tt/n/ refers to the number of the ioctl within the group.  On SCO, this
  number alone denotes the ioctl.  <tt/t/ is the data type which will
  get passed to the driver; this gets handed to a sizeof() operator in
  the kernel.  The ioctl() system call will either copyin() or copyout()
! or both for your driver then hand you a pointer to the data structure
  in the <tt/arg/ argument of the XXioctl call.  Currently the data size
  is limited to one page (4k on the i386).
  
--- 136,148 ----
  <tt/_IOWR(g,n,t)/ for operations that write to a device, and then
  read data back. &nl;
  
! Here <tt/g/ refers to a <em/group/. This is an 8-bit value, typically
! indicative of the device; for example, 't' is used in tty ioctls.
  <tt/n/ refers to the number of the ioctl within the group.  On SCO, this
  number alone denotes the ioctl.  <tt/t/ is the data type which will
  get passed to the driver; this gets handed to a sizeof() operator in
  the kernel.  The ioctl() system call will either copyin() or copyout()
! or both for your driver, then hand you a pointer to the data structure
  in the <tt/arg/ argument of the XXioctl call.  Currently the data size
  is limited to one page (4k on the i386).
  
***************
*** 163,169 ****
  io.  It is most common in a block device.  This is significantly different
  than the System V model, where only the block driver performs scatter-gather
  io. Under BSD, character devices are sometimes requested to perform
! scater-gather io via the readv() and writev() system calls.
  
  <sect2> Header Files
  
--- 163,169 ----
  io.  It is most common in a block device.  This is significantly different
  than the System V model, where only the block driver performs scatter-gather
  io. Under BSD, character devices are sometimes requested to perform
! scatter-gather io via the readv() and writev() system calls.
  
  <sect2> Header Files
  
***************
*** 279,289 ****
  </code>
  
  This is the structure used by the probe/attach code to detect and
! initialize your device.  The <tt/.probe/ member is a pointer to your
! device probe function; the <tt/.attach/ member is a pointer to your
  attach function.  The <tt/name/ member is a character pointer to the
  two or three letter name for your driver.  This is the name reported
! durint the probe/attach process (and probably also in lsdev(8)).  The
  <tt/sensitive_hw/ member is a flag which helps the probe code
  determine probing order.
  
--- 279,289 ----
  </code>
  
  This is the structure used by the probe/attach code to detect and
! initialize your device.  The <tt/probe/ member is a pointer to your
! device probe function; the <tt/attach/ member is a pointer to your
  attach function.  The <tt/name/ member is a character pointer to the
  two or three letter name for your driver.  This is the name reported
! during the probe/attach process (and probably also in lsdev(8)).  The
  <tt/sensitive_hw/ member is a flag which helps the probe code
  determine probing order.
  
***************
*** 297,307 ****
  <sect3> XXprobe()
  <p>
  XXprobe() takes a <tt/struct isa_device/ pointer as an argument and returns
! an int.  The return value is ``zero'' or ``non-zero'' as to the absense
  or presence of your device.  This entry point may (and probably should)
  be declared as <tt/static/ because it is accessed via the <tt/probe/ member
  of the <tt/struct isa_driver/ structure.  This function is intended
! to only detect the presence of your device it should not do any
  configuration of the device itself.
  
  <sect3> XXattach()
--- 297,307 ----
  <sect3> XXprobe()
  <p>
  XXprobe() takes a <tt/struct isa_device/ pointer as an argument and returns
! an int.  The return value is ``zero'' or ``non-zero'' as to the absence
  or presence of your device.  This entry point may (and probably should)
  be declared as <tt/static/ because it is accessed via the <tt/probe/ member
  of the <tt/struct isa_driver/ structure.  This function is intended
! to detect the presence of your device only; it should not do any
  configuration of the device itself.
  
  <sect3> XXattach()
***************
*** 333,339 ****
  
  <sect2> Header Files
  
! <sect1> PCI -- Peripheral Computer Interconect
  <sect2> Data Structures
  
  <p> <tt/struct pci_device/ Structure
--- 333,339 ----
  
  <sect2> Header Files
  
! <sect1> PCI -- Peripheral Computer Interconnect
  <sect2> Data Structures
  
  <p> <tt/struct pci_device/ Structure
***************
*** 343,349 ****
        probe:  Checks if the driver can support a device
                with this type. The tag may be used to get
                more info with pci_read_conf(). See below.
!               It returns a string with the devices name,
                or a NULL pointer, if the driver cannot
                support this device.
  
--- 343,349 ----
        probe:  Checks if the driver can support a device
                with this type. The tag may be used to get
                more info with pci_read_conf(). See below.
!               It returns a string with the device's name,
                or a NULL pointer, if the driver cannot
                support this device.
  
***************
*** 405,411 ****
  some effort has been made to make the pci, pccard, and scsi code
  portable.  The isa and eisa specific code resides in
  /usr/src/sys/i386/isa and /usr/src/sys/i386/eisa respectively.
! The machine independant pci, pc-card, and scsi code reside in
  /usr/src/sys/{pci,pccard,scsi}. The i386 specific code for these
  reside in /usr/src/sys/i386/{pci,pccard,scsi}.
  
--- 405,411 ----
  some effort has been made to make the pci, pccard, and scsi code
  portable.  The isa and eisa specific code resides in
  /usr/src/sys/i386/isa and /usr/src/sys/i386/eisa respectively.
! The machine independent pci, pc-card, and scsi code reside in
  /usr/src/sys/{pci,pccard,scsi}. The i386 specific code for these
  reside in /usr/src/sys/i386/{pci,pccard,scsi}.
  
***************
*** 419,425 ****
  
  <p>
  A typical driver has the source code in one c-file, say dev.c.  The
! driver also can have some include files devreg.h contains device
  public device register declarations, macros, and other driver
  specific declarations.  Some drivers call this devvar.h instead.
  Some drivers, such as the dgb (for the Digiboard PC/Xe),
--- 419,425 ----
  
  <p>
  A typical driver has the source code in one c-file, say dev.c.  The
! driver also can have some include files; devreg.h contains
  public device register declarations, macros, and other driver
  specific declarations.  Some drivers call this devvar.h instead.
  Some drivers, such as the dgb (for the Digiboard PC/Xe),
***************
*** 467,473 ****
  <p>
  The standard model for adding a device driver to the Berkeley kernel
  is to add your driver to the list of known devices. This list is
! dependant on the cpu architecture.  If the device is not i386 specific
  (pccard, pci, scsi), the file is in ``/usr/src/sys/conf/files''.
  If the device is i386 specific, use ``/usr/src/sys/i386/conf/files.i386''.
  A typical line looks like:
--- 467,473 ----
  <p>
  The standard model for adding a device driver to the Berkeley kernel
  is to add your driver to the list of known devices. This list is
! dependent on the cpu architecture.  If the device is not i386 specific
  (pccard, pci, scsi), the file is in ``/usr/src/sys/conf/files''.
  If the device is i386 specific, use ``/usr/src/sys/i386/conf/files.i386''.
  A typical line looks like:
***************
*** 494,501 ****
  
  <sect2>Make room in conf.c
  <p>
! Now you must edit ``/usr/src/sys/i386/i386/conf.c`` to make an entry
! for your driver.  Somewhere near the top, you need to delcare your
  entry points. The entry for the joystick driver is:
  <code>
  #include "joy.h"
--- 494,501 ----
  
  <sect2>Make room in conf.c
  <p>
! Now you must edit ``/usr/src/sys/i386/i386/conf.c'' to make an entry
! for your driver.  Somewhere near the top, you need to declare your
  entry points. The entry for the joystick driver is:
  <code>
  #include "joy.h"
***************
*** 547,555 ****
  Order is what determines the major number of your device. Which is why
  there will always be an entry for your driver, either null entry
  points, or actual entry points.  It is probably worth noting that this
! is significantly different from SCO and other system V derrivatives,
  where any device can (in theory) have any major number.  This is
! largley a convenience on FreeBSD, due to the way device nodes are
  created.  More on this later.
  
  <sect2>Adding your device to the config file.
--- 547,555 ----
  Order is what determines the major number of your device. Which is why
  there will always be an entry for your driver, either null entry
  points, or actual entry points.  It is probably worth noting that this
! is significantly different from SCO and other system V derivatives,
  where any device can (in theory) have any major number.  This is
! largely a convenience on FreeBSD, due to the way device nodes are
  created.  More on this later.
  
  <sect2>Adding your device to the config file.
***************
*** 565,578 ****
  
  A slightly more complicated entry is for the ``ix'' driver:
  <verb>
! device ix0 at isa? port 0x300 net irq 10 iomem 0xd0000 iosiz 32768 vector ixint
! r
  </verb>
  This says that we have a device called `ix0' on the isa bus.  It uses
! io-port 0x300. It's interrupt will be masked with other devices in
  the network class. It uses interrupt 10. It uses
  32k of shared memory at physical address 0xd0000.  It also defines
! it's interrupt handler to be ``ixintr()''
  
  <sect2>config(8) the kernel.
  <p>
--- 565,577 ----
  
  A slightly more complicated entry is for the ``ix'' driver:
  <verb>
! device ix0 at isa? port 0x300 net irq 10 iomem 0xd0000 iosiz 32768 vector ixintr
  </verb>
  This says that we have a device called `ix0' on the isa bus.  It uses
! io-port 0x300. Its interrupt will be masked with other devices in
  the network class. It uses interrupt 10. It uses
  32k of shared memory at physical address 0xd0000.  It also defines
! its interrupt handler to be ``ixintr()''.
  
  <sect2>config(8) the kernel.
  <p>
***************
*** 600,606 ****
  <p>
  On FreeBSD, you are responsible for making your own device nodes.  The
  major number of your device is determined by the slot number in the
! device switch.  Minor number is driver dependant, of course.  You can
  either run the mknod's from the command line, or add a section to
  /dev/MAKEDEV.local, or even /dev/MAKEDEV to do the work.  I sometimes
  create a MAKEDEV.dev script that can be run stand-alone or pasted
--- 599,605 ----
  <p>
  On FreeBSD, you are responsible for making your own device nodes.  The
  major number of your device is determined by the slot number in the
! device switch.  Minor number is driver dependent, of course.  You can
  either run the mknod's from the command line, or add a section to
  /dev/MAKEDEV.local, or even /dev/MAKEDEV to do the work.  I sometimes
  create a MAKEDEV.dev script that can be run stand-alone or pasted
***************
*** 674,680 ****
   -- Declares the device driver entry points as external.
  <code>
      38  /*
!     39   * delcare your entry points as externs
      40   */
      41
      42  extern int pcaprobe(struct isa_device *);
--- 673,679 ----
   -- Declares the device driver entry points as external.
  <code>
      38  /*
!     39   * declare your entry points as externs
      40   */
      41
      42  extern int pcaprobe(struct isa_device *);
***************
*** 692,698 ****
  Lines  52 -  70
  
   -- This is creates the device switch entry table for your driver.
! This table gets wholesale swapped into the system device switch at
  the location specified by your major number.  In the standard model,
  these are in /usr/src/sys/i386/i386/conf.c.  NOTE: you cannot pick a
  device major number higher than what exists in conf.c, for example at
--- 691,697 ----
  Lines  52 -  70
  
   -- This is creates the device switch entry table for your driver.
! This table gets swapped wholesale into the system device switch at
  the location specified by your major number.  In the standard model,
  these are in /usr/src/sys/i386/i386/conf.c.  NOTE: you cannot pick a
  device major number higher than what exists in conf.c, for example at
***************
*** 725,731 ****
  
   -- This section is analogous to the config file declaration of your
  device.  The members of the isa_device structure are filled in by what
! is known about your device, I/O port, shared memory segment, etc.  we
  will probably never have a need for two pcaudio devices in the kernel,
  but this example shows how multiple devices can be supported.
  <code>
--- 724,730 ----
  
   -- This section is analogous to the config file declaration of your
  device.  The members of the isa_device structure are filled in by what
! is known about your device, I/O port, shared memory segment, etc.  We
  will probably never have a need for two pcaudio devices in the kernel,
  but this example shows how multiple devices can be supported.
  <code>
***************
*** 798,806 ****
  driver, as opposed to an lkm filesystem, or an lkm system call.
  <code>
     132  /*
!    133   * this macro maps to a funtion which
     134   * sets the lkm up for a driver
!    135   * as opposed to a filesystem, systemcall, or misc
     136   * lkm.
     137   */
     138  MOD_DEV("pcaudio_mod", LM_DT_CHAR, 24, &amp;pcacdevsw);
--- 797,805 ----
  driver, as opposed to an lkm filesystem, or an lkm system call.
  <code>
     132  /*
!    133   * this macro maps to a function which
     134   * sets the lkm up for a driver
!    135   * as opposed to a filesystem, system call, or misc
     136   * lkm.
     137   */
     138  MOD_DEV("pcaudio_mod", LM_DT_CHAR, 24, &amp;pcacdevsw);
***************
*** 826,832 ****
  <code>
     140  /*
     141   * this function is called when the module is
!    142   * loaded, it tries to mimic the behavior
     143   * of the standard probe/attach stuff from
     144   * isa.c
     145   */
--- 825,831 ----
  <code>
     140  /*
     141   * this function is called when the module is
!    142   * loaded; it tries to mimic the behavior
     143   * of the standard probe/attach stuff from
     144   * isa.c
     145   */
***************
*** 857,863 ****
  
  Lines 169 - 179
  
!  -- This is the function called when your driver is unloaded, it just displays
  a message to that effect.
  <code>
     169  /*
--- 856,862 ----
  
  Lines 169 - 179
  
!  -- This is the function called when your driver is unloaded; it just displays
  a message to that effect.
  <code>
     169  /*
***************
*** 898,910 ****
     191  #endif /* NICP > 0 */
  </code>
  
! <sect1> Device Type Idiosyncracies
  <sect2> Character
  <sect2> Block
  <sect2> Network
  <sect2> Line Discipline
  
! <sect1> Bus Type Idiosyncracies
  <sect2> ISA
  <sect2> EISA
  <sect2> PCI
--- 897,909 ----
     191  #endif /* NICP > 0 */
  </code>
  
! <sect1> Device Type Idiosyncrasies
  <sect2> Character
  <sect2> Block
  <sect2> Network
  <sect2> Line Discipline
  
! <sect1> Bus Type Idiosyncrasies
  <sect2> ISA
  <sect2> EISA
  <sect2> PCI
***************
*** 950,957 ****
   * control, known in UN*X as a process; it has references to substructures
   * containing descriptions of things that the process uses, but may share
   * with related processes.  The process structure and the substructures
!  * are always addressible except for those marked "(PROC ONLY)" below,
!  * which might be addressible only on a processor on which the process
   * is running.
   */
  struct  proc {
--- 949,956 ----
   * control, known in UN*X as a process; it has references to substructures
   * containing descriptions of things that the process uses, but may share
   * with related processes.  The process structure and the substructures
!  * are always addressable except for those marked "(PROC ONLY)" below,
!  * which might be addressable only on a processor on which the process
   * is running.
   */
  struct  proc {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199605281737.RAA09291>