diff options
-rwxr-xr-x | share/examples/drivers/make_device_driver.sh | 115 |
1 files changed, 93 insertions, 22 deletions
diff --git a/share/examples/drivers/make_device_driver.sh b/share/examples/drivers/make_device_driver.sh index a614c8e..98a2f73 100755 --- a/share/examples/drivers/make_device_driver.sh +++ b/share/examples/drivers/make_device_driver.sh @@ -141,9 +141,7 @@ static d_write_t ${1}write; static d_ioctl_t ${1}ioctl; static d_mmap_t ${1}mmap; static d_poll_t ${1}poll; -#ifdef ${UPPER}_MODULE -static ointhand2_t ${1}intr; /* should actually have type inthand2_t */ -#endif +static void ${1}intr(void *arg); #define CDEV_MAJOR 20 static struct cdevsw ${1}_cdevsw = { @@ -168,6 +166,7 @@ static struct cdevsw ${1}_cdevsw = { */ #define BUFFERSIZE 1024 #define NUMPORTS 4 +#define MEMSIZE 1024*1024 /* imaginable h/w buffer size */ /* * One of these per allocated device @@ -175,10 +174,17 @@ static struct cdevsw ${1}_cdevsw = { struct ${1}_softc { bus_space_tag_t bt; bus_space_handle_t bh; - int port_rid; - struct resource* port_res; /* resource for port range */ - dev_t dev; + int rid_ioport; + int rid_memory; + int rid_irq; + int rid_drq; + struct resource* res_ioport; /* resource for port range */ + struct resource* res_memory; /* resource for mem range */ + struct resource* res_irq; /* resource for irq range */ + struct resource* res_drq; /* resource for dma channel */ device_t device; + dev_t dev; + void *intr_cookie; char buffer[BUFFERSIZE]; } ; @@ -219,8 +225,10 @@ ${1}_isa_probe (device_t device) sc_p scp = device_get_softc(device); bus_space_handle_t bh; bus_space_tag_t bt; - struct resource *port_res; - int rid = 0; + struct resource* res_ioport; /* resource for port range */ + struct resource* res_memory; /* resource for mem range */ + struct resource* res_irq; /* resource for irq range */ + struct resource* res_drq; /* resource for dma channel */ int size = 16; /* SIZE of port range used */ @@ -255,31 +263,52 @@ ${1}_isa_probe (device_t device) * which is read in by code in isa/isahint.c */ - port_res = bus_alloc_resource(device, SYS_RES_IOPORT, &rid, - 0ul, ~0ul, size, RF_ACTIVE); - if (port_res == NULL) { + res_ioport = bus_alloc_resource(device, SYS_RES_IOPORT, + &scp->rid_ioport, 0ul, ~0ul, size, RF_ACTIVE); + if (res_ioport == NULL) { + error = ENXIO; + goto errexit; + } + res_irq = bus_alloc_resource(device, SYS_RES_IRQ, + &scp->rid_irq, 0ul, ~0ul, 1, RF_SHAREABLE); + if (res_irq == NULL) { + error = ENXIO; + goto errexit; + } + res_drq = bus_alloc_resource(device, SYS_RES_DRQ, + &scp->rid_drq, 0ul, ~0ul, 1, RF_ACTIVE); + if (res_drq == NULL) { + error = ENXIO; + goto errexit; + } + res_memory = bus_alloc_resource(device, SYS_RES_IOPORT, + &scp->rid_memory, 0ul, ~0ul, MSIZE, RF_ACTIVE); + if (res_memory == NULL) { error = ENXIO; - break; + goto errexit; } - scp->port_rid = rid; - scp->port_res = port_res; - scp->bt = bt = rman_get_bustag(port_res); - scp->bh = bh = rman_get_bushandle(port_res); + scp->res_ioport = res_ioport; + scp->res_memory = res_memory; + scp->res_drq = res_drq; + scp->res_irq = res_irq; + scp->bt = bt = rman_get_bustag(res_ioport); + scp->bh = bh = rman_get_bushandle(res_ioport); if ( ${UPPER}_INB(SOME_PORT) != EXPECTED_VALUE) { /* * It isn't what we expected, * so release everything and quit looking for it. */ - bus_release_resource(device, SYS_RES_IOPORT, - rid, port_res); - return (ENXIO); + goto errexit; } error = 0; break; case ENXIO: /* not ours, leave imediatly */ +errexit: + /* cleanup anything we may have assigned. */ + ${1}_isa_detach(device); default: error = ENXIO; } @@ -295,9 +324,18 @@ ${1}_isa_attach (device_t device) { int unit = device_get_unit(device); sc_p scp = device_get_softc(device); + device_t parent = device_get_parent(device); scp->dev = make_dev(&${1}_cdevsw, 0, 0, 0, 0600, "${1}%d", unit); scp->dev->si_drv1 = scp; + /* register the interrupt handler as default */ + if (scp->res_irq) { + /* default to the tty mask for registration */ /* XXX */ + if (BUS_SETUP_INTR(parent, device, scp->res_irq, INTR_TYPE_TTY, + ${1}intr, device, &scp->intr_cookie) == 0) { + /* do something if successfull */ + } + } return 0; } @@ -305,10 +343,43 @@ static int ${1}_isa_detach (device_t device) { sc_p scp = device_get_softc(device); + device_t parent = device_get_parent(device); - bus_release_resource(device, SYS_RES_IOPORT, - scp->port_rid, scp->port_res); - destroy_dev(scp->dev); + if (scp->res_irq != 0) { + if (BUS_TEARDOWN_INTR(parent, device, + scp->res_irq, scp->intr_cookie) != 0) { + printf("intr teardown failed.. continuing\n"); + } + bus_deactivate_resource(device, SYS_RES_IRQ, + scp->rid_irq, scp->res_irq); + bus_release_resource(device, SYS_RES_IRQ, + scp->rid_irq, scp->res_irq); + scp->res_irq = 0; + } + if (scp->res_ioport != 0) { + bus_deactivate_resource(device, SYS_RES_IOPORT, + scp->rid_ioport, scp->res_ioport); + bus_release_resource(device, SYS_RES_IOPORT, + scp->rid_ioport, scp->res_ioport); + scp->res_ioport = 0; + } + if (scp->res_ioport != 0) { + bus_deactivate_resource(device, SYS_RES_MEMORY, + scp->rid_memory, scp->res_memory); + bus_release_resource(device, SYS_RES_MEMORY, + scp->rid_memory, scp->res_memory); + scp->res_ioport = 0; + } + if (scp->res_drq != 0) { + bus_deactivate_resource(device, SYS_RES_DRQ, + scp->rid_drq, scp->res_drq); + bus_release_resource(device, SYS_RES_DRQ, + scp->rid_drq, scp->res_drq); + scp->res_drq = 0; + } + if (scp->dev) { + destroy_dev(scp->dev); + } return (0); } |