15e176f9aSJulian Elischer#!/bin/sh 25e176f9aSJulian Elischer# This writes a skeleton driver and puts it into the kernel tree for you 35e176f9aSJulian Elischer#arg1 is lowercase "foo" 45e176f9aSJulian Elischer# 55e176f9aSJulian Elischer# Trust me, RUN THIS SCRIPT :) 65e176f9aSJulian Elischer# 75e176f9aSJulian Elischer#-------cut here------------------ 85e176f9aSJulian Elischercd /sys/i386/conf 95e176f9aSJulian Elischer 105e176f9aSJulian Elischerif [ "${1}X" = "X" ] 115e176f9aSJulian Elischerthen 125e176f9aSJulian Elischer echo "Hey , how about some help here.. give me a device name!" 135e176f9aSJulian Elischer exit 1 145e176f9aSJulian Elischerfi 155e176f9aSJulian Elischer 165e176f9aSJulian ElischerUPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"` 175e176f9aSJulian Elischercat >files.${UPPER} <<DONE 185e176f9aSJulian Elischeri386/isa/${1}.c optional ${1} device-driver 195e176f9aSJulian ElischerDONE 205e176f9aSJulian Elischer 215e176f9aSJulian Elischercat >${UPPER} <<DONE 225e176f9aSJulian Elischer# Configuration file for kernel type: ${UPPER} 235e176f9aSJulian Elischerident ${UPPER} 245e176f9aSJulian Elischer# \$Id:\$" 255e176f9aSJulian ElischerDONE 265e176f9aSJulian Elischer 275e176f9aSJulian Elischergrep -v GENERIC < GENERIC >>${UPPER} 285e176f9aSJulian Elischer 295e176f9aSJulian Elischercat >>${UPPER} <<DONE 305e176f9aSJulian Elischer# trust me, you'll need this 315e176f9aSJulian Elischeroptions DDB 325e176f9aSJulian Elischerdevice ${1}0 at isa? port 0x234 bio irq 5 vector ${1}intr 335e176f9aSJulian ElischerDONE 345e176f9aSJulian Elischer 355e176f9aSJulian Elischercat >../isa/${1}.c <<DONE 365e176f9aSJulian Elischer/* 375e176f9aSJulian Elischer * Copyright ME 385e176f9aSJulian Elischer * 395e176f9aSJulian Elischer * ${1} driver 405e176f9aSJulian Elischer * \$Id:\$ 415e176f9aSJulian Elischer */ 425e176f9aSJulian Elischer 435e176f9aSJulian Elischer 445e176f9aSJulian Elischer#include "${1}.h" /* generated file.. defines N${UPPER} */ 455e176f9aSJulian Elischer#include <sys/param.h> 465e176f9aSJulian Elischer#include <sys/systm.h> 475e176f9aSJulian Elischer#include <sys/kernel.h> /* SYSINIT stuff */ 485e176f9aSJulian Elischer#include <sys/conf.h> /* cdevsw stuff */ 495e176f9aSJulian Elischer#include <sys/malloc.h> /* malloc region definitions */ 505e176f9aSJulian Elischer#include <machine/clock.h> /* DELAY() */ 515e176f9aSJulian Elischer#include <i386/isa/isa.h> /* ISA bus port definitions etc. */ 525e176f9aSJulian Elischer#include <i386/isa/isa_device.h>/* ISA bus configuration structures */ 535e176f9aSJulian Elischer#include <sys/${1}io.h> /* ${1} IOCTL definitions */ 545e176f9aSJulian Elischer#ifdef DEVFS 555e176f9aSJulian Elischer#include <sys/devfsext.h> /* DEVFS defintitions */ 565e176f9aSJulian Elischer#endif /* DEVFS */ 575e176f9aSJulian Elischer 585e176f9aSJulian Elischer 595e176f9aSJulian Elischer 605e176f9aSJulian Elischer/* Function prototypes (these should all be static except for ${1}intr()) */ 615e176f9aSJulian Elischerstatic d_open_t ${1}open; 625e176f9aSJulian Elischerstatic d_close_t ${1}close; 635e176f9aSJulian Elischerstatic d_read_t ${1}read; 645e176f9aSJulian Elischerstatic d_write_t ${1}write; 655e176f9aSJulian Elischerstatic d_ioctl_t ${1}ioctl; 665e176f9aSJulian Elischerstatic d_mmap_t ${1}mmap; 675e176f9aSJulian Elischerstatic d_select_t ${1}select; 685e176f9aSJulian Elischerstatic int ${1}probe (struct isa_device *); 695e176f9aSJulian Elischerstatic int ${1}attach (struct isa_device *); 705e176f9aSJulian Elischer/* void ${1}intr(int unit);*//* actually defined in ioconf.h (generated file) */ 715e176f9aSJulian Elischer 725e176f9aSJulian Elischer#define CDEV_MAJOR 20 735e176f9aSJulian Elischerstatic struct cdevsw ${1}_cdevsw = { 745e176f9aSJulian Elischer ${1}open, 755e176f9aSJulian Elischer ${1}close, 765e176f9aSJulian Elischer ${1}read, 775e176f9aSJulian Elischer ${1}write, 785e176f9aSJulian Elischer ${1}ioctl, 795e176f9aSJulian Elischer nullstop, 805e176f9aSJulian Elischer nullreset, 815e176f9aSJulian Elischer nodevtotty, 825e176f9aSJulian Elischer ${1}select, 835e176f9aSJulian Elischer ${1}mmap, 845e176f9aSJulian Elischer NULL, 855e176f9aSJulian Elischer "${1}", 865e176f9aSJulian Elischer NULL, 875e176f9aSJulian Elischer -1 }; 885e176f9aSJulian Elischer 895e176f9aSJulian Elischerstruct isa_driver ${1}driver = { 905e176f9aSJulian Elischer ${1}probe, 915e176f9aSJulian Elischer ${1}attach, 925e176f9aSJulian Elischer "${1}" }; 935e176f9aSJulian Elischer 945e176f9aSJulian Elischer/* 955e176f9aSJulian Elischer * device specific Misc defines 965e176f9aSJulian Elischer */ 975e176f9aSJulian Elischer#define BUFFERSIZE 1024 985e176f9aSJulian Elischer#define NUMPORTS 4 995e176f9aSJulian Elischer#define UNIT(dev) minor(dev) /* assume one minor number per unit */ 1005e176f9aSJulian Elischer 1015e176f9aSJulian Elischer/* 1025e176f9aSJulian Elischer * One of these per allocated device 1035e176f9aSJulian Elischer */ 1045e176f9aSJulian Elischerstruct ${1}_softc { 1055e176f9aSJulian Elischer struct isa_device *dev; 1065e176f9aSJulian Elischer char buffer[BUFFERSIZE]; 1075e176f9aSJulian Elischer#ifdef DEVFS 1085e176f9aSJulian Elischer static void *devfs_token; 1095e176f9aSJulian Elischer#endif 1105e176f9aSJulian Elischer} ; 1115e176f9aSJulian Elischer 1125e176f9aSJulian Elischertypedef struct ${1}_softc *sc_p; 1135e176f9aSJulian Elischer 1145e176f9aSJulian Elischerstatic sc_p sca[N${UPPER}]; 1155e176f9aSJulian Elischer 1165e176f9aSJulian Elischer/* add your own test to see if it exists */ 1175e176f9aSJulian Elischer/* should return the number of ports needed */ 1185e176f9aSJulian Elischerstatic int 1195e176f9aSJulian Elischer${1}probe (struct isa_device *dev) 1205e176f9aSJulian Elischer{ 1215e176f9aSJulian Elischer char val; 1225e176f9aSJulian Elischer int unit = dev->id_unit; 1235e176f9aSJulian Elischer sc_p scp = sca[unit]; 1245e176f9aSJulian Elischer 1255e176f9aSJulian Elischer /* 1265e176f9aSJulian Elischer * Check the unit makes sense. 1275e176f9aSJulian Elischer */ 1285e176f9aSJulian Elischer if (unit > N${UPPER}) { 1295e176f9aSJulian Elischer printf("bad unit (%d)\n", unit); 1305e176f9aSJulian Elischer return (0); 1315e176f9aSJulian Elischer } 1325e176f9aSJulian Elischer if (scp) { 1335e176f9aSJulian Elischer printf("unit $d already attached\n", unit); 1345e176f9aSJulian Elischer return (0); 1355e176f9aSJulian Elischer } 1365e176f9aSJulian Elischer 1375e176f9aSJulian Elischer /* 1385e176f9aSJulian Elischer * try see if the device is there. 1395e176f9aSJulian Elischer */ 1405e176f9aSJulian Elischer val = inb (dev->id_iobase); 1415e176f9aSJulian Elischer if ( val != 42 ) { 1425e176f9aSJulian Elischer return (0); 1435e176f9aSJulian Elischer } 1445e176f9aSJulian Elischer 1455e176f9aSJulian Elischer /* 1465e176f9aSJulian Elischer * ok, we got one we think 1475e176f9aSJulian Elischer * do some further (this time possibly destructive) tests. 1485e176f9aSJulian Elischer */ 1495e176f9aSJulian Elischer outb (dev->id_iobase, 0xff); 1505e176f9aSJulian Elischer DELAY (10000); /* 10 ms delay */ 1515e176f9aSJulian Elischer val = inb (dev->id_iobase) & 0x0f; 1525e176f9aSJulian Elischer return ((val & 0x0f) == 0x0f)? NUMPORTS : 0 ; 1535e176f9aSJulian Elischer} 1545e176f9aSJulian Elischer 1555e176f9aSJulian Elischer/* 1565e176f9aSJulian Elischer * Called if the probe succeeded. 1575e176f9aSJulian Elischer * We can be destructive here as we know we have the device. 1585e176f9aSJulian Elischer * we can also trust the unit number. 1595e176f9aSJulian Elischer */ 1605e176f9aSJulian Elischerstatic int 1615e176f9aSJulian Elischer${1}attach (struct isa_device *dev) 1625e176f9aSJulian Elischer{ 1635e176f9aSJulian Elischer int unit = dev->id_unit; 1645e176f9aSJulian Elischer sc_p scp = sca[unit]; 1655e176f9aSJulian Elischer 1665e176f9aSJulian Elischer /* 1675e176f9aSJulian Elischer * Allocate storage for this instance . 1685e176f9aSJulian Elischer */ 1695e176f9aSJulian Elischer scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT); 1705e176f9aSJulian Elischer if( scp == NULL) { 1715e176f9aSJulian Elischer printf("${1}%d failed to allocage driver strorage\n", unit); 1725e176f9aSJulian Elischer return (0); 1735e176f9aSJulian Elischer } 1745e176f9aSJulian Elischer bzero(scp, sizeof(*scp)); 1755e176f9aSJulian Elischer sca[unit] = scp; 1765e176f9aSJulian Elischer 1775e176f9aSJulian Elischer /* 1785e176f9aSJulian Elischer * Store whatever seems wise. 1795e176f9aSJulian Elischer */ 1805e176f9aSJulian Elischer scp->dev = dev; 1815e176f9aSJulian Elischer#if DEVFS 1825e176f9aSJulian Elischer scp->devfs_token = devfs_add_devswf(&${1}_cdevsw, unit, DV_CHR, 1835e176f9aSJulian Elischer UID_ROOT, GID_KMEM, 0600, "${1}%d", unit); 1845e176f9aSJulian Elischer#endif 1855e176f9aSJulian Elischer return 1; 1865e176f9aSJulian Elischer} 1875e176f9aSJulian Elischer 1885e176f9aSJulian Elischer/* 1895e176f9aSJulian Elischer * Macro to check that the unit number is valid 1905e176f9aSJulian Elischer * Often this isn't needed as once the open() is performed, 1915e176f9aSJulian Elischer * the unit number is pretty much safe.. The exception would be if we 1925e176f9aSJulian Elischer * implemented devices that could "go away". in which case all these routines 1935e176f9aSJulian Elischer * would be wise to check the number, DIAGNOSTIC or not. 1945e176f9aSJulian Elischer */ 1955e176f9aSJulian Elischer#define CHECKUNIT(RETVAL) \ 1965e176f9aSJulian Elischerdo { /* the do-while is a safe way to do this grouping */ \ 1975e176f9aSJulian Elischer if (unit > N${UPPER}) { \ 1985e176f9aSJulian Elischer printf(__FUNCTION__ ":bad unit $d\n", unit); \ 1995e176f9aSJulian Elischer return (RETVAL); \ 2005e176f9aSJulian Elischer } \ 2015e176f9aSJulian Elischer if (scp == NULL) { \ 2025e176f9aSJulian Elischer printf( __FUNCTION__ ": unit $d not attached\n", unit);\ 2035e176f9aSJulian Elischer return (RETVAL); \ 2045e176f9aSJulian Elischer } \ 2055e176f9aSJulian Elischer} while (0) 2065e176f9aSJulian Elischer#ifdef DIAGNOSTIC 2075e176f9aSJulian Elischer#define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL) 2085e176f9aSJulian Elischer#else /* DIAGNOSTIC */ 2095e176f9aSJulian Elischer#define CHECKUNIT_DIAG(RETVAL) 2105e176f9aSJulian Elischer#endif /* DIAGNOSTIC */ 2115e176f9aSJulian Elischer 2125e176f9aSJulian Elischervoid 2135e176f9aSJulian Elischer${1}intr(int unit) 2145e176f9aSJulian Elischer{ 2155e176f9aSJulian Elischer sc_p scp = sca[unit]; 2165e176f9aSJulian Elischer 2175e176f9aSJulian Elischer /* 2185e176f9aSJulian Elischer * well we got an interupt, now what? 2195e176f9aSJulian Elischer * Theoretically we don't need to check the unit. 2205e176f9aSJulian Elischer */ 2215e176f9aSJulian Elischer return; 2225e176f9aSJulian Elischer} 2235e176f9aSJulian Elischer 2245e176f9aSJulian Elischerint ${1}ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) 2255e176f9aSJulian Elischer{ 2265e176f9aSJulian Elischer int unit = UNIT (dev); 2275e176f9aSJulian Elischer sc_p scp = sca[unit]; 2285e176f9aSJulian Elischer 2295e176f9aSJulian Elischer CHECKUNIT_DIAG(ENXIO); 2305e176f9aSJulian Elischer 2315e176f9aSJulian Elischer switch (cmd) { 2325e176f9aSJulian Elischer case DHIOCRESET: 2335e176f9aSJulian Elischer /* whatever resets it */ 2345e176f9aSJulian Elischer outb(scp->dev->id_iobase, 0xff); 2355e176f9aSJulian Elischer break; 2365e176f9aSJulian Elischer default: 2375e176f9aSJulian Elischer return ENXIO; 2385e176f9aSJulian Elischer } 2395e176f9aSJulian Elischer return (0); 2405e176f9aSJulian Elischer} 2415e176f9aSJulian Elischer/* 2425e176f9aSJulian Elischer * You also need read, write, open, close routines. 2435e176f9aSJulian Elischer * This should get you started 2445e176f9aSJulian Elischer */ 2455e176f9aSJulian Elischerstatic int 2465e176f9aSJulian Elischer${1}open(dev_t dev, int oflags, int devtype, struct proc *p) 2475e176f9aSJulian Elischer{ 2485e176f9aSJulian Elischer int unit = UNIT (dev); 2495e176f9aSJulian Elischer sc_p scp = sca[unit]; 2505e176f9aSJulian Elischer 2515e176f9aSJulian Elischer CHECKUNIT(ENXIO); 2525e176f9aSJulian Elischer 2535e176f9aSJulian Elischer /* 2545e176f9aSJulian Elischer * Do processing 2555e176f9aSJulian Elischer */ 2565e176f9aSJulian Elischer return (0); 2575e176f9aSJulian Elischer} 2585e176f9aSJulian Elischer 2595e176f9aSJulian Elischerstatic int 2605e176f9aSJulian Elischer${1}close(dev_t dev, int fflag, int devtype, struct proc *p) 2615e176f9aSJulian Elischer{ 2625e176f9aSJulian Elischer int unit = UNIT (dev); 2635e176f9aSJulian Elischer sc_p scp = sca[unit]; 2645e176f9aSJulian Elischer 2655e176f9aSJulian Elischer CHECKUNIT_DIAG(ENXIO); 2665e176f9aSJulian Elischer 2675e176f9aSJulian Elischer /* 2685e176f9aSJulian Elischer * Do processing 2695e176f9aSJulian Elischer */ 2705e176f9aSJulian Elischer return (0); 2715e176f9aSJulian Elischer} 2725e176f9aSJulian Elischer 2735e176f9aSJulian Elischerstatic int 2745e176f9aSJulian Elischer${1}read(dev_t dev, struct uio *uio, int ioflag) 2755e176f9aSJulian Elischer{ 2765e176f9aSJulian Elischer int unit = UNIT (dev); 2775e176f9aSJulian Elischer sc_p scp = sca[unit]; 2785e176f9aSJulian Elischer int toread; 2795e176f9aSJulian Elischer 2805e176f9aSJulian Elischer 2815e176f9aSJulian Elischer CHECKUNIT_DIAG(ENXIO); 2825e176f9aSJulian Elischer 2835e176f9aSJulian Elischer /* 2845e176f9aSJulian Elischer * Do processing 2855e176f9aSJulian Elischer * read from buffer 2865e176f9aSJulian Elischer */ 2875e176f9aSJulian Elischer toread = (min(uio->uio_resid, sizeof(scp->buffer))); 2885e176f9aSJulian Elischer return(uiomove(scp->buffer, toread, uio)); 2895e176f9aSJulian Elischer} 2905e176f9aSJulian Elischer 2915e176f9aSJulian Elischerstatic int 2925e176f9aSJulian Elischer${1}write(dev_t dev, struct uio *uio, int ioflag) 2935e176f9aSJulian Elischer{ 2945e176f9aSJulian Elischer int unit = UNIT (dev); 2955e176f9aSJulian Elischer sc_p scp = sca[unit]; 2965e176f9aSJulian Elischer int towrite; 2975e176f9aSJulian Elischer 2985e176f9aSJulian Elischer CHECKUNIT_DIAG(ENXIO); 2995e176f9aSJulian Elischer 3005e176f9aSJulian Elischer /* 3015e176f9aSJulian Elischer * Do processing 3025e176f9aSJulian Elischer * write to buffer 3035e176f9aSJulian Elischer */ 3045e176f9aSJulian Elischer towrite = (min(uio->uio_resid, sizeof(scp->buffer))); 3055e176f9aSJulian Elischer return(uiomove(scp->buffer, towrite, uio)); 3065e176f9aSJulian Elischer} 3075e176f9aSJulian Elischer 3085e176f9aSJulian Elischerstatic int 3095e176f9aSJulian Elischer${1}mmap(dev_t dev, int offset, int nprot) 3105e176f9aSJulian Elischer{ 3115e176f9aSJulian Elischer int unit = UNIT (dev); 3125e176f9aSJulian Elischer sc_p scp = sca[unit]; 3135e176f9aSJulian Elischer 3145e176f9aSJulian Elischer CHECKUNIT_DIAG(-1); 3155e176f9aSJulian Elischer 3165e176f9aSJulian Elischer /* 3175e176f9aSJulian Elischer * Do processing 3185e176f9aSJulian Elischer */ 3195e176f9aSJulian Elischer#if 0 /* if we had a frame buffer or whatever.. do this */ 3205e176f9aSJulian Elischer if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) { 3215e176f9aSJulian Elischer return (-1); 3225e176f9aSJulian Elischer } 3235e176f9aSJulian Elischer return i386_btop((FRAMEBASE + offset)); 3245e176f9aSJulian Elischer#else 3255e176f9aSJulian Elischer return (-1); 3265e176f9aSJulian Elischer#endif 3275e176f9aSJulian Elischer} 3285e176f9aSJulian Elischer 3295e176f9aSJulian Elischerstatic int 3305e176f9aSJulian Elischer${1}select(dev_t dev, int which, struct proc *p) 3315e176f9aSJulian Elischer{ 3325e176f9aSJulian Elischer int unit = UNIT (dev); 3335e176f9aSJulian Elischer sc_p scp = sca[unit]; 3345e176f9aSJulian Elischer 3355e176f9aSJulian Elischer CHECKUNIT_DIAG(ENXIO); 3365e176f9aSJulian Elischer 3375e176f9aSJulian Elischer /* 3385e176f9aSJulian Elischer * Do processing 3395e176f9aSJulian Elischer */ 3405e176f9aSJulian Elischer return (0); /* this is the wrong value I'm sure */ 3415e176f9aSJulian Elischer} 3425e176f9aSJulian Elischer 3435e176f9aSJulian Elischer/* 3445e176f9aSJulian Elischer * Now for some driver initialisation. 3455e176f9aSJulian Elischer * Occurs ONCE during boot (very early). 3465e176f9aSJulian Elischer */ 3475e176f9aSJulian Elischerstatic void 3485e176f9aSJulian Elischer${1}_drvinit(void *unused) 3495e176f9aSJulian Elischer{ 3505e176f9aSJulian Elischer dev_t dev; 3515e176f9aSJulian Elischer 3525e176f9aSJulian Elischer dev = makedev(CDEV_MAJOR, 0); 3535e176f9aSJulian Elischer cdevsw_add(&dev, &${1}_cdevsw, NULL); 3545e176f9aSJulian Elischer} 3555e176f9aSJulian Elischer 3565e176f9aSJulian ElischerSYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR, 3575e176f9aSJulian Elischer ${1}_drvinit, NULL) 3585e176f9aSJulian Elischer 3595e176f9aSJulian Elischer 3605e176f9aSJulian ElischerDONE 3615e176f9aSJulian Elischer 3625e176f9aSJulian Elischercat >../../sys/${1}io.h <<DONE 3635e176f9aSJulian Elischer/* 3645e176f9aSJulian Elischer * Definitions needed to access the ${1} device (ioctls etc) 3655e176f9aSJulian Elischer * see mtio.h , ioctl.h as examples 3665e176f9aSJulian Elischer */ 3675e176f9aSJulian Elischer#ifndef SYS_DHIO_H 3685e176f9aSJulian Elischer#define SYS_DHIO_H 3695e176f9aSJulian Elischer 3705e176f9aSJulian Elischer#ifndef KERNEL 3715e176f9aSJulian Elischer#include <sys/types.h> 3725e176f9aSJulian Elischer#endif 3735e176f9aSJulian Elischer#include <sys/ioccom.h> 3745e176f9aSJulian Elischer 3755e176f9aSJulian Elischer/* 3765e176f9aSJulian Elischer * define an ioctl here 3775e176f9aSJulian Elischer */ 3785e176f9aSJulian Elischer#define DHIOCRESET _IO('D', 0) /* reset the ${1} device */ 3795e176f9aSJulian Elischer#endif 3805e176f9aSJulian ElischerDONE 3815e176f9aSJulian Elischer 3825e176f9aSJulian Elischerconfig ${UPPER} 3835e176f9aSJulian Elischercd ../../compile/${UPPER} 3845e176f9aSJulian Elischermake depend 3855e176f9aSJulian Elischermake ${1}.o 3865e176f9aSJulian Elischermake 3875e176f9aSJulian Elischerexit 3885e176f9aSJulian Elischer 3895e176f9aSJulian Elischer#--------------end of script--------------- 3905e176f9aSJulian Elischer# 3915e176f9aSJulian Elischer#you also need to add an entry into the cdevsw[] 3925e176f9aSJulian Elischer#array in conf.c, but it's too hard to do in a script.. 3935e176f9aSJulian Elischer# 3945e176f9aSJulian Elischer#edit to your taste.. 3955e176f9aSJulian Elischer# 3965e176f9aSJulian Elischer# 3975e176f9aSJulian Elischer 3985e176f9aSJulian Elischer 3995e176f9aSJulian Elischer 4005e176f9aSJulian Elischer 401