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