make_device_driver.sh revision 68748
1212795Sdim#!/bin/sh 2212795Sdim# This writes a skeleton driver and puts it into the kernel tree for you. 3212795Sdim# It also adds FOO and files.FOO configuration files so you can compile 4212795Sdim# a kernel with your FOO driver linked in. 5212795Sdim# To do so: 6212795Sdim# cd /sys/i386/conf; config FOO; cd ../../compile/FOO; make depend; make 7212795Sdim# 8212795Sdim# More interestingly, it creates a modules/foo directory 9212795Sdim# which it populates, to allow you to compile a FOO module 10212795Sdim# which can be lonked with your presently running kernel (if you feel brave). 11212795Sdim# To do so: 12212795Sdim# cd /sys/modules/foo; make depend; make; make install; kldload foo 13212795Sdim# 14212795Sdim# arg1 to this script is expected to be lowercase "foo" 15212795Sdim# 16212795Sdim# Trust me, RUN THIS SCRIPT :) 17212795Sdim# 18212795Sdim# $FreeBSD: head/share/examples/drivers/make_device_driver.sh 68748 2000-11-15 12:05:21Z julian $" 19212795Sdim# 20212795Sdim# 21212795Sdimif [ "${1}X" = "X" ] 22218893Sdimthen 23212795Sdim echo "Hey , how about some help here.. give me a device name!" 24212795Sdim exit 1 25212795Sdimfi 26212795SdimUPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"` 27212795Sdim 28212795SdimHERE=`pwd` 29212795Sdimcd /sys 30226633SdimTOP=`pwd` 31226633Sdim 32226633SdimRCS_KEYWORD=FreeBSD 33226633Sdim 34226633Sdimif [ -d ${TOP}/modules/${1} ] 35226633Sdimthen 36226633Sdim echo "There appears to already be a module called ${1}" 37212795Sdim echo -n "Should it be overwritten? [Y]" 38212795Sdim read VAL 39218893Sdim if [ "-z" "$VAL" ] 40226633Sdim then 41212795Sdim VAL=YES 42212795Sdim fi 43226633Sdim case ${VAL} in 44226633Sdim [yY]*) 45226633Sdim echo "Cleaning up from prior runs" 46212795Sdim rm -rf ${TOP}/dev/${1} 47212795Sdim rm -rf ${TOP}/modules/${1} 48212795Sdim rm ${TOP}/i386/conf/files.${UPPER} 49218893Sdim rm ${TOP}/i386/conf/${UPPER} 50212795Sdim rm ${TOP}/sys/${1}io.h 51212795Sdim ;; 52226633Sdim *) 53212795Sdim exit 1 54212795Sdim ;; 55212795Sdim esac 56212795Sdimfi 57212795Sdim 58212795Sdimecho "The following files will be created:" 59212795Sdimecho ${TOP}/modules/${1} 60212795Sdimecho ${TOP}/i386/conf/files.${UPPER} 61212795Sdimecho ${TOP}/i386/conf/${UPPER} 62212795Sdimecho ${TOP}/dev/${1} 63212795Sdimecho ${TOP}/dev/${1}/${1}.c 64218893Sdimecho ${TOP}/sys/${1}io.h 65226633Sdimecho ${TOP}/modules/${1} 66218893Sdimecho ${TOP}/modules/${1}/Makefile 67218893Sdim 68212795Sdim 69212795Sdim mkdir ${TOP}/modules/${1} 70212795Sdim 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 <machine/bus_pio.h> 157#include <machine/bus_memio.h> 158#include <sys/rman.h> 159#include <sys/time.h> 160 161#include <pci/pcireg.h> 162#include <pci/pcivar.h> 163 164#include <isa/isavar.h> 165#include "isa_if.h" 166#include <sys/${1}io.h> /* ${1} IOCTL definitions */ 167 168/* XXX These should be defined in terms of bus-space ops */ 169#define ${UPPER}_INB(port) inb(port_start) 170#define ${UPPER}_OUTB(port, val) ( port_start, (val)) 171#define SOME_PORT 123 172#define EXPECTED_VALUE 0x42 173 174/* 175 * device specific Misc defines 176 */ 177#define BUFFERSIZE 1024 178#define NUMPORTS 4 179#define MEMSIZE (4 * 1024) /* imaginable h/w buffer size */ 180 181/* 182 * One of these per allocated device 183 */ 184struct ${1}_softc { 185 bus_space_tag_t bt; 186 bus_space_handle_t bh; 187 int rid_ioport; 188 int rid_memory; 189 int rid_irq; 190 int rid_drq; 191 struct resource* res_ioport; /* resource for port range */ 192 struct resource* res_memory; /* resource for mem range */ 193 struct resource* res_irq; /* resource for irq range */ 194 struct resource* res_drq; /* resource for dma channel */ 195 device_t device; 196 dev_t dev; 197 void *intr_cookie; 198 void *vaddr; /* Virtual address of mem resource */ 199 char buffer[BUFFERSIZE]; /* if we needed to buffer something */ 200} ; 201 202typedef struct ${1}_softc *sc_p; 203 204 205/* Function prototypes (these should all be static) */ 206static int ${1}_deallocate_resources(device_t device); 207static int ${1}_allocate_resources(device_t device); 208static int ${1}_attach(device_t device, sc_p scp); 209static int ${1}_detach(device_t device, sc_p scp); 210 211static d_open_t ${1}open; 212static d_close_t ${1}close; 213static d_read_t ${1}read; 214static d_write_t ${1}write; 215static d_ioctl_t ${1}ioctl; 216static d_mmap_t ${1}mmap; 217static d_poll_t ${1}poll; 218static void ${1}intr(void *arg); 219 220#define CDEV_MAJOR 20 221static struct cdevsw ${1}_cdevsw = { 222 /* open */ ${1}open, 223 /* close */ ${1}close, 224 /* read */ ${1}read, 225 /* write */ ${1}write, 226 /* ioctl */ ${1}ioctl, 227 /* poll */ ${1}poll, 228 /* mmap */ ${1}mmap, 229 /* strategy */ nostrategy, /* not a block type device */ 230 /* name */ "${1}", 231 /* maj */ CDEV_MAJOR, 232 /* dump */ nodump, /* not a block type device */ 233 /* psize */ nopsize, /* not a block type device */ 234 /* flags */ 0, 235 /* bmaj */ -1 236}; 237 238static devclass_t ${1}_devclass; 239 240/*****************************************\ 241* ISA Attachment structures and functions 242\*****************************************/ 243static void ${1}_isa_identify (driver_t *, device_t); 244static int ${1}_isa_probe (device_t); 245static int ${1}_isa_attach (device_t); 246static int ${1}_isa_detach (device_t); 247 248static struct isa_pnp_id ${1}_ids[] = { 249 {0x12345678, "ABCco Widget"}, 250 {0xfedcba98, "shining moon Widget ripoff"}, 251 {0, NULL} 252}; 253 254static device_method_t ${1}_methods[] = { 255 DEVMETHOD(device_identify, ${1}_isa_identify), 256 DEVMETHOD(device_probe, ${1}_isa_probe), 257 DEVMETHOD(device_attach, ${1}_isa_attach), 258 DEVMETHOD(device_detach, ${1}_isa_detach), 259 { 0, 0 } 260}; 261 262static driver_t ${1}_isa_driver = { 263 "${1}", 264 ${1}_methods, 265 sizeof (struct ${1}_softc) 266}; 267 268 269DRIVER_MODULE(${1}, isa, ${1}_isa_driver, ${1}_devclass, 0, 0); 270 271/* 272 * Here list some port addresses we might expect our widget to appear at: 273 */ 274static struct localhints { 275 int ioport; 276 int irq; 277 int drq; 278 int mem; 279} res[] = { 280 { 0x210, 11, 2, 0xcd000}, 281 { 0x310, 12, 3, 0xdd000}, 282 { 0x320, 9, 6, 0xd4000}, 283 {0,0,0,0} 284}; 285 286#define MAXHINTS 10 /* just an arbitrary safty limit */ 287/* 288 * Called once when the driver is somehow connected with the bus, 289 * (Either linked in and the bus is started, or loaded as a module). 290 * 291 * The aim of this routine in an ISA driver is to add child entries to 292 * the parent bus so that it looks as if the devices were detected by 293 * some pnp-like method, or at least mentionned in the hints. 294 * 295 * For NON-PNP "dumb" devices: 296 * Add entries into the bus's list of likely devices, so that 297 * our 'probe routine' will be called for them. 298 * This is similar to what the 'hints' code achieves, except this is 299 * loadable with the driver. 300 * In the 'dumb' case we end up with more children than needed but 301 * some (or all) of them will fail probe() and only waste a little memory. 302 * 303 * For NON-PNP "Smart" devices: 304 * If the device has a NON-PNP way of being detected and setting/sensing 305 * the card, then do that here and add a child for each set of 306 * hardware found. 307 * 308 * For PNP devices: 309 * If the device is always PNP capable then this function can be removed. 310 * 311 * If the device is mentionned in the 'hints' file then this 312 * function can be removed. All devices mentionned in the hints 313 * file get added as children for probing, whether or not the 314 * driver is linked in. So even as a module it MAY still be there. 315 * See isa/isahint.c for hints being added in. 316 */ 317static void 318${1}_isa_identify (driver_t *driver, device_t parent) 319{ 320 u_int32_t irq=0; 321 u_int32_t ioport; 322 device_t child; 323 int i; 324 325 326 /* 327 * If we've already got ${UPPER} attached somehow, don't try again. 328 * Maybe it was in the hints file. or it was loaded before. 329 */ 330 if (device_find_child(parent, "${1}", 0)) { 331 printf("${UPPER}: already attached\n"); 332 return; 333 } 334/* XXX look at dev/acpica/acpi_isa.c for use of ISA_ADD_CONFIG() macro */ 335/* XXX What is ISA_SET_CONFIG_CALLBACK(parent, child, pnpbios_set_config, 0) ?*/ 336 for (i = 0; i < MAXHINTS; i++) { 337 338 ioport = res[i].ioport; 339 irq = res[i].irq; 340 if ((ioport == 0) && (irq == 0)) { 341 return; /* we've added all our local hints */ 342 } 343 344 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "${1}", -1); 345 bus_set_resource(child, SYS_RES_IOPORT, 0, ioport, NUMPORTS); 346 bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); 347 bus_set_resource(child, SYS_RES_DRQ, 0, res[i].drq, 1); 348 bus_set_resource(child, SYS_RES_MEMORY, 0, res[i].mem, MEMSIZE); 349 350 351#if 0 352 /* 353 * If we wanted to pretend PNP found it 354 * we could do this, and put matching entries 355 * in the PNP table, but I think it's probably too hacky. 356 * As you see, some people have done it though. 357 * Basically EISA (remember that?) would do this I think 358 */ 359 isa_set_vendorid(child, PNP_EISAID("ESS1888")); 360 isa_set_logicalid(child, PNP_EISAID("ESS1888")); 361#endif 362 } 363#if 0 364 Do some smart probing (e.g. like the lnc driver) 365 and add a child for each one found. 366#endif 367 368 return; 369} 370/* 371 * The ISA code calls this for each device it knows about, 372 * whether via the PNP code or via the hints etc. 373 * If the device nas no PNP capabilities, remove all the 374 * PNP entries, but keep the call to ISA_PNP_PROBE() 375 * As it will guard against accidentally recognising 376 * foreign hardware. This is because we will be called to check against 377 * ALL PNP hardware. 378 */ 379static int 380${1}_isa_probe (device_t device) 381{ 382 int error; 383 device_t parent = device_get_parent(device); 384 sc_p scp = device_get_softc(device); 385 u_long port_start, port_count; 386 387 388 bzero(scp, sizeof(*scp)); 389 scp->device = device; 390 391 /* 392 * Check this device for a PNP match in our table.. 393 * There are several possible outcomes. 394 * error == 0 We match a PNP ). 395 * error == ENXIO, It is a PNP device but not in out table. 396 * error == ENOENT, I is not a PNP device.. try heuristic probes. 397 * -- logic from if_ed_isa.c, added info from isa/isa_if.m: 398 * 399 * If we had a list of devices that we could handle really well, 400 * and a list which we could handle only basic functions, then 401 * we would call this twice, once for each list, 402 * and return a value of '-2' or something if we could 403 * only handle basic functions. This would allow a specific 404 * Widgetplus driver to make a better offer if it knows how to 405 * do all the extended functions. (see non-pnp part for more info) 406 */ 407 error = ISA_PNP_PROBE(parent, device, ${1}_ids); 408 switch (error) { 409 case 0: 410 /* 411 * We found a PNP device. 412 * Do nothing, as it's all done in attach() 413 */ 414 break; 415 case ENOENT: 416 /* 417 * Well it didn't show up in the PNP tables 418 * so look directly at known ports (if we have any) 419 * in case we are looking for an old pre-PNP card. 420 * 421 * Hopefully the 'identify' routine will have picked these 422 * up for us first if they use some proprietary detection 423 * method. 424 * 425 * The ports, irqs etc should come from a 'hints' section 426 * which is read in by code in isa/isahint.c 427 * and kern/subr_bus.c to create resource entries, 428 * or have been added by the 'identify routine above. 429 * Note that HINTS based resourse requests have NO 430 * SIZE for the memory or ports requests (just a base) 431 * so we may need to 'correct' this before we 432 * do any probing. 433 */ 434 /* 435 * find out the values of any resources we 436 * need for our dumb probe. Also check we have enough ports 437 * in the request. (could be hints based). 438 * Should probably do the same for memory regions too. 439 */ 440 error = bus_get_resource(device, SYS_RES_IOPORT, 0, 441 &port_start, &port_count); 442 if (port_count != NUMPORTS) { 443 bus_set_resource(device, SYS_RES_IOPORT, 0, 444 port_start, NUMPORTS); 445 } 446 447 /* 448 * Make a temporary resource reservation. 449 * If we can't get the resources we need then 450 * we need to abort. Possibly this indicates 451 * the resources were used by another device 452 * in which case the probe would have failed anyhow. 453 */ 454 if ((error = (${1}_allocate_resources(device)))) { 455 error = ENXIO; 456 goto errexit; 457 } 458 459 /* dummy heuristic type probe */ 460 if ( inb(port_start) != EXPECTED_VALUE) { 461 /* 462 * It isn't what we hoped, so quit looking for it. 463 */ 464 error = ENXIO; 465 } else { 466 u_long membase = bus_get_resource_start(device, 467 SYS_RES_MEMORY, 0 /*rid*/); 468 u_long memsize; 469 /* 470 * If we discover in some way that the device has 471 * XXX bytes of memory window, we can override 472 * or set the memory size in the child resource list. 473 */ 474 memsize = inb(port_start + 1) * 1024; /* for example */ 475 error = bus_set_resource(device, SYS_RES_MEMORY, 476 /*rid*/0, membase, memsize); 477 /* 478 * We found one, return non-positive numbers.. 479 * Return -N if we cant handle it, but not well. 480 * Return -2 if we would LIKE the device 481 * Return -1 if we want it a lot 482 * Return 0 if we MUST get the device 483 * This allows drivers to 'bid' for a device. 484 */ 485 device_set_desc(device, "ACME Widget model 1234"); 486 error = -1; /* we want it but someone else 487 may be even better */ 488 } 489 /* 490 * Unreserve the resources for now because 491 * another driver may bid for device too. 492 * If we lose the bid, but still hold the resouces, we will 493 * effectively have diabled the other driver from getting them 494 * which will result in neither driver getting the device. 495 * We will ask for them again in attach if we win. 496 */ 497 ${1}_deallocate_resources(device); 498 break; 499 case ENXIO: 500 /* It was PNP but not ours, leave imediatly */ 501 default: 502 error = ENXIO; 503 } 504errexit: 505 return (error); 506} 507 508/* 509 * Called if the probe succeeded and our bid won the device. 510 * We can be destructive here as we know we have the device. 511 * This is the first place we can be sure we have a softc structure. 512 * You would do ISA specific attach things here, but generically there aren't 513 * any (yey new-bus!). 514 */ 515static int 516${1}_isa_attach (device_t device) 517{ 518 sc_p scp = device_get_softc(device); 519 int error; 520 521 error = ${1}_attach(device, scp); 522 if (error) { 523 ${1}_isa_detach(device); 524 } 525 return (error); 526 527} 528 529/* 530 * detach the driver (e.g. module unload) 531 * call the bus independent version 532 * and undo anything we did in the ISA attach routine. 533 */ 534static int 535${1}_isa_detach (device_t device) 536{ 537 sc_p scp = device_get_softc(device); 538 int error; 539 540 error = ${1}_detach(device, scp); 541 return (error); 542} 543 544/***************************************\ 545* PCI Attachment structures and code * 546\***************************************/ 547 548static int ${1}_pci_probe __P((device_t)); 549static int ${1}_pci_attach __P((device_t)); 550static int ${1}_pci_detach __P((device_t)); 551 552static device_method_t ${1}_pci_methods[] = { 553 /* Device interface */ 554 DEVMETHOD(device_probe, ${1}_pci_probe), 555 DEVMETHOD(device_attach, ${1}_pci_attach), 556 DEVMETHOD(device_detach, ${1}_pci_detach), 557 { 0, 0 } 558}; 559 560static driver_t ${1}_pci_driver = { 561 "${1}", 562 ${1}_pci_methods, 563 sizeof(struct ${1}_softc), 564}; 565 566 567DRIVER_MODULE(${1}, pci, ${1}_pci_driver, ${1}_devclass, 0, 0); 568 569static struct _pcsid 570{ 571 u_int32_t type; 572 const char *desc; 573} pci_ids[] = { 574 { 0x1234abcd, "ACME PCI Widgetplus" }, 575 { 0x1234fedc, "Happy moon brand RIPOFFplus" }, 576 { 0x00000000, NULL } 577}; 578 579/* 580 * See if this card is specifically mentionned in our list of known devices. 581 * Theoretically we might also put in a weak bid for some devices that 582 * report themselves o be some generic type of device if we can handle 583 * that generic type. (other PCI_XXX calls give that info). 584 * This would allow a specific driver to over-ride us. 585 * 586 * See the comments in the ISA section regarding returning non-positive 587 * values from probe routines. 588 */ 589static int 590${1}_pci_probe (device_t device) 591{ 592 u_int32_t type = pci_get_devid(device); 593 struct _pcsid *ep =pci_ids; 594 595 while (ep->type && ep->type != type) 596 ++ep; 597 if (ep->desc) { 598 device_set_desc(device, ep->desc); 599 return 0; /* If there may be a better driver, return -2 */ 600 } else { 601 return ENXIO; 602 } 603} 604 605static int 606${1}_pci_attach(device_t device) 607{ 608 sc_p scp = device_get_softc(device); 609 int error; 610 611 error = ${1}_attach(device, scp); 612 if (error) { 613 ${1}_pci_detach(device); 614 } 615 return (error); 616} 617 618static int 619${1}_pci_detach (device_t device) 620{ 621 sc_p scp = device_get_softc(device); 622 int error; 623 624 error = ${1}_detach(device, scp); 625 return (error); 626} 627 628 629/****************************************\ 630* Common Attachment subfunctions * 631\****************************************/ 632static int 633${1}_attach(device_t device, sc_p scp) 634{ 635 int unit = device_get_unit(device); 636 device_t parent = device_get_parent(device); 637 638 scp->dev = make_dev(&${1}_cdevsw, 0, 639 UID_ROOT, GID_OPERATOR, 0600, "${1}%d", unit); 640 scp->dev->si_drv1 = scp; 641 642 if (${1}_allocate_resources(device)) { 643 goto errexit; 644 } 645 646 scp->bt = rman_get_bustag(scp->res_ioport); 647 scp->bh = rman_get_bushandle(scp->res_ioport); 648 649 /* register the interrupt handler */ 650 /* 651 * The type should be one of: 652 * INTR_TYPE_TTY 653 * (INTR_TYPE_TTY | INTR_TYPE_FAST) 654 * INTR_TYPE_BIO 655 * INTR_TYPE_CAM 656 * INTR_TYPE_NET 657 * INTR_TYPE_MISC 658 * This will probably change with SMPng. 659 */ 660 if (scp->res_irq) { 661 /* default to the tty mask for registration */ /* XXX */ 662 if (BUS_SETUP_INTR(parent, device, scp->res_irq, INTR_TYPE_TTY, 663 ${1}intr, scp, &scp->intr_cookie) == 0) { 664 /* do something if successfull */ 665 } else { 666 goto errexit; 667 } 668 } 669 670 /* 671 * If we want to access the memory we will need 672 * to know where it was mapped. 673 */ 674 scp->vaddr = rman_get_virtual(scp->res_memory); 675 return 0; 676 677errexit: 678 /* 679 * Undo anything we may have done 680 */ 681 ${1}_detach(device, scp); 682 return (ENXIO); 683} 684 685static int 686${1}_detach(device_t device, sc_p scp) 687{ 688 device_t parent = device_get_parent(device); 689 690 /* 691 * At this point stick a strong piece of wood into the device 692 * to make sure it is stopped safely. The alternative is to 693 * simply REFUSE to detach if it's busy. What you do depends on 694 * your specific situation. 695 */ 696 /* ZAP some register */ 697 698 /* 699 * Take our interrupt handler out of the list of handlers 700 * that can handle this irq. 701 */ 702 if (scp->intr_cookie != NULL) { 703 if (BUS_TEARDOWN_INTR(parent, device, 704 scp->res_irq, scp->intr_cookie) != 0) { 705 printf("intr teardown failed.. continuing\n"); 706 } 707 scp->intr_cookie = NULL; 708 } 709 710 /* 711 * deallocate any system resources we may have 712 * allocated on behalf of this driver. 713 */ 714 scp->vaddr = NULL; 715 return ${1}_deallocate_resources(device); 716} 717 718static int 719${1}_allocate_resources(device_t device) 720{ 721 int error; 722 sc_p scp = device_get_softc(device); 723 int size = 16; /* SIZE of port range used */ 724 725 scp->res_ioport = bus_alloc_resource(device, SYS_RES_IOPORT, 726 &scp->rid_ioport, 0ul, ~0ul, size, RF_ACTIVE); 727 if (scp->res_ioport == NULL) { 728 goto errexit; 729 } 730 731 scp->res_irq = bus_alloc_resource(device, SYS_RES_IRQ, 732 &scp->rid_irq, 0ul, ~0ul, 1, RF_SHAREABLE|RF_ACTIVE); 733 if (scp->res_irq == NULL) { 734 goto errexit; 735 } 736 737 scp->res_drq = bus_alloc_resource(device, SYS_RES_DRQ, 738 &scp->rid_drq, 0ul, ~0ul, 1, RF_ACTIVE); 739 if (scp->res_drq == NULL) { 740 goto errexit; 741 } 742 743 scp->res_memory = bus_alloc_resource(device, SYS_RES_MEMORY, 744 &scp->rid_memory, 0ul, ~0ul, MSIZE, RF_ACTIVE); 745 if (scp->res_memory == NULL) { 746 goto errexit; 747 } 748 return (0); 749 750errexit: 751 error = ENXIO; 752 /* cleanup anything we may have assigned. */ 753 ${1}_deallocate_resources(device); 754 return (ENXIO); /* for want of a better idea */ 755} 756 757static int 758${1}_deallocate_resources(device_t device) 759{ 760 sc_p scp = device_get_softc(device); 761 762 if (scp->res_irq != 0) { 763 bus_deactivate_resource(device, SYS_RES_IRQ, 764 scp->rid_irq, scp->res_irq); 765 bus_release_resource(device, SYS_RES_IRQ, 766 scp->rid_irq, scp->res_irq); 767 scp->res_irq = 0; 768 } 769 if (scp->res_ioport != 0) { 770 bus_deactivate_resource(device, SYS_RES_IOPORT, 771 scp->rid_ioport, scp->res_ioport); 772 bus_release_resource(device, SYS_RES_IOPORT, 773 scp->rid_ioport, scp->res_ioport); 774 scp->res_ioport = 0; 775 } 776 if (scp->res_memory != 0) { 777 bus_deactivate_resource(device, SYS_RES_MEMORY, 778 scp->rid_memory, scp->res_memory); 779 bus_release_resource(device, SYS_RES_MEMORY, 780 scp->rid_memory, scp->res_memory); 781 scp->res_memory = 0; 782 } 783 if (scp->res_drq != 0) { 784 bus_deactivate_resource(device, SYS_RES_DRQ, 785 scp->rid_drq, scp->res_drq); 786 bus_release_resource(device, SYS_RES_DRQ, 787 scp->rid_drq, scp->res_drq); 788 scp->res_drq = 0; 789 } 790 if (scp->dev) { 791 destroy_dev(scp->dev); 792 } 793 return (0); 794} 795 796static void 797${1}intr(void *arg) 798{ 799 sc_p scp = arg; 800 801 /* 802 * well we got an interupt, now what? 803 */ 804 return; 805} 806 807static int 808${1}ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 809{ 810 sc_p scp = dev->si_drv1; 811 812 switch (cmd) { 813 case DHIOCRESET: 814 /* whatever resets it */ 815#if 0 816 ${UPPER}_OUTB(SOME_PORT, 0xff) ; 817#endif 818 break; 819 default: 820 return ENXIO; 821 } 822 return (0); 823} 824/* 825 * You also need read, write, open, close routines. 826 * This should get you started 827 */ 828static int 829${1}open(dev_t dev, int oflags, int devtype, struct proc *p) 830{ 831 sc_p scp = dev->si_drv1; 832 833 /* 834 * Do processing 835 */ 836 return (0); 837} 838 839static int 840${1}close(dev_t dev, int fflag, int devtype, struct proc *p) 841{ 842 sc_p scp = dev->si_drv1; 843 844 /* 845 * Do processing 846 */ 847 return (0); 848} 849 850static int 851${1}read(dev_t dev, struct uio *uio, int ioflag) 852{ 853 sc_p scp = dev->si_drv1; 854 int toread; 855 856 857 /* 858 * Do processing 859 * read from buffer 860 */ 861 toread = (min(uio->uio_resid, sizeof(scp->buffer))); 862 return(uiomove(scp->buffer, toread, uio)); 863} 864 865static int 866${1}write(dev_t dev, struct uio *uio, int ioflag) 867{ 868 sc_p scp = dev->si_drv1; 869 int towrite; 870 871 /* 872 * Do processing 873 * write to buffer 874 */ 875 towrite = (min(uio->uio_resid, sizeof(scp->buffer))); 876 return(uiomove(scp->buffer, towrite, uio)); 877} 878 879static int 880${1}mmap(dev_t dev, vm_offset_t offset, int nprot) 881{ 882 sc_p scp = dev->si_drv1; 883 884 /* 885 * Given a byte offset into your device, return the PHYSICAL 886 * page number that it would map to. 887 */ 888#if 0 /* if we had a frame buffer or whatever.. do this */ 889 if (offset > FRAMEBUFFERSIZE - PAGE_SIZE) { 890 return (-1); 891 } 892 return i386_btop((FRAMEBASE + offset)); 893#else 894 return (-1); 895#endif 896} 897 898static int 899${1}poll(dev_t dev, int which, struct proc *p) 900{ 901 sc_p scp = dev->si_drv1; 902 903 /* 904 * Do processing 905 */ 906 return (0); /* this is the wrong value I'm sure */ 907} 908 909DONE 910 911cat >${TOP}/sys/${1}io.h <<DONE 912/* 913 * Definitions needed to access the ${1} device (ioctls etc) 914 * see mtio.h , ioctl.h as examples 915 */ 916#ifndef SYS_DHIO_H 917#define SYS_DHIO_H 918 919#ifndef KERNEL 920#include <sys/types.h> 921#endif 922#include <sys/ioccom.h> 923 924/* 925 * define an ioctl here 926 */ 927#define DHIOCRESET _IO('D', 0) /* reset the ${1} device */ 928#endif 929DONE 930 931if [ ! -d ${TOP}/modules/${1} ] 932then 933 mkdir -p ${TOP}/modules/${1} 934fi 935 936cat >${TOP}/modules/${1}/Makefile <<DONE 937# ${UPPER} Loadable Kernel Module 938# 939# \$${RCS_KEYWORD}: $ 940 941.PATH: \${.CURDIR}/../../dev/${1} 942KMOD = ${1} 943SRCS = ${1}.c 944SRCS += opt_inet.h device_if.h bus_if.h pci_if.h isa_if.h 945 946# you may need to do this is your device is an if_xxx driver 947opt_inet.h: 948 echo "#define INET 1" > opt_inet.h 949 950.include <bsd.kmod.mk> 951DONE 952 953(cd ${TOP}/modules/${1}; make depend; make ) 954exit 955 956config ${UPPER} 957cd ../../compile/${UPPER} 958make depend 959make ${1}.o 960make 961exit 962 963#--------------end of script--------------- 964# 965#edit to your taste.. 966# 967# 968 969 970 971 972