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)或者其他的,请给系统安装源码

原文地址:https://www.cnblogs.com/lishuaicq/p/13919491.html