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# It also creates a directory under /usr/src/lkm to help you create 6#loadable kernel modules, though without much use except for development. 7# 8# Trust me, RUN THIS SCRIPT :) 9# 10#-------cut here------------------ 11cd /sys/i386/conf 12 13if [ "${1}X" = "X" ] 14then 15 echo "Hey , how about some help here.. give me a device name!" 16 exit 1 17fi 18 19if [ -d /usr/src/lkm ] 20then 21 mkdir /usr/src/lkm/${1} 22fi 23 24UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"` 25cat >files.${UPPER} <<DONE 26i386/isa/${1}.c optional ${1} device-driver 27DONE 28 29cat >${UPPER} <<DONE 30# Configuration file for kernel type: ${UPPER} 31ident ${UPPER} 32# \$FreeBSD$" 33DONE 34 35grep -v GENERIC < GENERIC >>${UPPER} 36 37cat >>${UPPER} <<DONE 38# trust me, you'll need this 39options DDB 40device ${1}0 at isa? port 0x234 bio irq 5 41DONE 42 43cat >../isa/${1}.c <<DONE 44/* 45 * Copyright ME 46 * 47 * ${1} driver 48 * \$FreeBSD$ 49 */ 50 51 52#include "${1}.h" /* generated file.. defines N${UPPER} */ 53#include <sys/param.h> 54#include <sys/systm.h> 55#include <sys/kernel.h> /* SYSINIT stuff */ 56#include <sys/conf.h> /* cdevsw stuff */ 57#include <sys/malloc.h> /* malloc region definitions */ 58#include <machine/clock.h> /* DELAY() */ 59#include <i386/isa/isa.h> /* ISA bus port definitions etc. */ 60#include <i386/isa/isa_device.h>/* ISA bus configuration structures */ 61#include <sys/${1}io.h> /* ${1} IOCTL definitions */ 62#ifdef DEVFS 63#include <sys/devfsext.h> /* DEVFS defintitions */ 64#endif /* DEVFS */ 65 66 67 68/* Function prototypes (these should all be static) */ 69static d_open_t ${1}open; 70static d_close_t ${1}close; 71static d_read_t ${1}read; 72static d_write_t ${1}write; 73static d_ioctl_t ${1}ioctl; 74static d_mmap_t ${1}mmap; 75static d_poll_t ${1}poll; 76static int ${1}probe (struct isa_device *); 77static int ${1}attach (struct isa_device *); 78#ifdef ${UPPER}_MODULE 79static ointhand2_t ${1}intr; /* should actually have type inthand2_t */ 80#endif 81 82#define CDEV_MAJOR 20 83static struct cdevsw ${1}_cdevsw = { 84 ${1}open, 85 ${1}close, 86 ${1}read, 87 ${1}write, 88 ${1}ioctl, 89 nullstop, 90 nullreset, 91 nodevtotty, 92 ${1}poll, 93 ${1}mmap, 94 NULL, 95 "${1}", 96 NULL, 97 -1 }; 98 99struct isa_driver ${1}driver = { 100 ${1}probe, 101 ${1}attach, 102 "${1}" }; 103 104/* 105 * device specific Misc defines 106 */ 107#define BUFFERSIZE 1024 108#define NUMPORTS 4 109#define UNIT(dev) minor(dev) /* assume one minor number per unit */ 110 111/* 112 * One of these per allocated device 113 */ 114struct ${1}_softc { 115 struct isa_device *dev; 116 char buffer[BUFFERSIZE]; 117#ifdef DEVFS 118 static void *devfs_token; 119#endif 120} ; 121 122typedef struct ${1}_softc *sc_p; 123 124static sc_p sca[N${UPPER}]; 125 126/* add your own test to see if it exists */ 127/* should return the number of ports needed */ 128static int 129${1}probe (struct isa_device *dev) 130{ 131 char val; 132 int unit = dev->id_unit; 133 sc_p scp = sca[unit]; 134 135 /* 136 * Check the unit makes sense. 137 */ 138 if (unit > N${UPPER}) { 139 printf("bad unit (%d)\n", unit); 140 return (0); 141 } 142 if (scp) { 143 printf("unit %d already attached\n", unit); 144 return (0); 145 } 146 147 /* 148 * try see if the device is there. 149 */ 150 val = inb (dev->id_iobase); 151 if ( val != 42 ) { 152 return (0); 153 } 154 155 /* 156 * ok, we got one we think 157 * do some further (this time possibly destructive) tests. 158 */ 159 outb (dev->id_iobase, 0xff); 160 DELAY (10000); /* 10 ms delay */ 161 val = inb (dev->id_iobase) & 0x0f; 162 return ((val & 0x0f) == 0x0f)? NUMPORTS : 0 ; 163} 164 165/* 166 * Called if the probe succeeded. 167 * We can be destructive here as we know we have the device. 168 * we can also trust the unit number. 169 */ 170static int 171${1}attach (struct isa_device *dev) 172{ 173 int unit = dev->id_unit; 174 sc_p scp = sca[unit]; 175 176 /* 177 * Attach our interrupt handler to the device struct. Our caller 178 * will attach it to the hardware soon after we return. 179 */ 180 dev->id_ointr = ${1}intr; 181 182 /* 183 * Allocate storage for this instance . 184 */ 185 scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT); 186 if( scp == NULL) { 187 printf("${1}%d failed to allocage driver strorage\n", unit); 188 return (0); 189 } 190 bzero(scp, sizeof(*scp)); 191 sca[unit] = scp; 192 193 /* 194 * Store whatever seems wise. 195 */ 196 scp->dev = dev; 197#if DEVFS 198 scp->devfs_token = devfs_add_devswf(&${1}_cdevsw, unit, DV_CHR, 199 UID_ROOT, GID_KMEM, 0600, "${1}%d", unit); 200#endif 201 return 1; 202} 203 204/* 205 * Macro to check that the unit number is valid 206 * Often this isn't needed as once the open() is performed, 207 * the unit number is pretty much safe.. The exception would be if we 208 * implemented devices that could "go away". in which case all these routines 209 * would be wise to check the number, DIAGNOSTIC or not. 210 */ 211#define CHECKUNIT(RETVAL) \ 212do { /* the do-while is a safe way to do this grouping */ \ 213 if (unit > N${UPPER}) { \ 214 printf(__FUNCTION__ ":bad unit %d\n", unit); \ 215 return (RETVAL); \ 216 } \ 217 if (scp == NULL) { \ 218 printf( __FUNCTION__ ": unit %d not attached\n", unit);\ 219 return (RETVAL); \ 220 } \ 221} while (0) 222#ifdef DIAGNOSTIC 223#define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL) 224#else /* DIAGNOSTIC */ 225#define CHECKUNIT_DIAG(RETVAL) 226#endif /* DIAGNOSTIC */ 227 228static void 229${1}intr(int unit) 230{ 231 sc_p scp = sca[unit]; 232 233 /* 234 * well we got an interupt, now what? 235 * Theoretically we don't need to check the unit. 236 */ 237 return; 238} 239 240int ${1}ioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) 241{ 242 int unit = UNIT (dev); 243 sc_p scp = sca[unit]; 244 245 CHECKUNIT_DIAG(ENXIO); 246 247 switch (cmd) { 248 case DHIOCRESET: 249 /* whatever resets it */ 250 outb(scp->dev->id_iobase, 0xff); 251 break; 252 default: 253 return ENXIO; 254 } 255 return (0); 256} 257/* 258 * You also need read, write, open, close routines. 259 * This should get you started 260 */ 261static int 262${1}open(dev_t dev, int oflags, int devtype, struct proc *p) 263{ 264 int unit = UNIT (dev); 265 sc_p scp = sca[unit]; 266 267 CHECKUNIT(ENXIO); 268 269 /* 270 * Do processing 271 */ 272 return (0); 273} 274 275static int 276${1}close(dev_t dev, int fflag, int devtype, struct proc *p) 277{ 278 int unit = UNIT (dev); 279 sc_p scp = sca[unit]; 280 281 CHECKUNIT_DIAG(ENXIO); 282 283 /* 284 * Do processing 285 */ 286 return (0); 287} 288 289static int 290${1}read(dev_t dev, struct uio *uio, int ioflag) 291{ 292 int unit = UNIT (dev); 293 sc_p scp = sca[unit]; 294 int toread; 295 296 297 CHECKUNIT_DIAG(ENXIO); 298 299 /* 300 * Do processing 301 * read from buffer 302 */ 303 toread = (min(uio->uio_resid, sizeof(scp->buffer))); 304 return(uiomove(scp->buffer, toread, uio)); 305} 306 307static int 308${1}write(dev_t dev, struct uio *uio, int ioflag) 309{ 310 int unit = UNIT (dev); 311 sc_p scp = sca[unit]; 312 int towrite; 313 314 CHECKUNIT_DIAG(ENXIO); 315 316 /* 317 * Do processing 318 * write to buffer 319 */ 320 towrite = (min(uio->uio_resid, sizeof(scp->buffer))); 321 return(uiomove(scp->buffer, towrite, uio)); 322} 323 324static int 325${1}mmap(dev_t dev, int offset, int nprot) 326{ 327 int unit = UNIT (dev); 328 sc_p scp = sca[unit]; 329 330 CHECKUNIT_DIAG(-1); 331 332 /* 333 * Do processing 334 */ 335#if 0 /* if we had a frame buffer or whatever.. do this */ 336 if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) { 337 return (-1); 338 } 339 return i386_btop((FRAMEBASE + offset)); 340#else 341 return (-1); 342#endif 343} 344 345static int 346${1}poll(dev_t dev, int which, struct proc *p) 347{ 348 int unit = UNIT (dev); 349 sc_p scp = sca[unit]; 350 351 CHECKUNIT_DIAG(ENXIO); 352 353 /* 354 * Do processing 355 */ 356 return (0); /* this is the wrong value I'm sure */ 357} 358 359#ifndef ${UPPER}_MODULE 360 361/* 362 * Now for some driver initialisation. 363 * Occurs ONCE during boot (very early). 364 * This is if we are NOT a loadable module. 365 */ 366static void 367${1}_drvinit(void *unused) 368{ 369 dev_t dev; 370 371 dev = makedev(CDEV_MAJOR, 0); 372 cdevsw_add(&dev, &${1}_cdevsw, NULL); 373} 374 375SYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR, 376 ${1}_drvinit, NULL) 377 378#else /* ${UPPER}_MODULE */ 379/* Here is the support for if we ARE a loadable kernel module */ 380 381#include <sys/exec.h> 382#include <sys/sysent.h> 383#include <sys/lkm.h> 384 385MOD_DEV (${1}, LM_DT_CHAR, CDEV_MAJOR, &${1}_cdevsw); 386 387static struct isa_device dev = {0, &${1}driver, BASE_IO, IRQ, DMA, (caddr_t) PHYS_IO, PHYS_IO_SIZE, INT_INT, 0, FLAGS, 0, 0, 0, 0, 1, 0, 0}; 388 389static int 390${1}_load (struct lkm_table *lkmtp, int cmd) 391{ 392 if (${1}probe (&dev)) { 393 ${1}attach (&dev); 394 uprintf ("${1} driver loaded\n"); 395 uprintf ("${1}: interrupts not hooked\n"); 396 return 0; 397 } else { 398 uprintf ("${1} driver: probe failed\n"); 399 return 1; 400 } 401} 402 403static int 404${1}_unload (struct lkm_table *lkmtp, int cmd) 405{ 406 uprintf ("${1} driver unloaded\n"); 407 return 0; 408} 409 410static int 411${1}_stat (struct lkm_table *lkmtp, int cmd) 412{ 413 return 0; 414} 415 416int 417${1}_mod (struct lkm_table *lkmtp, int cmd, int ver) 418{ 419 MOD_DISPATCH(${1}, lkmtp, cmd, ver, 420 ${1}_load, ${1}_unload, ${1}_stat); 421} 422 423#endif /* ${UPPER}_MODULE */ 424 425DONE 426 427cat >../../sys/${1}io.h <<DONE 428/* 429 * Definitions needed to access the ${1} device (ioctls etc) 430 * see mtio.h , ioctl.h as examples 431 */ 432#ifndef SYS_DHIO_H 433#define SYS_DHIO_H 434 435#ifndef KERNEL 436#include <sys/types.h> 437#endif 438#include <sys/ioccom.h> 439 440/* 441 * define an ioctl here 442 */ 443#define DHIOCRESET _IO('D', 0) /* reset the ${1} device */ 444#endif 445DONE 446 447if [ -d /usr/src/lkm/${1} ] 448then 449 cat >/usr/src/lkm/${1}/Makefile <<DONE 450# ${UPPER} Loadable Kernel Module 451# 452# This happens not to work, actually. It's written for 453# a character ISA device driver, but they cannot be 454# be made into lkm's, because you have to hard code 455# everything you'll otherwise enter into the kernel 456# configuration file. 457 458.PATH: \${.CURDIR}/../../sys/i386/isa 459KMOD = ${1}_mod 460SRCS = ${1}.c ${1}.h 461 462CFLAGS += -I. -D${UPPER}_MODULE 463CLEANFILES += ${1}.h 464 465BASE_IO=0 # Base IO address 466IRQ=0 # IRQ number 467DMA=-1 # DMA channel 468PHYS_IO=0 # Physical IO Memory base address 469PHYS_IO_SIZE=0 # Physical IO Memory size 470INT_INT=0 # Interrupt interface 471FLAGS=0 # Flags 472 473CFLAGS+= -DBASE_IO=\${BASE_IO} -DIRQ=\${IRQ} -DDMA=\${DMA} -DPHYS_IO=\${PHYS_IO} -DPHYS_IO_SIZE=\${PHYS_IO_SIZE} -DINT_INT=\${INT_INT} -DFLAGS=\${FLAGS} 474 475${1}.h: 476 echo "#define N${UPPER} 1" > ${1}.h 477 478afterinstall: 479 \${INSTALL} -c -o \${BINOWN} -g \${BINGRP} -m \${BINMODE} \ 480 \${.CURDIR}/${1} \${DESTDIR}/usr/bin 481 482.include <bsd.kmod.mk> 483DONE 484fi 485 486config ${UPPER} 487cd ../../compile/${UPPER} 488make depend 489make ${1}.o 490make 491exit 492 493#--------------end of script--------------- 494# 495#edit to your taste.. 496# 497# 498 499 500 501 502