Skip site navigation (1)Skip section navigation (2)
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>