1#!/bin/sh 2# This writes a skeleton driver and puts it into the kernel tree for you 3#arg1 is lowercase "foo" 4# 5# Trust me, RUN THIS SCRIPT :) 6# 7#-------cut here------------------ 8cd /sys/i386/conf 9 10if [ "${1}X" = "X" ] 11then 12 echo "Hey , how about some help here.. give me a device name!" 13 exit 1 14fi 15 16UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"` 17cat >files.${UPPER} <<DONE 18dev/${1}.c optional ${1} device-driver 19DONE 20 21cat >${UPPER} <<DONE 22# Configuration file for kernel type: ${UPPER} 23ident ${UPPER} 24# \$FreeBSD$" 25DONE 26 27grep -v GENERIC < GENERIC >>${UPPER} 28 29cat >>${UPPER} <<DONE 30# trust me, you'll need this 31options DDB 32device ${1} 4 # might as well allow 4 of them 33DONE 34 35cat >../../dev/${1}.c <<DONE 36/* 37 * Copyright ME 38 * 39 * ${1} driver 40 * \$FreeBSD$ 41 */ 42 43 44#include "${1}.h" /* generated file.. defines N${UPPER} */ 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/kernel.h> /* SYSINIT stuff */ 48#include <sys/conf.h> /* cdevsw stuff */ 49#include <sys/malloc.h> /* malloc region definitions */ 50#include <sys/proc.h> 51#include <machine/clock.h> /* DELAY() */ 52#include <sys/${1}io.h> /* ${1} IOCTL definitions */ 53#ifdef DEVFS 54#include <sys/devfsext.h> /* DEVFS defintitions */ 55#endif /* DEVFS */ 56 57 58 59/* Function prototypes (these should all be static) */ 60static d_open_t ${1}open; 61static d_close_t ${1}close; 62static d_read_t ${1}read; 63static d_write_t ${1}write; 64static d_ioctl_t ${1}ioctl; 65static d_mmap_t ${1}mmap; 66static d_poll_t ${1}poll; 67 68#define CDEV_MAJOR 20 69static struct cdevsw ${1}_cdevsw = { 70 ${1}open, 71 ${1}close, 72 ${1}read, 73 ${1}write, 74 ${1}ioctl, 75 nullstop, 76 nullreset, 77 nodevtotty, 78 ${1}poll, 79 ${1}mmap, 80 NULL, 81 "${1}", 82 NULL, 83 -1 }; 84 85/* 86 * device specific Misc defines 87 */ 88#define BUFFERSIZE 1024 89#define UNIT(dev) minor(dev) /* assume one minor number per unit */ 90 91/* 92 * One of these per allocated device 93 */ 94struct ${1}_softc { 95 struct isa_device *dev; 96 char buffer[BUFFERSIZE]; 97#ifdef DEVFS 98 static void *devfs_token; 99#endif 100} ; 101 102typedef struct ${1}_softc *sc_p; 103 104static sc_p sca[N${UPPER}]; 105 106/* 107 * Macro to check that the unit number is valid 108 * Often this isn't needed as once the open() is performed, 109 * the unit number is pretty much safe.. The exception would be if we 110 * implemented devices that could "go away". in which case all these routines 111 * would be wise to check the number, DIAGNOSTIC or not. 112 */ 113#define CHECKUNIT(RETVAL) \ 114do { /* the do-while is a safe way to do this grouping */ \ 115 if (unit > N${UPPER}) { \ 116 printf(__FUNCTION__ ":bad unit %d\n", unit); \ 117 return (RETVAL); \ 118 } \ 119 if (scp == NULL) { \ 120 printf( __FUNCTION__ ": unit %d not attached\n", unit);\ 121 return (RETVAL); \ 122 } \ 123} while (0) 124#ifdef DIAGNOSTIC 125#define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL) 126#else /* DIAGNOSTIC */ 127#define CHECKUNIT_DIAG(RETVAL) 128#endif /* DIAGNOSTIC */ 129 130int ${1}ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct thread *td) 131{ 132 int unit = UNIT (dev); 133 sc_p scp = sca[unit]; 134 135 CHECKUNIT_DIAG(ENXIO); 136 137 switch (cmd) { 138 case DHIOCRESET: 139 /* whatever resets it */ 140 outb(scp->dev->id_iobase, 0xff); 141 break; 142 default: 143 return ENXIO; 144 } 145 return (0); 146} 147/* 148 * You also need read, write, open, close routines. 149 * This should get you started 150 */ 151static int 152${1}open(dev_t dev, int oflags, int devtype, struct thread *td) 153{ 154 int unit = UNIT (dev); 155 sc_p scp = sca[unit]; 156 157 CHECKUNIT(ENXIO); 158 159 /* 160 * Do processing 161 */ 162 return (0); 163} 164 165static int 166${1}close(dev_t dev, int fflag, int devtype, struct thread *td) 167{ 168 int unit = UNIT (dev); 169 sc_p scp = sca[unit]; 170 171 CHECKUNIT_DIAG(ENXIO); 172 173 /* 174 * Do processing 175 */ 176 return (0); 177} 178 179static int 180${1}read(dev_t dev, struct uio *uio, int ioflag) 181{ 182 int unit = UNIT (dev); 183 sc_p scp = sca[unit]; 184 int toread; 185 186 187 CHECKUNIT_DIAG(ENXIO); 188 189 /* 190 * Do processing 191 * read from buffer 192 */ 193 toread = (min(uio->uio_resid, sizeof(scp->buffer))); 194 return(uiomove(scp->buffer, toread, uio)); 195} 196 197static int 198${1}write(dev_t dev, struct uio *uio, int ioflag) 199{ 200 int unit = UNIT (dev); 201 sc_p scp = sca[unit]; 202 int towrite; 203 204 CHECKUNIT_DIAG(ENXIO); 205 206 /* 207 * Do processing 208 * write to buffer 209 */ 210 towrite = (min(uio->uio_resid, sizeof(scp->buffer))); 211 return(uiomove(scp->buffer, towrite, uio)); 212} 213 214static int 215${1}mmap(dev_t dev, int offset, int nprot) 216{ 217 int unit = UNIT (dev); 218 sc_p scp = sca[unit]; 219 220 CHECKUNIT_DIAG(-1); 221 222 /* 223 * Do processing 224 */ 225#if 0 /* if we had a frame buffer or whatever.. do this */ 226 if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) { 227 return (-1); 228 } 229 return i386_btop((FRAMEBASE + offset)); 230#else 231 return (-1); 232#endif 233} 234 235static int 236${1}poll(dev_t dev, int which, struct thread *td) 237{ 238 int unit = UNIT (dev); 239 sc_p scp = sca[unit]; 240 241 CHECKUNIT_DIAG(ENXIO); 242 243 /* 244 * Do processing 245 */ 246 return (0); /* this is the wrong value I'm sure */ 247} 248 249/* 250 * Now for some driver initialisation. 251 * Occurs ONCE during boot (very early). 252 */ 253static void 254${1}_drvinit(void *unused) 255{ 256 dev_t dev; 257 int unit; 258 sc_p scp = sca[unit]; 259 260 dev = makedev(CDEV_MAJOR, 0); 261 cdevsw_add(&dev, &${1}_cdevsw, NULL); 262 for (unit = 0; unit < N${UPPER}; unit++) { 263 /* 264 * Allocate storage for this instance . 265 */ 266 scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT | M_ZERO); 267 if( scp == NULL) { 268 printf("${1}%d failed to allocate strorage\n", unit); 269 return ; 270 } 271 sca[unit] = scp; 272#if DEVFS 273 scp->devfs_token = devfs_add_devswf(&${1}_cdevsw, unit, DV_CHR, 274 UID_ROOT, GID_KMEM, 0640, "${1}%d", unit); 275#endif 276 } 277} 278 279SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR, 280 ${1}_drvinit, NULL) 281 282 283DONE 284 285cat >../../sys/${1}io.h <<DONE 286/* 287 * Definitions needed to access the ${1} device (ioctls etc) 288 * see mtio.h , ioctl.h as examples 289 */ 290#ifndef SYS_DHIO_H 291#define SYS_DHIO_H 292 293#ifndef KERNEL 294#include <sys/types.h> 295#endif 296#include <sys/ioccom.h> 297 298/* 299 * define an ioctl here 300 */ 301#define DHIOCRESET _IO('D', 0) /* reset the ${1} device */ 302#endif 303DONE 304 305config ${UPPER} 306cd ../../compile/${UPPER} 307make depend 308make ${1}.o 309make 310exit 311 312#--------------end of script--------------- 313# 314#you also need to add an entry into the cdevsw[] 315#array in conf.c, but it's too hard to do in a script.. 316# 317#edit to your taste.. 318# 319# 320 321 322