make_device_driver.sh revision 68533
1#!/bin/sh 2# This writes a skeleton driver and puts it into the kernel tree for you. 3# It also adds FOO and files.FOO configuration files so you can compile 4# a kernel with your FOO driver linked in. 5# To do so: 6# cd /sys/i386/conf; config FOO; cd ../../compile/FOO; make depend; make 7# 8# More interestingly, it creates a modules/foo directory 9# which it populates, to allow you to compile a FOO module 10# which can be lonked with your presently running kernel (if you feel brave). 11# To do so: 12# cd /sys/modules/foo; make depend; make; make install; kldload foo 13# 14# arg1 to this script is expected to be lowercase "foo" 15# 16# Trust me, RUN THIS SCRIPT :) 17# 18# $FreeBSD: head/share/examples/drivers/make_device_driver.sh 68533 2000-11-09 18:55:44Z julian $" 19# 20#-------cut here------------------ 21if [ "${1}X" = "X" ] 22then 23 echo "Hey , how about some help here.. give me a device name!" 24 exit 1 25fi 26UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"` 27 28HERE=`pwd` 29cd /sys 30TOP=`pwd` 31 32RCS_KEYWORD=FreeBSD 33 34if [ -d ${TOP}/modules/${1} ] 35then 36 echo "There appears to already be a module called ${1}" 37 echo -n "Should it be overwritten? [Y]" 38 read VAL 39 if [ "-z" "$VAL" ] 40 then 41 VAL=YES 42 fi 43 case ${VAL} in 44 [yY]*) 45 echo "Cleaning up from prior runs" 46 rm -rf ${TOP}/dev/${1} 47 rm -rf ${TOP}/modules/${1} 48 rm ${TOP}/i386/conf/files.${UPPER} 49 rm ${TOP}/i386/conf/${UPPER} 50 rm ${TOP}/sys/${1}io.h 51 ;; 52 *) 53 exit 1 54 ;; 55 esac 56fi 57 58echo "The following files will be created:" 59echo ${TOP}/modules/${1} 60echo ${TOP}/i386/conf/files.${UPPER} 61echo ${TOP}/i386/conf/${UPPER} 62echo ${TOP}/dev/${1} 63echo ${TOP}/dev/${1}/${1}.c 64echo ${TOP}/sys/${1}io.h 65echo ${TOP}/modules/${1} 66echo ${TOP}/modules/${1}/Makefile 67 68 69 mkdir ${TOP}/modules/${1} 70 71####################################################################### 72####################################################################### 73# 74# Create configuration information needed to create a kernel 75# containing this driver. 76# 77# Not really needed if we are going to do this as a module. 78####################################################################### 79# First add the file to a local file list. 80####################################################################### 81 82cat >${TOP}/i386/conf/files.${UPPER} <<DONE 83dev/${1}/${1}.c optional ${1} 84DONE 85 86####################################################################### 87# Then create a configuration file for a kernel that contains this driver. 88####################################################################### 89cat >${TOP}/i386/conf/${UPPER} <<DONE 90# Configuration file for kernel type: ${UPPER} 91ident ${UPPER} 92# \$${RCS_KEYWORD}: $ 93DONE 94 95grep -v GENERIC < /sys/i386/conf/GENERIC >>${TOP}/i386/conf/${UPPER} 96 97cat >>${TOP}/i386/conf/${UPPER} <<DONE 98options DDB # trust me, you'll need this 99device ${1} 100DONE 101 102if [ ! -d ${TOP}/dev/${1} ] 103then 104 mkdir -p ${TOP}/dev/${1} 105fi 106 107 108 109 110cat >${TOP}/dev/${1}/${1}.c <<DONE 111/* 112 * Copyright (c) [year] [your name] 113 * All rights reserved. 114 * 115 * Redistribution and use in source and binary forms, with or without 116 * modification, are permitted provided that the following conditions 117 * are met: 118 * 1. Redistributions of source code must retain the above copyright 119 * notice, this list of conditions and the following disclaimer. 120 * 2. Redistributions in binary form must reproduce the above copyright 121 * notice, this list of conditions and the following disclaimer in the 122 * documentation and/or other materials provided with the distribution. 123 * 124 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 125 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 126 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 127 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 128 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 129 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 130 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 131 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 132 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 133 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 134 * SUCH DAMAGE. 135 * 136 * 137 * ${1} driver 138 * \$${RCS_KEYWORD}: $ 139 */ 140 141/* 142 * http://www.daemonnews.org/200008/isa.html is required reading. 143 * hopefully it will make it's way into the handbook. 144 */ 145 146#include <sys/param.h> 147#include <sys/systm.h> 148#include <sys/conf.h> /* cdevsw stuff */ 149#include <sys/kernel.h> /* SYSINIT stuff */ 150#include <sys/uio.h> /* SYSINIT stuff */ 151#include <sys/malloc.h> /* malloc region definitions */ 152#include <sys/module.h> 153#include <sys/bus.h> 154#include <machine/bus.h> 155#include <machine/resource.h> 156#include <sys/rman.h> 157#include <sys/time.h> 158 159#include <isa/isavar.h> 160#include "isa_if.h" 161#include <sys/${1}io.h> /* ${1} IOCTL definitions */ 162 163/* XXX These should be defined in terms of bus-space ops */ 164#define ${UPPER}_INB(port) inb(port_start) 165#define ${UPPER}_OUTB(port, val) ( port_start, (val)) 166#define SOME_PORT 123 167#define EXPECTED_VALUE 0x42 168 169 170/* Function prototypes (these should all be static) */ 171static void ${1}_isa_identify (driver_t *, device_t); 172static int ${1}_isa_probe (device_t); 173static int ${1}_isa_attach (device_t); 174static int ${1}_isa_detach (device_t); 175static int ${1}_deallocate_resources(device_t device); 176static int ${1}_allocate_resources(device_t device); 177 178static d_open_t ${1}open; 179static d_close_t ${1}close; 180static d_read_t ${1}read; 181static d_write_t ${1}write; 182static d_ioctl_t ${1}ioctl; 183static d_mmap_t ${1}mmap; 184static d_poll_t ${1}poll; 185static void ${1}intr(void *arg); 186 187#define CDEV_MAJOR 20 188static struct cdevsw ${1}_cdevsw = { 189 /* open */ ${1}open, 190 /* close */ ${1}close, 191 /* read */ ${1}read, 192 /* write */ ${1}write, 193 /* ioctl */ ${1}ioctl, 194 /* poll */ ${1}poll, 195 /* mmap */ ${1}mmap, 196 /* strategy */ nostrategy, /* not a block type device */ 197 /* name */ "${1}", 198 /* maj */ CDEV_MAJOR, 199 /* dump */ nodump, /* not a block type device */ 200 /* psize */ nopsize, /* not a block type device */ 201 /* flags */ 0, 202 /* bmaj */ -1 203}; 204 205/* 206 * device specific Misc defines 207 */ 208#define BUFFERSIZE 1024 209#define NUMPORTS 4 210#define MEMSIZE (4 * 1024) /* imaginable h/w buffer size */ 211 212/* 213 * One of these per allocated device 214 */ 215struct ${1}_softc { 216 bus_space_tag_t bt; 217 bus_space_handle_t bh; 218 int rid_ioport; 219 int rid_memory; 220 int rid_irq; 221 int rid_drq; 222 struct resource* res_ioport; /* resource for port range */ 223 struct resource* res_memory; /* resource for mem range */ 224 struct resource* res_irq; /* resource for irq range */ 225 struct resource* res_drq; /* resource for dma channel */ 226 device_t device; 227 dev_t dev; 228 void *intr_cookie; 229 void *vaddr; /* Virtual address of mem resource */ 230 char buffer[BUFFERSIZE]; /* if we needed to buffer something */ 231} ; 232 233typedef struct ${1}_softc *sc_p; 234 235static devclass_t ${1}_devclass; 236 237static struct isa_pnp_id ${1}_ids[] = { 238 {0x12345678, "ABCco Widget"}, 239 {0xfedcba98, "shining moon Widget ripoff"}, 240 {0, NULL} 241}; 242 243static device_method_t ${1}_methods[] = { 244 DEVMETHOD(device_identify, ${1}_isa_identify), 245 DEVMETHOD(device_probe, ${1}_isa_probe), 246 DEVMETHOD(device_attach, ${1}_isa_attach), 247 DEVMETHOD(device_detach, ${1}_isa_detach), 248 { 0, 0 } 249}; 250 251static driver_t ${1}_isa_driver = { 252 "${1}", 253 ${1}_methods, 254 sizeof (struct ${1}_softc) 255}; 256 257DRIVER_MODULE(${1}, isa, ${1}_isa_driver, ${1}_devclass, 0, 0); 258 259/* 260 * Here list some port addresses we might expect our widget to appear at: 261 */ 262static struct localhints { 263 int ioport; 264 int irq; 265 int drq; 266 int mem; 267} res[] = { 268 { 0x210, 11, 2, 0xcd000}, 269 { 0x310, 12, 3, 0xdd000}, 270 { 0x320, 9, 6, 0xd4000}, 271 {0,0,0,0} 272}; 273 274#define MAXHINTS 10 /* just an arbitrary safty limit */ 275/* 276 * Called once when the driver is somehow connected with the bus, 277 * (Either linked in and the bus is started, or loaded as a module). 278 * 279 * The aim of this routine in an ISA driver is to add child entries to 280 * the parent bus so that it looks as if the devices were detected by 281 * some pnp-like method, or at least mentionned in the hints. 282 * 283 * For NON-PNP "dumb" devices: 284 * Add entries into the bus's list of likely devices, so that 285 * our 'probe routine' will be called for them. 286 * This is similar to what the 'hints' code achieves, except this is 287 * loadable with the driver. 288 * In the 'dumb' case we end up with more children than needed but 289 * some (or all) of them will fail probe() and only waste a little memory. 290 * 291 * For NON-PNP "Smart" devices: 292 * If the device has a NON-PNP way of being detected and setting/sensing 293 * the card, then do that here and add a child for each set of 294 * hardware found. 295 * 296 * For PNP devices: 297 * If the device is always PNP capable then this function can be removed. 298 * 299 * If the device is mentionned in the 'hints' file then this 300 * function can be removed. All devices mentionned in the hints 301 * file get added as children for probing, whether or not the 302 * driver is linked in. So even as a module it MAY still be there. 303 * See isa/isahint.c for hints being added in. 304 */ 305static void 306${1}_isa_identify (driver_t *driver, device_t parent) 307{ 308 u_int32_t irq=0; 309 u_int32_t ioport; 310 device_t child; 311 int i; 312 313 314 /* 315 * If we've already got ${UPPER} attached somehow, don't try again. 316 * Maybe it was in the hints file. or it was loaded before. 317 */ 318 if (device_find_child(parent, "${1}", 0)) { 319 printf("${UPPER}: already attached\n"); 320 return; 321 } 322/* XXX look at dev/acpica/acpi_isa.c for use of ISA_ADD_CONFIG() macro */ 323/* XXX What is ISA_SET_CONFIG_CALLBACK(parent, child, pnpbios_set_config, 0) ?*/ 324 for (i = 0; i < MAXHINTS; i++) { 325 if (((ioport = res[i].ioport) == 0) 326 && ((irq = res[i].irq) == 0)) { 327 return; /* we've added all our local hints */ 328 } 329 330 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "${1}", -1); 331 bus_set_resource(child, SYS_RES_IOPORT, 0, ioport, NUMPORTS); 332 bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); 333 bus_set_resource(child, SYS_RES_DRQ, 0, res[i].drq, 1); 334 bus_set_resource(child, SYS_RES_MEMORY, 0, res[i].mem, MEMSIZE); 335 336 337#if 0 338 /* 339 * If we wanted to pretend PNP found it 340 * we could do this, and put matching entries 341 * in the PNP table, but I think it's probably too hacky. 342 * As you see, some people have done it though. 343 * Basically EISA (remember that?) would do this I think 344 */ 345 isa_set_vendorid(child, PNP_EISAID("ESS1888")); 346 isa_set_logicalid(child, PNP_EISAID("ESS1888")); 347#endif 348 } 349#if 0 350 Do some smart probing (e.g. like the lnc driver) 351 and add a child for each one found. 352#endif 353 354 return; 355} 356/* 357 * The ISA code calls this for each device it knows about, 358 * whether via the PNP code or via the hints etc. 359 * If the device nas no PNP capabilities, remove all the 360 * PNP entries, but keep the call to ISA_PNP_PROBE() 361 * As it will guard against accidentally recognising 362 * foreign hardware. This is because we will be called to check against 363 * ALL PNP hardware. 364 */ 365static int 366${1}_isa_probe (device_t device) 367{ 368 int error; 369 device_t parent = device_get_parent(device); 370 sc_p scp = device_get_softc(device); 371 u_long port_start, port_count; 372 373 374 bzero(scp, sizeof(*scp)); 375 scp->device = device; 376 377 /* 378 * Check this device for a PNP match in our table.. 379 * There are several possible outcomes. 380 * error == 0 We match a PNP ). 381 * error == ENXIO, It is a PNP device but not in out table. 382 * error == ENOENT, I is not a PNP device.. try heuristic probes. 383 * -- logic from if_ed_isa.c, added info from isa/isa_if.m: 384 */ 385 error = ISA_PNP_PROBE(parent, device, ${1}_ids); 386 switch (error) { 387 case 0: 388 /* 389 * We found a PNP device. 390 * Do nothing, as it's all done in attach() 391 */ 392 break; 393 case ENOENT: 394 /* 395 * Well it didn't show up in the PNP tables 396 * so look directly at known ports (if we have any) 397 * in case we are looking for an old pre-PNP card. 398 * 399 * Hopefully the 'identify' routine will have picked these 400 * up for us first. 401 * 402 * The ports etc should come from a 'hints' section 403 * which is read in by code in isa/isahint.c 404 * and kern/subr_bus.c to create resource entries, 405 * or have been added by the 'identify routine above. 406 * 407 * First make a temporary resource reservation. 408 * If we can't get the resources we need then 409 * we need to abort. Possibly this indicates 410 * the resources were used by another device. 411 */ 412 if ((error = (${1}_allocate_resources(device)))) { 413 error = ENXIO; 414 goto errexit; 415 } 416 417 /* 418 * find out the values of any resources we 419 * need for our dumb probe. 420 */ 421 error = bus_get_resource(device, SYS_RES_IOPORT, 0, 422 &port_start, &port_count); 423 424 425 /* dummy heuristic type probe */ 426 if ( inb(port_start) != EXPECTED_VALUE) { 427 /* 428 * It isn't what we hoped, so quit looking for it. 429 */ 430 error = ENXIO; 431 } else { 432 u_long membase = bus_get_resource_start(device, 433 SYS_RES_MEMORY, 0 /*rid*/); 434 u_long memsize; 435 /* 436 * If we discover in some way that the device has 437 * XXX bytes of memory window, we can override 438 * or set the memory size in the child resource list. 439 */ 440 memsize = inb(port_start + 1) * 1024; /* for example */ 441 error = bus_set_resource(device, SYS_RES_MEMORY, 442 /*rid*/0, membase, memsize); 443 /* 444 * We found one.. 445 * Return -2 if we would LIKE the device 446 * Return -1 if we want it a lot 447 * Return 0 if we MUST get the device 448 * This allows drivers to 'bid' for a device. 449 */ 450 device_set_desc(device, "ACME Widget model 1234"); 451 error = 0; /* we really want it */ 452 } 453 /* 454 * Unreserve the resources for now because 455 * another driver may bid for device too. 456 * If we lose the bid, but still hold the resouces, we will 457 * effectively have diabled the other driver from getting them 458 * which will result in neither driver getting the device. 459 * We will ask for them again in attach if we win. 460 */ 461 ${1}_deallocate_resources(device); 462 break; 463 case ENXIO: 464 /* It was PNP but not ours, leave imediatly */ 465 default: 466 error = ENXIO; 467 } 468errexit: 469 return (error); 470} 471 472/* 473 * Called if the probe succeeded and our bid won the device. 474 * We can be destructive here as we know we have the device. 475 * This is the first place we can be sure we have a softc structure. 476 */ 477static int 478${1}_isa_attach (device_t device) 479{ 480 int unit = device_get_unit(device); 481 sc_p scp = device_get_softc(device); 482 device_t parent = device_get_parent(device); 483 484 scp->dev->si_drv1 = scp; 485 scp->dev = make_dev(&${1}_cdevsw, 0, 486 UID_ROOT, GID_OPERATOR, 0600, "${1}%d", unit); 487 488 if (${1}_allocate_resources(device)) { 489 goto errexit; 490 } 491 492 scp->bt = rman_get_bustag(scp->res_ioport); 493 scp->bh = rman_get_bushandle(scp->res_ioport); 494 495 /* register the interrupt handler */ 496 /* 497 * The type should be one of: 498 * INTR_TYPE_TTY 499 * (INTR_TYPE_TTY | INTR_TYPE_FAST) 500 * INTR_TYPE_BIO 501 * INTR_TYPE_CAM 502 * INTR_TYPE_NET 503 * INTR_TYPE_MISC 504 * This will probably change with SMPng. 505 */ 506 if (scp->res_irq) { 507 /* default to the tty mask for registration */ /* XXX */ 508 if (BUS_SETUP_INTR(parent, device, scp->res_irq, INTR_TYPE_TTY, 509 ${1}intr, scp, &scp->intr_cookie) == 0) { 510 /* do something if successfull */ 511 } 512 } 513 514 /* 515 * If we want to access the memory we will need 516 * to know where it was mapped. 517 */ 518 scp->vaddr = rman_get_virtual(scp->res_memory); 519 return 0; 520 521errexit: 522 /* 523 * Undo anything we may have done 524 */ 525 ${1}_isa_detach(device); 526 return (ENXIO); 527} 528 529static int 530${1}_isa_detach (device_t device) 531{ 532 sc_p scp = device_get_softc(device); 533 device_t parent = device_get_parent(device); 534 535 /* 536 * At this point stick a strong piece of wood into the device 537 * to make sure it is stopped safely. The alternative is to 538 * simply REFUSE to detach if it's busy. What you do depends on 539 * your specific situation. 540 */ 541 /* ZAP some register */ 542 543 /* 544 * Take our interrupt handler out of the list of handlers 545 * that can handle this irq. 546 */ 547 if (scp->intr_cookie != NULL) { 548 if (BUS_TEARDOWN_INTR(parent, device, 549 scp->res_irq, scp->intr_cookie) != 0) { 550 printf("intr teardown failed.. continuing\n"); 551 } 552 scp->intr_cookie = NULL; 553 } 554 555 /* 556 * deallocate any system resources we may have 557 * allocated on behalf of this driver. 558 */ 559 scp->vaddr = NULL; 560 return ${1}_deallocate_resources(device); 561} 562 563static int 564${1}_allocate_resources(device_t device) 565{ 566 int error; 567 sc_p scp = device_get_softc(device); 568 int size = 16; /* SIZE of port range used */ 569 570 scp->res_ioport = bus_alloc_resource(device, SYS_RES_IOPORT, 571 &scp->rid_ioport, 0ul, ~0ul, size, RF_ACTIVE); 572 if (scp->res_ioport == NULL) { 573 goto errexit; 574 } 575 576 scp->res_irq = bus_alloc_resource(device, SYS_RES_IRQ, 577 &scp->rid_irq, 0ul, ~0ul, 1, RF_SHAREABLE|RF_ACTIVE); 578 if (scp->res_irq == NULL) { 579 goto errexit; 580 } 581 582 scp->res_drq = bus_alloc_resource(device, SYS_RES_DRQ, 583 &scp->rid_drq, 0ul, ~0ul, 1, RF_ACTIVE); 584 if (scp->res_drq == NULL) { 585 goto errexit; 586 } 587 588 scp->res_memory = bus_alloc_resource(device, SYS_RES_MEMORY, 589 &scp->rid_memory, 0ul, ~0ul, MSIZE, RF_ACTIVE); 590 if (scp->res_memory == NULL) { 591 goto errexit; 592 } 593 return (0); 594 595errexit: 596 error = ENXIO; 597 /* cleanup anything we may have assigned. */ 598 ${1}_deallocate_resources(device); 599 return (ENXIO); /* for want of a better idea */ 600} 601 602static int 603${1}_deallocate_resources(device_t device) 604{ 605 sc_p scp = device_get_softc(device); 606 607 if (scp->res_irq != 0) { 608 bus_deactivate_resource(device, SYS_RES_IRQ, 609 scp->rid_irq, scp->res_irq); 610 bus_release_resource(device, SYS_RES_IRQ, 611 scp->rid_irq, scp->res_irq); 612 scp->res_irq = 0; 613 } 614 if (scp->res_ioport != 0) { 615 bus_deactivate_resource(device, SYS_RES_IOPORT, 616 scp->rid_ioport, scp->res_ioport); 617 bus_release_resource(device, SYS_RES_IOPORT, 618 scp->rid_ioport, scp->res_ioport); 619 scp->res_ioport = 0; 620 } 621 if (scp->res_ioport != 0) { 622 bus_deactivate_resource(device, SYS_RES_MEMORY, 623 scp->rid_memory, scp->res_memory); 624 bus_release_resource(device, SYS_RES_MEMORY, 625 scp->rid_memory, scp->res_memory); 626 scp->res_ioport = 0; 627 } 628 if (scp->res_drq != 0) { 629 bus_deactivate_resource(device, SYS_RES_DRQ, 630 scp->rid_drq, scp->res_drq); 631 bus_release_resource(device, SYS_RES_DRQ, 632 scp->rid_drq, scp->res_drq); 633 scp->res_drq = 0; 634 } 635 if (scp->dev) { 636 destroy_dev(scp->dev); 637 } 638 return (0); 639} 640 641static void 642${1}intr(void *arg) 643{ 644 sc_p scp = arg; 645 646 /* 647 * well we got an interupt, now what? 648 */ 649 return; 650} 651 652static int 653${1}ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 654{ 655 sc_p scp = dev->si_drv1; 656 657 switch (cmd) { 658 case DHIOCRESET: 659 /* whatever resets it */ 660#if 0 661 ${UPPER}_OUTB(SOME_PORT, 0xff) ; 662#endif 663 break; 664 default: 665 return ENXIO; 666 } 667 return (0); 668} 669/* 670 * You also need read, write, open, close routines. 671 * This should get you started 672 */ 673static int 674${1}open(dev_t dev, int oflags, int devtype, struct proc *p) 675{ 676 sc_p scp = dev->si_drv1; 677 678 /* 679 * Do processing 680 */ 681 return (0); 682} 683 684static int 685${1}close(dev_t dev, int fflag, int devtype, struct proc *p) 686{ 687 sc_p scp = dev->si_drv1; 688 689 /* 690 * Do processing 691 */ 692 return (0); 693} 694 695static int 696${1}read(dev_t dev, struct uio *uio, int ioflag) 697{ 698 sc_p scp = dev->si_drv1; 699 int toread; 700 701 702 /* 703 * Do processing 704 * read from buffer 705 */ 706 toread = (min(uio->uio_resid, sizeof(scp->buffer))); 707 return(uiomove(scp->buffer, toread, uio)); 708} 709 710static int 711${1}write(dev_t dev, struct uio *uio, int ioflag) 712{ 713 sc_p scp = dev->si_drv1; 714 int towrite; 715 716 /* 717 * Do processing 718 * write to buffer 719 */ 720 towrite = (min(uio->uio_resid, sizeof(scp->buffer))); 721 return(uiomove(scp->buffer, towrite, uio)); 722} 723 724static int 725${1}mmap(dev_t dev, vm_offset_t offset, int nprot) 726{ 727 sc_p scp = dev->si_drv1; 728 729 /* 730 * Given a byte offset into your device, return the PHYSICAL 731 * page number that it would map to. 732 */ 733#if 0 /* if we had a frame buffer or whatever.. do this */ 734 if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) { 735 return (-1); 736 } 737 return i386_btop((FRAMEBASE + offset)); 738#else 739 return (-1); 740#endif 741} 742 743static int 744${1}poll(dev_t dev, int which, struct proc *p) 745{ 746 sc_p scp = dev->si_drv1; 747 748 /* 749 * Do processing 750 */ 751 return (0); /* this is the wrong value I'm sure */ 752} 753 754DONE 755 756cat >${TOP}/sys/${1}io.h <<DONE 757/* 758 * Definitions needed to access the ${1} device (ioctls etc) 759 * see mtio.h , ioctl.h as examples 760 */ 761#ifndef SYS_DHIO_H 762#define SYS_DHIO_H 763 764#ifndef KERNEL 765#include <sys/types.h> 766#endif 767#include <sys/ioccom.h> 768 769/* 770 * define an ioctl here 771 */ 772#define DHIOCRESET _IO('D', 0) /* reset the ${1} device */ 773#endif 774DONE 775 776if [ ! -d ${TOP}/modules/${1} ] 777then 778 mkdir -p ${TOP}/modules/${1} 779fi 780 781cat >${TOP}/modules/${1}/Makefile <<DONE 782# ${UPPER} Loadable Kernel Module 783# 784# \$${RCS_KEYWORD}: $ 785 786.PATH: \${.CURDIR}/../../dev/${1} 787KMOD = ${1} 788SRCS = ${1}.c 789SRCS += opt_inet.h device_if.h bus_if.h pci_if.h isa_if.h 790 791# you may need to do this is your device is an if_xxx driver 792opt_inet.h: 793 echo "#define INET 1" > opt_inet.h 794 795.include <bsd.kmod.mk> 796DONE 797 798(cd ${TOP}/modules/${1}; make depend; make ) 799exit 800 801config ${UPPER} 802cd ../../compile/${UPPER} 803make depend 804make ${1}.o 805make 806exit 807 808#--------------end of script--------------- 809# 810#edit to your taste.. 811# 812# 813 814 815 816 817