Date: Sun, 21 Jan 2001 17:10:30 +0100 From: "Alex" <d_f0rce@gmx.de> To: <freebsd-hackers@freebsd.org> Subject: Problems attaching an interrupt handler Message-ID: <NEBBIKIHMLCDHCFEOMAHOEKCCAAA.d_f0rce@gmx.de>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. ------=_NextPart_000_0000_01C083CD.0EB2B120 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Hi, I started experimenting with kernel hacking to write an infrared device driver. Therfore I read Alexander Langer's article on DaemonNews and started modifying the led.c example code. Unfortunately I can't get my interrupt handler working. Could anyone please have a short look on my code. On loading the module the first time everything stays stable and vmstat -i shows 1 INT on my device. After unloading the module and reloading it the kernel crashes on the next incoming interrupt. Any ideas? Alex ------=_NextPart_000_0000_01C083CD.0EB2B120 Content-Type: application/octet-stream; name="mydev.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="mydev.c" /*=0A= * Copyright (c) 2000. M. Warner Losh. All Rights Reserved.=0A= *=0A= * "THE BEER-WARE LICENSE" (Revision 42):=0A= * <imp@FreeBSD.ORG> wrote this file. As long as you retain this notice = you=0A= * can do whatever you want with this stuff. If we meet some day, and = you think=0A= * this stuff is worth it, you can buy me a beer in return. M. Warner = Losh=0A= */=0A= =0A= /*=0A= * Simple driver for the I-Opener LED, but likely could be adapted=0A= * to any led driver. This is intended to be a thought excersize=0A= * as well as a useful sample driver. Since I don't have a hackable=0A= * iopener around to test it out on.=0A= *=0A= * The LED is located at 0x404c on the iopener. Likely we should find = this=0A= * in the pci space, and then do stuff from tehre. However, it appears = to=0A= * be controlled in some way by acpi, so I'm going to try to write this = driver=0A= * to not interfere with that.=0A= *=0A= * the lower two bits of this register control the state of the LED. = The left=0A= * led, with the mail ICON, is controlled by bit 0. The phone led is=0A= * controlled by bit 1.=0A= *=0A= * This is a bog simple ISA driver... Would make a useful example, imho.=0A= *=0A= * Since I'm lazy, I have only a write interface. The characters = recieved=0A= * by the driver are masked and the results sent to these gpios. This=0A= * allows things like '1' to turn on the led and '0' to turn off the led.=0A= * There is a minor number for each led controlled.=0A= *=0A= * The read interface returns 1 character ('0' off '1' on) for the state =0A= * of the led.=0A= *=0A= * thanks to "roastbeef" who posted technical information about this to = the=0A= * I-Opener BBS web site.=0A= */=0A= =0A= #include <sys/types.h>=0A= #include <sys/param.h>=0A= #include <sys/systm.h>=0A= #include <sys/malloc.h>=0A= #include <sys/kernel.h>=0A= #include <sys/bus.h>=0A= #include <sys/errno.h>=0A= #include <sys/conf.h>=0A= #include <sys/module.h>=0A= #include <sys/uio.h>=0A= #include <machine/bus.h>=0A= #include <machine/resource.h>=0A= #include <sys/rman.h>=0A= =0A= =0A= struct ir_softc =0A= {=0A= bus_space_tag_t bst;=0A= bus_space_handle_t bsh;=0A= dev_t dev0;=0A= dev_t dev1;=0A= u_int32_t open_mask;=0A= u_int32_t read_mask;=0A= struct resource *res;=0A= int rid;=0A= struct resource *irq;=0A= void *ih;=0A= int irqid;=0A= };=0A= =0A= static devclass_t ir_devclass;=0A= =0A= #define IR_IOADDR 0x3f8=0A= =0A= static void ir_intr( void *p );=0A= void get_sio_status( struct ir_softc *sc );=0A= =0A= =0A= static void=0A= ir_identify (driver_t *driver, device_t parent)=0A= {=0A= devclass_t dc;=0A= device_t child;=0A= =0A= dc =3D devclass_find("ir");=0A= if (devclass_get_device(dc, 0) =3D=3D NULL) {=0A= child =3D BUS_ADD_CHILD(parent, 0, "ir", -1);=0A= bus_set_resource(child, SYS_RES_IOPORT, 0, IR_IOADDR, 7);=0A= bus_set_resource(child, SYS_RES_IRQ, 0, 4, 1);=0A= }=0A= uprintf("IR Ident\n");=0A= }=0A= =0A= static int=0A= ir_probe(device_t dev)=0A= {=0A= if (device_get_unit(dev) !=3D 0)=0A= return (ENXIO);=0A= if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) =3D=3D 0)=0A= return (ENXIO);=0A= =0A= uprintf("IR Probe\n");=0A= return (0);=0A= }=0A= =0A= static int=0A= ir_attach(device_t dev)=0A= {=0A= struct ir_softc *sc;=0A= u_int8_t old;=0A= =0A= sc =3D (struct ir_softc *) device_get_softc(dev);=0A= sc->rid =3D 0;=0A= sc->res =3D bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid, 0ul, = ~0ul, 7,=0A= RF_ACTIVE);=0A= if (sc->res =3D=3D NULL)=0A= return ENXIO;=0A= sc->bst =3D rman_get_bustag(sc->res);=0A= sc->bsh =3D rman_get_bushandle(sc->res);=0A= sc->open_mask =3D 0;=0A= sc->read_mask =3D 0;=0A= =0A= uprintf("IR Attach\nTrying to access device ....\n");=0A= =0A= get_sio_status( sc );=0A= =0A= /* FIFO Puffer aktivieren */=0A= bus_space_write_1(sc->bst, sc->bsh,2,(u_int8_t) 7);=0A= /* keine Kontrolle, da IIR fuer FIFO-Operation write only */=0A= =0A= /* LCR Bit 7 auf 0 */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,3);=0A= old &=3D ~128; /* Bit 7 ausnullen */=0A= bus_space_write_1(sc->bst, sc->bsh,3,(u_int8_t) old);=0A= =0A= /* IER setzen, um Interrupt bei Modem Status Aenderung auszuloesen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,1);=0A= old &=3D ~1; /* Bit 0 ausnullen =3D> kein INT ausloesen, sobald ein = neues Zeichen im RBR */=0A= old &=3D ~2; /* Bit 1 ausnullen =3D> kein INT sobald THR leer */=0A= old &=3D ~4; /* Bit 2 ausnullen =3D> kein INT sobald Aenderung im LSR */=0A= old |=3D 8; /* Bit 3 setzen =3D> INT bei Aenderung im MSR */=0A= bus_space_write_1(sc->bst, sc->bsh,1,(u_int8_t) old);=0A= =0A= /* RTS im MCR auf high setzen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,4);=0A= old |=3D 1; /* Bit 0 setzen - DTR auf 0 -> PC bereit */=0A= old |=3D 2; /* Bit 1 setzen - RTS auf 0 -> PC will senden */=0A= old |=3D 8; /* Bit 3 setzen - UART loest INTs gemaess den = Einstellungen im IER aus */=0A= old &=3D ~16; /* Bit 4 ausnullen =3D> Selbsttest aus. */=0A= bus_space_write_1(sc->bst, sc->bsh,4,(u_int8_t) old);=0A= =0A= get_sio_status( sc );=0A= =0A= /* Interrupt Handler */=0A= sc->irqid=3D0;=0A= sc->irq =3D bus_alloc_resource( dev, SYS_RES_IRQ, &sc->irqid, 0ul, = ~0ul, 1, RF_SHAREABLE | RF_ACTIVE );=0A= uprintf("IRQID: %d\n",sc->irqid);=0A= if( !sc->irq )=0A= return ENXIO;=0A= if( BUS_SETUP_INTR(device_get_parent(dev), dev, sc->irq, = INTR_TYPE_MISC, ir_intr, sc, &sc->ih) !=3D 0){=0A= uprintf("Failed to init INT\n");=0A= }=0A= return 0;=0A= }=0A= =0A= static int=0A= ir_detach(device_t dev)=0A= {=0A= struct ir_softc *sc;=0A= =0A= sc =3D (struct ir_softc *) device_get_softc(dev);=0A= /* deactivate Interrupt Handler */=0A= bus_teardown_intr(dev, sc->irq, sc->ih) !=3D 0 );=0A= bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);=0A= =0A= =0A= /* release resources */=0A= bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->res);=0A= uprintf("IR Detach\n");=0A= return 0;=0A= }=0A= =0A= static device_method_t ir_methods[] =3D {=0A= /* Device interface */=0A= DEVMETHOD(device_identify, ir_identify),=0A= DEVMETHOD(device_probe, ir_probe),=0A= DEVMETHOD(device_attach, ir_attach),=0A= DEVMETHOD(device_detach, ir_detach),=0A= =0A= { 0, 0 }=0A= };=0A= =0A= static driver_t ir_driver =3D {=0A= "ir",=0A= ir_methods,=0A= sizeof(struct ir_softc),=0A= };=0A= =0A= static void ir_intr( void *p ){=0A= uprintf("GOT INTERUPT!\n");=0A= }=0A= =0A= void get_sio_status( struct ir_softc *sc ){=0A= u_int8_t old;=0A= =0A= uprintf("--------------------------------\n");=0A= /* Erstmal Bit 7 im LCR auf 0 um alle Register auszulesen,=0A= die dieses Bit auf 0 verlangen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,3);=0A= old &=3D ~128; /* Bit 7 ausnullen */=0A= bus_space_write_1(sc->bst, sc->bsh,3,(u_int8_t) old);=0A= =0A= /* RBR auslesen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,0);=0A= uprintf("RBR: %d\n", old);=0A= =0A= /* IER auslesen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,1);=0A= uprintf("IER: %d\n", old);=0A= =0A= /* Bit 7 im LCR wieder setzen, um Register abzufragen, die=0A= dieses Bit auf 1 brauchen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,3);=0A= old |=3D 128; /* Bit 7 setzen */=0A= bus_space_write_1(sc->bst, sc->bsh,3,(u_int8_t) old);=0A= =0A= /* DLL Register auslesen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,0);=0A= uprintf("DLL: %d\n", old);=0A= =0A= /* DLM Register auslesen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,1);=0A= uprintf("DLM: %d\n", old);=0A= =0A= /* Jetzt noch die Register, denen das Bit 7 wurscht ist. */=0A= /* IIR Register auslesen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,2);=0A= uprintf("IIR: %d\n", old);=0A= =0A= /* LCR Register auslesen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,3);=0A= uprintf("LCR: %d\n", old);=0A= =0A= /* MCR Register auslesen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,4);=0A= uprintf("MCR: %d\n", old);=0A= =0A= /* LSR Register auslesen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,5);=0A= uprintf("LSR: %d\n", old);=0A= =0A= /* DLM Register auslesen */=0A= old =3D bus_space_read_1(sc->bst, sc->bsh,6);=0A= uprintf("MSR: %d\n", old);=0A= uprintf("--------------------------------\n");=0A= }=0A= =0A= DRIVER_MODULE(ir, isa, ir_driver, ir_devclass, 0, 0);=0A= =0A= ------=_NextPart_000_0000_01C083CD.0EB2B120-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?NEBBIKIHMLCDHCFEOMAHOEKCCAAA.d_f0rce>