|
This chapter will talk about the FreeBSD mechanisms for writing a device driver for a device on a PCI bus.
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/param.h> /* defines used in kernel.h */ #include <sys/module.h> #include <sys/systm.h> #include <sys/errno.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 <machine/bus.h> #include <sys/rman.h> #include <machine/resource.h> #include <dev/pci/pcivar.h> /* For get_pci macros! */ #include <dev/pci/pcireg.h> /* 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 = { .d_open = mypci_open, .d_close = mypci_close, .d_read = mypci_read, .d_write = mypci_write, .d_name = "mypci", }; /* 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, d_thread_t *td) { int err = 0; printf("Opened device \"mypci\" successfully.\n"); return (err); } int mypci_close(dev_t dev, int fflag, int devtype, d_thread_t *td) { int err = 0; printf("Closing device \"mypci.\"\n"); return (err); } int mypci_read(dev_t dev, struct uio *uio, int ioflag) { int err = 0; printf("mypci read!\n"); return (err); } int mypci_write(dev_t dev, struct uio *uio, int ioflag) { int err = 0; printf("mypci write!\n"); return (err); } /* PCI Support Functions */ /* * Return identification string if this is device is ours. */ static int mypci_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"); return (0); } return (ENXIO); } /* Attach function is only called if the probe is successful */ static int mypci_attach(device_t dev) { printf("MyPCI Attach for : deviceID : 0x%x\n",pci_get_vendor(dev)); sdev = make_dev(&mypci_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "mypci"); printf("Mypci device loaded.\n"); return (ENXIO); } /* Detach device. */ static int mypci_detach(device_t dev) { printf("Mypci detach!\n"); return (0); } /* Called during system shutdown after sync. */ static int mypci_shutdown(device_t dev) { printf("Mypci shutdown!\n"); return (0); } /* * Device suspend routine. */ static int mypci_suspend(device_t dev) { printf("Mypci suspend!\n"); return (0); } /* * Device resume routine. */ static int mypci_resume(device_t dev) { printf("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
PCI System Architecture, Fourth Edition by Tom Shanley, et al.
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>.
Hosting by: Hurra Communications Ltd.
Generated: 2007-01-26 17:58:42