第 11 章 PCI设备

翻译:.
目录
11.1. 探测与连接
11.2. 总线资源

本章将讨论FreeBSD为了给PCI总线上的设备编写驱动程序而提供的机制。

11.1. 探测与连接

这儿的信息是关于PCI总线代码如何迭代通过未连接的设备,并查看新 加载的kld是否会连接其中一个。

11.1.1. 示例驱动程序源代码(mypci.c)

/* * 与PCI函数进行交互的简单KLD * * Murray Stokely */#include <sys/param.h> /* kernel.h中使用的定义 */#include <sys/module.h>#include <sys/systm.h>#include <sys/errno.h>#include <sys/kernel.h> /* 模块初始化中使用的类型 */#include <sys/conf.h> /* cdevsw结构 */#include <sys/uio.h> /* uio结构 */#include <sys/malloc.h>#include <sys/bus.h> /* pci总线用到的结构、原型 */#include <machine/bus.h>#include <sys/rman.h>#include <machine/resource.h>#include <dev/pci/pcivar.h> /* 为了使用get_pci宏! */#include <dev/pci/pcireg.h>/* softc保存我们每个实例的数据。 */struct mypci_softc { device_t my_dev; struct cdev *my_cdev;};/* 函数原型 */static d_open_t mypci_open;static d_close_t mypci_close;static d_read_t mypci_read;static d_write_t mypci_write;/* 字符设备入口点 */static struct cdevsw mypci_cdevsw = { .d_version = D_VERSION, .d_open = mypci_open, .d_close = mypci_close, .d_read = mypci_read, .d_write = mypci_write, .d_name = "mypci",};/* * 在cdevsw例程中,我们通过结构体cdev中的成员si_drv1找出我们的softc。 * 当我们建立/dev项时,在我们的已附着的例程中, * 我们设置这个变量指向我们的softc。 */intmypci_open(struct cdev *dev, int oflags, int devtype, d_thread_t *td){ struct mypci_softc *sc; /* Look up our softc. */ sc = dev->si_drv1; device_printf(sc->my_dev, "Opened successfully.\n"); return (0);}intmypci_close(struct cdev *dev, int fflag, int devtype, d_thread_t *td){ struct mypci_softc *sc; /* Look up our softc. */ sc = dev->si_drv1; device_printf(sc->my_dev, "Closed.\n"); return (0);}intmypci_read(struct cdev *dev, struct uio *uio, int ioflag){ struct mypci_softc *sc; /* Look up our softc. */ sc = dev->si_drv1; device_printf(sc->my_dev, "Asked to read %d bytes.\n", uio->uio_resid); return (0);}intmypci_write(struct cdev *dev, struct uio *uio, int ioflag){ struct mypci_softc *sc; /* Look up our softc. */ sc = dev->si_drv1; device_printf(sc->my_dev, "Asked to write %d bytes.\n", uio->uio_resid); return (0);}/* PCI支持函数 *//* * 将某个设置的标识与这个驱动程序支持的标识相比较。 * 如果相符,设置描述字符并返回成功。 */static intmypci_probe(device_t dev){ device_printf(dev, "MyPCI Probe\nVendor ID : 0x%x\nDevice ID : 0x%x\n", pci_get_vendor(dev), pci_get_device(dev)); if (pci_get_vendor(dev) == 0x11c1) { printf("We've got the Winmodem, probe successful!\n"); device_set_desc(dev, "WinModem"); return (BUS_PROBE_DEFAULT); } return (ENXIO);}/* 只有当探测成功时才调用连接函数 */static intmypci_attach(device_t dev){ struct mypci_softc *sc; printf("MyPCI Attach for : deviceID : 0x%x\n", pci_get_devid(dev)); /* Look up our softc and initialize its fields. */ sc = device_get_softc(dev); sc->my_dev = dev; /* * Create a /dev entry for this device. The kernel will assign us * a major number automatically. We use the unit number of this * device as the minor number and name the character device * "mypci<unit>". */ sc->my_cdev = make_dev(&mypci_cdevsw, device_get_unit(dev), UID_ROOT, GID_WHEEL, 0600, "mypci%u", device_get_unit(dev)); sc->my_cdev->si_drv1 = sc; printf("Mypci device loaded.\n"); return (0);}/* 分离设备。 */static intmypci_detach(device_t dev){ struct mypci_softc *sc; /* Teardown the state in our softc created in our attach routine. */ sc = device_get_softc(dev); destroy_dev(sc->my_cdev); printf("Mypci detach!\n"); return (0);}/* 系统关闭期间在sync之后调用。 */static intmypci_shutdown(device_t dev){ printf("Mypci shutdown!\n"); return (0);}/* * 设备挂起例程。 */static intmypci_suspend(device_t dev){ printf("Mypci suspend!\n"); return (0);}/* * 设备恢复(重新开始)例程。 */static intmypci_resume(device_t dev){ printf("Mypci resume!\n"); return (0);}static device_method_t mypci_methods[] = { /* 设备接口 */ 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 devclass_t mypci_devclass;DEFINE_CLASS_0(mypci, mypci_driver, mypci_methods, sizeof(struct mypci_softc));DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);

11.1.2. 示例驱动程序的Makefile

# 驱动程序mypci的MakefileKMOD= mypciSRCS= mypci.cSRCS+= device_if.h bus_if.h pci_if.h.include <bsd.kmod.mk>

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

11.1.3. 更多资源

本文档和其它文档可从这里下载: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

如果对于FreeBSD有问题,请先阅读 文档,如不能解决再联系 <questions@FreeBSD.org>.

关于本文档的问题请发信联系 <doc@FreeBSD.org>.