1101214Smarkm#!/bin/sh 222195Sjulian# This writes a skeleton driver and puts it into the kernel tree for you 322195Sjulian# 4161139Srik# arg1 is lowercase "foo" 5161139Srik# arg2 path to the kernel sources, "/sys" if omitted 6161139Srik# 722195Sjulian# Trust me, RUN THIS SCRIPT :) 822195Sjulian# 9101214Smarkm# $FreeBSD$ 10101214Smarkm# 1122195Sjulian#-------cut here------------------ 1222195Sjulian 13101214Smarkmif [ "${1}X" = "X" ] 1422195Sjulianthen 1522195Sjulian echo "Hey , how about some help here.. give me a device name!" 1622195Sjulian exit 1 1722195Sjulianfi 18161139Srikif [ "X${2}" = "X" ]; then 19161139Srik TOP=`cd /sys; pwd -P` 20161139Srik echo "Using ${TOP} as the path to the kernel sources!" 21161139Srikelse 22161139Srik TOP=${2} 23161139Srikfi 2422195Sjulian 25161139Srikfor i in "" "conf" "i386" "i386/conf" "dev" "sys" "modules" 26161139Srikdo 27161139Srik if [ -d ${TOP}/${i} ] 28161139Srik then 29161139Srik continue 30161139Srik fi 31161139Srik echo "${TOP}/${i}: no such directory." 32161139Srik echo "Please, correct the error and try again." 33161139Srik exit 1 34161139Srikdone 35161139Srik 36101214SmarkmUPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"` 37161139Srik 38161139Srikif [ -d ${TOP}/modules/${1} ]; then 39161139Srik echo "There appears to already be a module called ${1}" 40161139Srik echo -n "Should it be overwritten? [Y]" 41161139Srik read VAL 42161139Srik if [ "-z" "$VAL" ]; then 43161139Srik VAL=YES 44161139Srik fi 45161139Srik case ${VAL} in 46161139Srik [yY]*) 47161139Srik echo "Cleaning up from prior runs" 48161139Srik rm -rf ${TOP}/dev/${1} 49161139Srik rm -rf ${TOP}/modules/${1} 50161139Srik rm ${TOP}/conf/files.${UPPER} 51161139Srik rm ${TOP}/i386/conf/${UPPER} 52161139Srik rm ${TOP}/sys/${1}io.h 53161139Srik ;; 54161139Srik *) 55161139Srik exit 1 56161139Srik ;; 57161139Srik esac 58161139Srikfi 59161139Srik 60161139Srikecho "The following files will be created:" 61161139Srikecho ${TOP}/modules/${1} 62161139Srikecho ${TOP}/conf/files.${UPPER} 63161139Srikecho ${TOP}/i386/conf/${UPPER} 64161139Srikecho ${TOP}/dev/${1} 65161139Srikecho ${TOP}/dev/${1}/${1}.c 66161139Srikecho ${TOP}/sys/${1}io.h 67161139Srikecho ${TOP}/modules/${1} 68161139Srikecho ${TOP}/modules/${1}/Makefile 69161139Srik 70161139Srikmkdir ${TOP}/modules/${1} 71161139Srik 72161139Srikcat >${TOP}/conf/files.${UPPER} <<DONE 73161559Srikdev/${1}/${1}.c optional ${1} 7422195SjulianDONE 7522195Sjulian 76161139Srikcat >${TOP}/i386/conf/${UPPER} <<DONE 7722195Sjulian# Configuration file for kernel type: ${UPPER} 78101214Smarkm# \$FreeBSD\$ 7922195Sjulian 80161139Srikfiles "${TOP}/conf/files.${UPPER}" 8122195Sjulian 82161139Srikinclude GENERIC 83161139Srik 84161139Srikident ${UPPER} 85161139Srik 8622195Sjulian# trust me, you'll need this 87161139Srikoptions KDB 88161139Srikoptions DDB 89161139Srikdevice ${1} 9022195SjulianDONE 9122195Sjulian 92161139Srikif [ ! -d ${TOP}/dev/${1} ]; then 93161139Srik mkdir -p ${TOP}/dev/${1} 94161139Srikfi 95161139Srik 96161139Srikcat >${TOP}/dev/${1}/${1}.c <<DONE 9722195Sjulian/* 98161137Srik * Copyright (c) [year] [your name] 99161137Srik * All rights reserved. 10022195Sjulian * 101161137Srik * Redistribution and use in source and binary forms, with or without 102161137Srik * modification, are permitted provided that the following conditions 103161137Srik * are met: 104161137Srik * 1. Redistributions of source code must retain the above copyright 105161137Srik * notice, this list of conditions and the following disclaimer. 106161137Srik * 2. Redistributions in binary form must reproduce the above copyright 107161137Srik * notice, this list of conditions and the following disclaimer in the 108161137Srik * documentation and/or other materials provided with the distribution. 109161137Srik * 110161137Srik * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 111161137Srik * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 112161137Srik * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 113161137Srik * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 114161137Srik * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 115161137Srik * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 116161137Srik * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 117161137Srik * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 118161137Srik * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 119161137Srik * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 120161137Srik * SUCH DAMAGE. 121161137Srik * 12222195Sjulian * ${1} driver 12322195Sjulian */ 12422195Sjulian 125101214Smarkm#include <sys/cdefs.h> 126101214Smarkm__FBSDID("\$FreeBSD\$"); 12722195Sjulian 12822195Sjulian#include <sys/param.h> 12922195Sjulian#include <sys/systm.h> 13022195Sjulian#include <sys/kernel.h> /* SYSINIT stuff */ 131161137Srik#include <sys/uio.h> /* SYSINIT stuff */ 13222195Sjulian#include <sys/conf.h> /* cdevsw stuff */ 13322195Sjulian#include <sys/malloc.h> /* malloc region definitions */ 13486327Sarr#include <sys/proc.h> 13522195Sjulian#include <sys/${1}io.h> /* ${1} IOCTL definitions */ 13622195Sjulian 137101214Smarkm#include <machine/clock.h> /* DELAY() */ 13822195Sjulian 139161137Srik#define N${UPPER} 3 /* defines number of instances */ 14022195Sjulian 141161137Srik/* XXX These should be defined in terms of bus-space ops. */ 142161137Srik#define ${UPPER}_INB(port) inb(port) 143161137Srik#define ${UPPER}_OUTB(port, val) (port, (val)) 144161137Srik 14540592Sbde/* Function prototypes (these should all be static) */ 14622195Sjulianstatic d_open_t ${1}open; 14722195Sjulianstatic d_close_t ${1}close; 14822195Sjulianstatic d_read_t ${1}read; 14922195Sjulianstatic d_write_t ${1}write; 15022195Sjulianstatic d_ioctl_t ${1}ioctl; 15122195Sjulianstatic d_mmap_t ${1}mmap; 15232111Sjulianstatic d_poll_t ${1}poll; 153101214Smarkm 15422195Sjulian#define CDEV_MAJOR 20 15522195Sjulianstatic struct cdevsw ${1}_cdevsw = { 156161137Srik .d_version = D_VERSION, 157161137Srik .d_open = ${1}open, 158161137Srik .d_close = ${1}close, 159161137Srik .d_read = ${1}read, 160161137Srik .d_write = ${1}write, 161161137Srik .d_ioctl = ${1}ioctl, 162161137Srik .d_poll = ${1}poll, 163161137Srik .d_mmap = ${1}mmap, 164161137Srik .d_name = "${1}", 165101214Smarkm}; 166101214Smarkm 167101214Smarkm/* 168101214Smarkm * device specific Misc defines 16922195Sjulian */ 17022195Sjulian#define BUFFERSIZE 1024 171183416Sed#define UNIT(dev) dev2unit(dev) /* assume one minor number per unit */ 17222195Sjulian 17322195Sjulian/* 17422195Sjulian * One of these per allocated device 17522195Sjulian */ 17622195Sjulianstruct ${1}_softc { 177161137Srik u_long iobase; 17822195Sjulian char buffer[BUFFERSIZE]; 179161137Srik struct cdev *dev; 180101214Smarkm}; 18122195Sjulian 18222195Sjuliantypedef struct ${1}_softc *sc_p; 18322195Sjulian 18422195Sjulianstatic sc_p sca[N${UPPER}]; 18522195Sjulian 186101214Smarkm/* 18722195Sjulian * Macro to check that the unit number is valid 18822195Sjulian * Often this isn't needed as once the open() is performed, 18922195Sjulian * the unit number is pretty much safe.. The exception would be if we 19022195Sjulian * implemented devices that could "go away". in which case all these routines 19122195Sjulian * would be wise to check the number, DIAGNOSTIC or not. 19222195Sjulian */ 193101214Smarkm#define CHECKUNIT(RETVAL) \ 194101214Smarkmdo { /* the do-while is a safe way to do this grouping */ \ 195101214Smarkm if (unit > N${UPPER}) { \ 196143316Sstefanf printf("%s: bad unit %d\n", __func__, unit); \ 197101214Smarkm return (RETVAL); \ 198101214Smarkm } \ 199101214Smarkm if (scp == NULL) { \ 200143316Sstefanf printf("%s: unit %d not attached\n", __func__, unit); \ 201101214Smarkm return (RETVAL); \ 202101214Smarkm } \ 203101214Smarkm} while (0) 204101214Smarkm 20522195Sjulian#ifdef DIAGNOSTIC 20622195Sjulian#define CHECKUNIT_DIAG(RETVAL) CHECKUNIT(RETVAL) 20722195Sjulian#else /* DIAGNOSTIC */ 20822195Sjulian#define CHECKUNIT_DIAG(RETVAL) 20922195Sjulian#endif /* DIAGNOSTIC */ 21022195Sjulian 211101214Smarkmstatic int 212161137Srik${1}ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 21322195Sjulian{ 214101214Smarkm int unit = UNIT(dev); 21522195Sjulian sc_p scp = sca[unit]; 216101214Smarkm 21722195Sjulian CHECKUNIT_DIAG(ENXIO); 218101214Smarkm 21922195Sjulian switch (cmd) { 22022195Sjulian case DHIOCRESET: 22122195Sjulian /* whatever resets it */ 222161137Srik (void)scp; /* Delete this line after using scp. */ 223161137Srik#if 0 224161137Srik ${UPPER}_OUTB(scp->iobase, 0xff); 225161137Srik#endif 22622195Sjulian break; 22722195Sjulian default: 22822195Sjulian return ENXIO; 22922195Sjulian } 23022195Sjulian return (0); 231101214Smarkm} 232101214Smarkm 23322195Sjulian/* 23422195Sjulian * You also need read, write, open, close routines. 23522195Sjulian * This should get you started 23622195Sjulian */ 237101214Smarkmstatic int 238161137Srik${1}open(struct cdev *dev, int oflags, int devtype, struct thread *td) 23922195Sjulian{ 240101214Smarkm int unit = UNIT(dev); 24122195Sjulian sc_p scp = sca[unit]; 242101214Smarkm 24322195Sjulian CHECKUNIT(ENXIO); 24422195Sjulian 245161137Srik (void)scp; /* Delete this line after using scp. */ 246101214Smarkm /* 24722195Sjulian * Do processing 24822195Sjulian */ 24922195Sjulian return (0); 25022195Sjulian} 25122195Sjulian 252101214Smarkmstatic int 253161137Srik${1}close(struct cdev *dev, int fflag, int devtype, struct thread *td) 25422195Sjulian{ 255101214Smarkm int unit = UNIT(dev); 25622195Sjulian sc_p scp = sca[unit]; 257101214Smarkm 25822195Sjulian CHECKUNIT_DIAG(ENXIO); 25922195Sjulian 260161137Srik (void)scp; /* Delete this line after using scp. */ 261101214Smarkm /* 26222195Sjulian * Do processing 26322195Sjulian */ 26422195Sjulian return (0); 26522195Sjulian} 26622195Sjulian 267101214Smarkmstatic int 268161137Srik${1}read(struct cdev *dev, struct uio *uio, int ioflag) 26922195Sjulian{ 270101214Smarkm int unit = UNIT(dev); 27122195Sjulian sc_p scp = sca[unit]; 27222195Sjulian int toread; 273101214Smarkm 274101214Smarkm 27522195Sjulian CHECKUNIT_DIAG(ENXIO); 27622195Sjulian 277101214Smarkm /* 27822195Sjulian * Do processing 27922195Sjulian * read from buffer 28022195Sjulian */ 28122195Sjulian toread = (min(uio->uio_resid, sizeof(scp->buffer))); 28222195Sjulian return(uiomove(scp->buffer, toread, uio)); 28322195Sjulian} 28422195Sjulian 285101214Smarkmstatic int 286161137Srik${1}write(struct cdev *dev, struct uio *uio, int ioflag) 28722195Sjulian{ 288101214Smarkm int unit = UNIT(dev); 28922195Sjulian sc_p scp = sca[unit]; 29022195Sjulian int towrite; 291101214Smarkm 29222195Sjulian CHECKUNIT_DIAG(ENXIO); 29322195Sjulian 294101214Smarkm /* 29522195Sjulian * Do processing 29622195Sjulian * write to buffer 29722195Sjulian */ 29822195Sjulian towrite = (min(uio->uio_resid, sizeof(scp->buffer))); 29922195Sjulian return(uiomove(scp->buffer, towrite, uio)); 30022195Sjulian} 30122195Sjulian 302101214Smarkmstatic int 303161137Srik${1}mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot) 30422195Sjulian{ 305101214Smarkm int unit = UNIT(dev); 30622195Sjulian sc_p scp = sca[unit]; 307101214Smarkm 30822195Sjulian CHECKUNIT_DIAG(-1); 30922195Sjulian 310161137Srik (void)scp; /* Delete this line after using scp. */ 311101214Smarkm /* 31222195Sjulian * Do processing 31322195Sjulian */ 31422195Sjulian#if 0 /* if we had a frame buffer or whatever.. do this */ 31522195Sjulian if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) { 31622195Sjulian return (-1); 31722195Sjulian } 31822195Sjulian return i386_btop((FRAMEBASE + offset)); 31922195Sjulian#else 32022195Sjulian return (-1); 32122195Sjulian#endif 32222195Sjulian} 32322195Sjulian 324101214Smarkmstatic int 325161137Srik${1}poll(struct cdev *dev, int which, struct thread *td) 32622195Sjulian{ 327101214Smarkm int unit = UNIT(dev); 32822195Sjulian sc_p scp = sca[unit]; 329101214Smarkm 33022195Sjulian CHECKUNIT_DIAG(ENXIO); 33122195Sjulian 332161137Srik (void)scp; /* Delete this line after using scp. */ 333101214Smarkm /* 33422195Sjulian * Do processing 33522195Sjulian */ 33622195Sjulian return (0); /* this is the wrong value I'm sure */ 33722195Sjulian} 33822195Sjulian 33922195Sjulian/* 34022195Sjulian * Now for some driver initialisation. 34122195Sjulian * Occurs ONCE during boot (very early). 34222195Sjulian */ 343101214Smarkmstatic void 34422195Sjulian${1}_drvinit(void *unused) 34522195Sjulian{ 34622195Sjulian int unit; 347183272Sed sc_p scp; 34822195Sjulian 34922195Sjulian for (unit = 0; unit < N${UPPER}; unit++) { 350101214Smarkm /* 35122195Sjulian * Allocate storage for this instance . 35222195Sjulian */ 35386327Sarr scp = malloc(sizeof(*scp), M_DEVBUF, M_NOWAIT | M_ZERO); 35422195Sjulian if( scp == NULL) { 35522195Sjulian printf("${1}%d failed to allocate strorage\n", unit); 356101214Smarkm return; 35722195Sjulian } 35822195Sjulian sca[unit] = scp; 359161137Srik scp->dev = make_dev(&${1}_cdevsw, unit, 360161137Srik UID_ROOT, GID_KMEM, 0640, "${1}%d", unit); 36122195Sjulian } 36222195Sjulian} 36322195Sjulian 36422195SjulianSYSINIT(${1}dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+CDEV_MAJOR, 365183272Sed ${1}_drvinit, NULL); 36622195SjulianDONE 36722195Sjulian 368161139Srikcat >${TOP}/sys/${1}io.h <<DONE 36922195Sjulian/* 37022195Sjulian * Definitions needed to access the ${1} device (ioctls etc) 37122195Sjulian * see mtio.h , ioctl.h as examples 37222195Sjulian */ 37322195Sjulian#ifndef SYS_DHIO_H 37422195Sjulian#define SYS_DHIO_H 37522195Sjulian 37622195Sjulian#ifndef KERNEL 37722195Sjulian#include <sys/types.h> 37822195Sjulian#endif 37922195Sjulian#include <sys/ioccom.h> 38022195Sjulian 38122195Sjulian/* 38222195Sjulian * define an ioctl here 38322195Sjulian */ 38422195Sjulian#define DHIOCRESET _IO('D', 0) /* reset the ${1} device */ 38522195Sjulian#endif 38622195SjulianDONE 38722195Sjulian 388161139Srikif [ ! -d ${TOP}/modules/${1} ]; then 389161139Srik mkdir -p ${TOP}/modules/${1} 390161139Srikfi 39122195Sjulian 392161139Srikcat >${TOP}/modules/${1}/Makefile <<DONE 393161139Srik# ${UPPER} Loadable Kernel Module 394161139Srik# 395161139Srik# \$FreeBSD\$ 396161139Srik 397161139Srik.PATH: \${.CURDIR}/../../dev/${1} 398161139SrikKMOD = ${1} 399161139SrikSRCS = ${1}.c 400161139Srik 401161139Srik.include <bsd.kmod.mk> 402161139SrikDONE 403161139Srik 404161139Srikecho -n "Do you want to build the '${1}' module? [Y]" 405161139Srikread VAL 406161139Srikif [ "-z" "$VAL" ]; then 407161139Srik VAL=YES 408161139Srikfi 409161139Srikcase ${VAL} in 410161139Srik[yY]*) 411161139Srik (cd ${TOP}/modules/${1}; make depend; make ) 412161139Srik ;; 413161139Srik*) 414161139Srik# exit 415161139Srik ;; 416161139Srikesac 417161139Srik 418161139Srikecho "" 419161139Srikecho -n "Do you want to build the '${UPPER}' kernel? [Y]" 420161139Srikread VAL 421161139Srikif [ "-z" "$VAL" ]; then 422161139Srik VAL=YES 423161139Srikfi 424161139Srikcase ${VAL} in 425161139Srik[yY]*) 426161139Srik ( 427161139Srik cd ${TOP}/i386/conf; \ 428161139Srik config ${UPPER}; \ 429161139Srik cd ${TOP}/i386/compile/${UPPER}; \ 430161139Srik make depend; \ 431161139Srik make; \ 432161139Srik ) 433161139Srik ;; 434161139Srik*) 435161139Srik# exit 436161139Srik ;; 437161139Srikesac 438161139Srik 43922195Sjulian#--------------end of script--------------- 44022195Sjulian# 44122195Sjulian#edit to your taste.. 44222195Sjulian# 443101214Smarkm# 444