Date: Thu, 28 Feb 2013 12:22:13 -0500 From: <star-one@tx.rr.com> To: freebsd-drivers@freebsd.org, John Baldwin <jhb@freebsd.org> Subject: Re: ISA driver for IRQ and PortIO Message-ID: <20130228172213.GI7H4.29745.root@cdptpa-web19-z02> In-Reply-To: <201302281039.41919.jhb@freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Thank you. I'll try that today. Dave ---- John Baldwin <jhb@freebsd.org> wrote: > On Wednesday, February 27, 2013 5:16:41 pm star-one@tx.rr.com wrote: > > I need to write a simple device driver for the ISA bus that uses one IRQ and > a few reads and writes to I/O Ports 0x300 +. > > > > > > I don't know even where to start with FreeBSD. I've done drivers before in > other OS systems and have a book for Linux but FreeBSD seems MUCH differnt. > > > > > > Are there any examples I can get? I thought about modifying the serial > driver but I'm not een sure if that's a good idea. > > > > > > Any help would be great. > > There is a FreeBSD Device Driver book. You will need to allocate 'struct > resource' objects for your IRQ and I/O port and then use the bus_space API > with your I/O port resource to do inb/outb operations. That is, you would > need something like this: > > In /boot/device.hints: > > hint.foo.0.at="isa0" > hint.foo.0.irq=X > hint.foo.0.port=0x300 > > Then a sketch of your driver would be: > > #define NPORTS 4 /* How many I/O ports you need starting at 0x300 */ > > /* Sample only of names for the 4 ports via relative offsets to the start */ > #define CONTROL_REG 0 > #define DATA_REG 1 > > struct foo_softc { > device_t dev; > struct resource *io; > struct resource *irq; > void *intr_cookie; > }; > > /* Interrupt handler. */ > static void > foo_int(void *arg) > { > struct foo_softc *sc; > > sc = arg; > device_printf(sc->dev, "got an interrupt\n"); > } > > static int > foo_probe(device_t dev) > { > /* Ignore PNP devices. */ > if (isa_get_logicalid(dev) != 0) > return (ENXIO); > > /* Require IRQ and port hints. */ > if (isa_get_port(dev) == -1 || > isa_get_irq(dev) == -1) > return (ENXIO); > > device_set_desc(dev, "My foo device"); > return (BUS_PROBE_GENERIC); > } > > static int > foo_attach(device_t dev) > { > struct foo_softc *sc; > int error, rid; > > sc = device_get_softc(dev); > sc->dev = dev; > > /* Allocate resources. */ > rid = 0; > sc->io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0ul, ~0ul, NPORTS, > RF_ACTIVE); > if (sc->io == NULL) { > device_printf(dev, "Failed to allocate I/O ports\n"); > error = ENXIO; > goto out; > rid = 0; > sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); > if (sc->irq == NULL) { > device_printf(dev, "Failed to allocate IRQ\n"); > error = ENXIO; > goto out; > } > > /* Read a byte from port 0x300 */ > device_printf(dev, "Current control value = %x\n", > bus_read_1(sc->io, CONTROL_REG)); > /* Read a byte from port 0x301 */ > device_printf(dev, "Current data value = %x\n", > bus_read_1(sc->io, DATA_REG)); > /* Write a byte to the control reg at 0x300 */ > bus_write_1(sc->io, CONTROL_REG, 0xff); > > /* Setup interrupt handler. */ > error = bus_setup_intr(dev, sc->irq, INTR_TYPE_MISC | INTR_MPSAFE, NULL, > foo_intr, sc, &sc->intr_cookie); > if (error != 0) { > device_printf(dev, "Failed to setup interrupt handler\n"); > goto out; > } > return (0); > > out: > if (sc->irq != NULL) > bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); > if (sc->io != NULL) > bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->io); > return (error); > } > > static int > foo_detach(device_t dev) > { > struct foo_softc *sc; > > sc = device_get_softc(dev); > bus_teardown_intr(dev, sc->irq, sc->intr_cookie); > bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); > bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->io); > return (0); > } > > static device_method_t foo_methods[] = { > DEVMETHOD(device_probe, foo_probe), > DEVMETHOD(device_attach, foo_attach), > DEVMETHOD(device_detach, foo_detach), > DEVMETHOD_END > }; > > static driver_t foo_driver = { > "foo", > foo_methods, > sizeof(struct foo_softc); > }; > > static devclass_t foo_devclass; > > DRIVER_MODULE(foo, isa, foo_driver, foo_devclass, NULL, NULL); > > That should get you up and running, but to do something useful with the device > you'll probably want to create a cdev or some such. > > -- > John Baldwin
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130228172213.GI7H4.29745.root>