This is an archive of past FreeBSD releases; it's part of the FreeBSD Documentation Archive.

PCI Devices

Chapter 23 PCI Devices

Table of Contents
23.1 Probe and Attach
23.2 Bus Resources

This chapter will talk about the FreeBSD mechanisms for writing a device driver for a device on a PCI bus.

23.1 Probe and Attach

Information here about how the PCI bus code iterates through the unattached devices and see if a newly loaded kld will attach to any of them.

    /*
     * Simple KLD to play with the PCI functions.
     *
     * Murray Stokely
     */
    
    #define MIN(a,b) (((a) < (b)) ? (a) : (b))
    
    #include <sys/types.h>
    #include <sys/module.h>
    #include <sys/systm.h>  /* uprintf */ 
    #include <sys/errno.h>
    #include <sys/param.h>  /* defines used in kernel.h */
    #include <sys/kernel.h> /* types used in module initialization */
    #include <sys/conf.h>   /* cdevsw struct */
    #include <sys/uio.h>    /* uio struct */
    #include <sys/malloc.h>
    #include <sys/bus.h>  /* structs, prototypes for pci bus stuff */
    
    #include <pci/pcivar.h> /* For get_pci macros! */
    
    /* Function prototypes */
    d_open_t      mypci_open;
    d_close_t     mypci_close;
    d_read_t      mypci_read;
    d_write_t     mypci_write;
    
    /* Character device entry points */
    
    static struct cdevsw mypci_cdevsw = {
      mypci_open,
      mypci_close,
      mypci_read,
      mypci_write,
      noioctl,
      nopoll,
      nommap,
      nostrategy,
      "mypci",
      36,                   /* reserved for lkms - /usr/src/sys/conf/majors */
      nodump,
      nopsize,
      D_TTY,
      -1
    };
    
    /* vars */
    static dev_t sdev;
    
    /* We're more interested in probe/attach than with
       open/close/read/write at this point */
    
    int 
    mypci_open(dev_t dev, int oflags, int devtype, struct proc *p)
    {
      int err = 0;
    
      uprintf("Opened device \"mypci\" successfully.\n");
      return(err);
    }
    
    int 
    mypci_close(dev_t dev, int fflag, int devtype, struct proc *p)
    {
      int err=0;
    
      uprintf("Closing device \"mypci.\"\n"); 
      return(err);
    } 
    
    int
    mypci_read(dev_t dev, struct uio *uio, int ioflag)
    {
      int err = 0;
    
      uprintf("mypci read!\n");
      return err;
    }
    
    int
    mypci_write(dev_t dev, struct uio *uio, int ioflag)
    {
      int err = 0;
    
      uprintf("mypci write!\n");
      return(err);
    }
    
    /* PCI Support Functions */
    
    /*
     * Return identification string if this is device is ours.
     */
    static int
    mypci_probe(device_t dev)
    {
      uprintf("MyPCI Probe\n"
          "Vendor ID : 0x%x\n"
          "Device ID : 0x%x\n",pci_get_vendor(dev),pci_get_device(dev));
    
      if (pci_get_vendor(dev) == 0x11c1) {
        uprintf("We've got the Winmodem, probe successful!\n");
        return 0;
      }
    
      return ENXIO;
    }
    
    /* Attach function is only called if the probe is successful */
    
    static int
    mypci_attach(device_t dev)
    {
      uprintf("MyPCI Attach for : deviceID : 0x%x\n",pci_get_vendor(dev));
      sdev = make_dev(&mypci_cdevsw,
              0,
              UID_ROOT,
              GID_WHEEL,
              0600,
              "mypci");
      uprintf("Mypci device loaded.\n");
      return ENXIO;
    }
    
    /* Detach device. */
    
    static int
    mypci_detach(device_t dev)
    {
      uprintf("Mypci detach!\n");
      return 0;
    }
    
    /* Called during system shutdown after sync. */
    
    static int
    mypci_shutdown(device_t dev)
    {
      uprintf("Mypci shutdown!\n");
      return 0;
    }
    
    /*
     * Device suspend routine.  
     */
    static int
    mypci_suspend(device_t dev)
    {
      uprintf("Mypci suspend!\n");
      return 0;
    }
    
    /*
     * Device resume routine.
     */
    
    static int
    mypci_resume(device_t dev)
    {
      uprintf("Mypci resume!\n");
      return 0;
    }
    
    static device_method_t mypci_methods[] = {
        /* Device interface */
        DEVMETHOD(device_probe,     mypci_probe),
        DEVMETHOD(device_attach,    mypci_attach),
        DEVMETHOD(device_detach,    mypci_detach),
        DEVMETHOD(device_shutdown,  mypci_shutdown),
        DEVMETHOD(device_suspend,   mypci_suspend),
        DEVMETHOD(device_resume,    mypci_resume),
    
        { 0, 0 }
    };
    
    static driver_t mypci_driver = {
        "mypci",
        mypci_methods,
        0,
        /*  sizeof(struct mypci_softc), */
    };
    
    static devclass_t mypci_devclass;
    
    DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);

Additional Resources



This, and other documents, can be downloaded from ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

For questions about FreeBSD, read the documentation before contacting <questions@FreeBSD.org>.
For questions about this documentation, e-mail <doc@FreeBSD.org>.