zoukankan      html  css  js  c++  java
  • FreeBSD的PCI驱动例子

      1 /*
      2  * Simple KLD to play with the PCI functions.
      3  *
      4  * Murray Stokely
      5  */
      6 
      7 #include <sys/param.h>        /* defines used in kernel.h */
      8 #include <sys/module.h>
      9 #include <sys/systm.h>
     10 #include <sys/errno.h>
     11 #include <sys/kernel.h>        /* types used in module initialization */
     12 #include <sys/conf.h>        /* cdevsw struct */
     13 #include <sys/uio.h>        /* uio struct */
     14 #include <sys/malloc.h>
     15 #include <sys/bus.h>        /* structs, prototypes for pci bus stuff and DEVMETHOD macros! */
     16 
     17 #include <machine/bus.h>
     18 #include <sys/rman.h>
     19 #include <machine/resource.h>
     20 
     21 #include <dev/pci/pcivar.h>    /* For pci_get macros! */
     22 #include <dev/pci/pcireg.h>
     23 
     24 /* The softc holds our per-instance data. */
     25 struct mypci_softc {
     26     device_t    my_dev;
     27     struct cdev    *my_cdev;
     28 };
     29 
     30 /* Function prototypes */
     31 static d_open_t        mypci_open;
     32 static d_close_t    mypci_close;
     33 static d_read_t        mypci_read;
     34 static d_write_t    mypci_write;
     35 
     36 /* Character device entry points */
     37 
     38 static struct cdevsw mypci_cdevsw = {
     39     .d_version =    D_VERSION,
     40     .d_open =    mypci_open,
     41     .d_close =    mypci_close,
     42     .d_read =    mypci_read,
     43     .d_write =    mypci_write,
     44     .d_name =    "mypci",
     45 };
     46 
     47 /*
     48  * In the cdevsw routines, we find our softc by using the si_drv1 member
     49  * of struct cdev.  We set this variable to point to our softc in our
     50  * attach routine when we create the /dev entry.
     51  */
     52 
     53 int
     54 mypci_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
     55 {
     56     struct mypci_softc *sc;
     57 
     58     /* Look up our softc. */
     59     sc = dev->si_drv1;
     60     device_printf(sc->my_dev, "Opened successfully.
    ");
     61     return (0);
     62 }
     63 
     64 int
     65 mypci_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
     66 {
     67     struct mypci_softc *sc;
     68 
     69     /* Look up our softc. */
     70     sc = dev->si_drv1;
     71     device_printf(sc->my_dev, "Closed.
    ");
     72     return (0);
     73 }
     74 
     75 int
     76 mypci_read(struct cdev *dev, struct uio *uio, int ioflag)
     77 {
     78     struct mypci_softc *sc;
     79 
     80     /* Look up our softc. */
     81     sc = dev->si_drv1;
     82     device_printf(sc->my_dev, "Asked to read %zd bytes.
    ", uio->uio_resid);
     83     return (0);
     84 }
     85 
     86 int
     87 mypci_write(struct cdev *dev, struct uio *uio, int ioflag)
     88 {
     89     struct mypci_softc *sc;
     90 
     91     /* Look up our softc. */
     92     sc = dev->si_drv1;
     93     device_printf(sc->my_dev, "Asked to write %zd bytes.
    ", uio->uio_resid);
     94     return (0);
     95 }
     96 
     97 /* PCI Support Functions */
     98 
     99 /*
    100  * Compare the device ID of this device against the IDs that this driver
    101  * supports.  If there is a match, set the description and return success.
    102  */
    103 static int
    104 mypci_probe(device_t dev)
    105 {
    106 
    107     device_printf(dev, "MyPCI Probe
    Vendor ID : 0x%x
    Device ID : 0x%x
    ",
    108         pci_get_vendor(dev), pci_get_device(dev));
    109 
    110     if (pci_get_vendor(dev) == 0x11c1) {
    111         printf("We've got the Winmodem, probe successful!
    ");
    112         device_set_desc(dev, "WinModem");
    113         return (BUS_PROBE_DEFAULT);
    114     }
    115     return (ENXIO);
    116 }
    117 
    118 /* Attach function is only called if the probe is successful. */
    119 
    120 static int
    121 mypci_attach(device_t dev)
    122 {
    123     struct mypci_softc *sc;
    124 
    125     printf("MyPCI Attach for : deviceID : 0x%x
    ", pci_get_devid(dev));
    126 
    127     /* Look up our softc and initialize its fields. */
    128     sc = device_get_softc(dev);
    129     sc->my_dev = dev;
    130 
    131     /*
    132      * Create a /dev entry for this device.  The kernel will assign us
    133      * a major number automatically.  We use the unit number of this
    134      * device as the minor number and name the character device
    135      * "mypci<unit>".
    136      */
    137     sc->my_cdev = make_dev(&mypci_cdevsw, device_get_unit(dev),
    138         UID_ROOT, GID_WHEEL, 0600, "mypci%u", device_get_unit(dev));
    139     sc->my_cdev->si_drv1 = sc;
    140     printf("Mypci device loaded.
    ");
    141     return (0);
    142 }
    143 
    144 /* Detach device. */
    145 
    146 static int
    147 mypci_detach(device_t dev)
    148 {
    149     struct mypci_softc *sc;
    150 
    151     /* Teardown the state in our softc created in our attach routine. */
    152     sc = device_get_softc(dev);
    153     destroy_dev(sc->my_cdev);
    154     printf("Mypci detach!
    ");
    155     return (0);
    156 }
    157 
    158 /* Called during system shutdown after sync. */
    159 
    160 static int
    161 mypci_shutdown(device_t dev)
    162 {
    163 
    164     printf("Mypci shutdown!
    ");
    165     return (0);
    166 }
    167 
    168 /*
    169  * Device suspend routine.
    170  */
    171 static int
    172 mypci_suspend(device_t dev)
    173 {
    174 
    175     printf("Mypci suspend!
    ");
    176     return (0);
    177 }
    178 
    179 /*
    180  * Device resume routine.
    181  */
    182 static int
    183 mypci_resume(device_t dev)
    184 {
    185 
    186     printf("Mypci resume!
    ");
    187     return (0);
    188 }
    189 
    190 static device_method_t mypci_methods[] = {
    191     /* Device interface */
    192     DEVMETHOD(device_probe,        mypci_probe),
    193     DEVMETHOD(device_attach,    mypci_attach),
    194     DEVMETHOD(device_detach,    mypci_detach),
    195     DEVMETHOD(device_shutdown,    mypci_shutdown),
    196     DEVMETHOD(device_suspend,    mypci_suspend),
    197     DEVMETHOD(device_resume,    mypci_resume),
    198 
    199     DEVMETHOD_END
    200 };
    201 
    202 static devclass_t mypci_devclass;
    203 
    204 DEFINE_CLASS_0(mypci, mypci_driver, mypci_methods, sizeof(struct mypci_softc));
    205 DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);
    # Makefile for mypci driver
    
    KMOD=    mypci
    SRCS=    mypci.c
    SRCS+=    device_if.h bus_if.h pci_if.h
    
    .include <bsd.kmod.mk>

    Chapter 11. PCI Devices (freebsd.org)上面代码链接地址

    第 11 章 PCI设备 (freebsd.org)中文版链接地址

    如果你将上面的源文件和 Makefile放入一个目录,你可以运行 make编译示例驱动程序。 还有,你可以运行make load 将驱动程序装载到当前正在运行的内核中,而make unload可在装载后卸载驱动程序。

    注:如果make报错(“make” command: unable to locate the kernel source tree)或者其他的,请给系统安装源码

  • 相关阅读:
    EUI库
    EUI库
    EUI库
    EUI库
    EUI库
    EUI库
    EUI库
    EUI库
    EUI库
    EUI库
  • 原文地址:https://www.cnblogs.com/lishuaicq/p/13919491.html
Copyright © 2011-2022 走看看