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