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