From owner-freebsd-drivers@FreeBSD.ORG Thu Feb 28 17:22:14 2013 Return-Path: Delivered-To: freebsd-drivers@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 9B1DE73B for ; Thu, 28 Feb 2013 17:22:14 +0000 (UTC) (envelope-from star-one@tx.rr.com) Received: from cdptpa-omtalb.mail.rr.com (cdptpa-omtalb.mail.rr.com [75.180.132.120]) by mx1.freebsd.org (Postfix) with ESMTP id 5AC0536C for ; Thu, 28 Feb 2013 17:22:14 +0000 (UTC) Authentication-Results: cdptpa-omtalb.mail.rr.com smtp.user=star-one@tx.rr.com; auth=pass (LOGIN) X-Authority-Analysis: v=2.0 cv=cYNQXw/M c=1 sm=0 a=_-dPGZQ6cu4A:10 a=05ChyHeVI94A:10 a=IkcTkHD0fZMA:10 a=ayC55rCoAAAA:8 a=ZO-uyplj7cEA:10 a=6I5d2MoRAAAA:8 a=ZHvs9RVKRzM5wJDJj-wA:9 a=QEXdDO2ut3YA:10 a=SV7veod9ZcQA:10 a=8g97u3uHHZxdf5iFaGgFAA==:117 X-Cloudmark-Score: 0 X-Authenticated-User: star-one@tx.rr.com Received: from [10.127.132.170] ([10.127.132.170:32782] helo=cdptpa-web19-z02) by cdptpa-oedge03.mail.rr.com (envelope-from ) (ecelerity 2.2.3.46 r()) with ESMTPA id DB/DE-11869-5429F215; Thu, 28 Feb 2013 17:22:13 +0000 Message-ID: <20130228172213.GI7H4.29745.root@cdptpa-web19-z02> Date: Thu, 28 Feb 2013 12:22:13 -0500 From: To: freebsd-drivers@freebsd.org, John Baldwin Subject: Re: ISA driver for IRQ and PortIO In-Reply-To: <201302281039.41919.jhb@freebsd.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) Sensitivity: Normal X-Originating-IP: X-BeenThere: freebsd-drivers@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Writing device drivers for FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Feb 2013 17:22:14 -0000 Thank you. I'll try that today. Dave ---- John Baldwin 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