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