]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - share/examples/drivers/make_device_driver.sh
MFC r333391 (imp): Remove 'All Rights Reserved' from the collection copyright
[FreeBSD/FreeBSD.git] / share / examples / drivers / make_device_driver.sh
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 /usr/src; make buildkernel KERNCONF=FOO
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 linked 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 # arg2 path to the kernel sources, "/sys" if omitted
16 #
17 # Trust me, RUN THIS SCRIPT :)
18 #
19 # TODO:
20 #   o generate foo_isa.c, foo_pci.c, foo_pccard.c, foo_cardbus.c, and foovar.h
21 #   o Put pccard stuff in here.
22 #
23 # $FreeBSD$"
24 #
25 #
26 if [ "X${1}" = "X" ]; then
27         echo "Hey, how about some help here... give me a device name!"
28         exit 1
29 fi
30 if [ "X${2}" = "X" ]; then
31         TOP=`cd /sys; pwd -P`
32         echo "Using ${TOP} as the path to the kernel sources!"
33 else
34         TOP=${2}
35 fi
36 UPPER=`echo ${1} |tr "[:lower:]" "[:upper:]"`
37
38 RCS_KEYWORD=FreeBSD
39
40 if [ -d ${TOP}/modules/${1} ]; then
41         echo "There appears to already be a module called ${1}"
42         echo -n "Should it be overwritten? [Y]"
43         read VAL
44         if [ "-z" "$VAL" ]; then
45                 VAL=YES
46         fi
47         case ${VAL} in
48         [yY]*)
49                 echo "Cleaning up from prior runs"
50                 rm -rf ${TOP}/dev/${1}
51                 rm -rf ${TOP}/modules/${1}
52                 rm ${TOP}/conf/files.${UPPER}
53                 rm ${TOP}/i386/conf/${UPPER}
54                 rm ${TOP}/sys/${1}io.h
55                 ;;
56         *)
57                 exit 1
58                 ;;
59         esac
60 fi
61
62 echo "The following files will be created:"
63 echo ${TOP}/modules/${1}
64 echo ${TOP}/conf/files.${UPPER}
65 echo ${TOP}/i386/conf/${UPPER}
66 echo ${TOP}/dev/${1}
67 echo ${TOP}/dev/${1}/${1}.c
68 echo ${TOP}/sys/${1}io.h
69 echo ${TOP}/modules/${1}
70 echo ${TOP}/modules/${1}/Makefile
71
72         mkdir ${TOP}/modules/${1}
73
74 #######################################################################
75 #######################################################################
76 #
77 # Create configuration information needed to create a kernel
78 # containing this driver.
79 #
80 # Not really needed if we are going to do this as a module.
81 #######################################################################
82 # First add the file to a local file list.
83 #######################################################################
84
85 cat >${TOP}/conf/files.${UPPER} <<DONE
86 dev/${1}/${1}.c  optional ${1}
87 DONE
88
89 #######################################################################
90 # Then create a configuration file for a kernel that contains this driver.
91 #######################################################################
92 cat >${TOP}/i386/conf/${UPPER} <<DONE
93 # Configuration file for kernel type: ${UPPER}
94 # \$${RCS_KEYWORD}$
95
96 files           "${TOP}/conf/files.${UPPER}"
97
98 include         GENERIC
99
100 ident           ${UPPER}
101
102 DONE
103
104 cat >>${TOP}/i386/conf/${UPPER} <<DONE
105 # trust me, you'll need this
106 options         KDB
107 options         DDB
108 device          ${1}
109 DONE
110
111 if [ ! -d ${TOP}/dev/${1} ]; then
112         mkdir -p ${TOP}/dev/${1}
113 fi
114
115 cat >${TOP}/dev/${1}/${1}.c <<DONE
116 /*
117  * Copyright (c) [year] [your name]
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions and the following disclaimer.
124  * 2. Redistributions in binary form must reproduce the above copyright
125  *    notice, this list of conditions and the following disclaimer in the
126  *    documentation and/or other materials provided with the distribution.
127  *
128  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
129  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
130  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
131  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
132  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
133  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
134  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
135  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
136  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
137  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
138  * SUCH DAMAGE.
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/cdefs.h>
147 __FBSDID("\$${RCS_KEYWORD}$");
148
149 #include <sys/param.h>
150 #include <sys/systm.h>
151 #include <sys/conf.h>           /* cdevsw stuff */
152 #include <sys/kernel.h>         /* SYSINIT stuff */
153 #include <sys/uio.h>            /* SYSINIT stuff */
154 #include <sys/malloc.h>         /* malloc region definitions */
155 #include <sys/module.h>
156 #include <sys/bus.h>
157 #include <sys/proc.h>
158 #include <sys/time.h>
159 #include <sys/${1}io.h>         /* ${1} IOCTL definitions */
160
161 #include <machine/bus.h>
162 #include <machine/resource.h>
163 #include <sys/rman.h>
164
165 #include <dev/pci/pcireg.h>
166 #include <dev/pci/pcivar.h>
167
168 #include <isa/isavar.h>
169
170 #include "isa_if.h"
171
172 /* XXX These should be defined in terms of bus-space ops. */
173 #define ${UPPER}_INB(port) inb(port_start)
174 #define ${UPPER}_OUTB(port, val) ( port_start, (val))
175 #define SOME_PORT 123
176 #define EXPECTED_VALUE 0x42
177
178 /*
179  * The softc is automatically allocated by the parent bus using the
180  * size specified in the driver_t declaration below.
181  */
182 #define DEV2SOFTC(dev)  ((struct ${1}_softc *) (dev)->si_drv1)
183 #define DEVICE2SOFTC(dev) ((struct ${1}_softc *) device_get_softc(dev))
184
185 /*
186  * Device specific misc defines.
187  */
188 #define BUFFERSIZE      1024
189 #define NUMPORTS        4
190 #define MEMSIZE         (4 * 1024) /* Imaginable h/w buffer size. */
191
192 /*
193  * One of these per allocated device.
194  */
195 struct ${1}_softc {
196         bus_space_tag_t bt;
197         bus_space_handle_t bh;
198         int rid_ioport;
199         int rid_memory;
200         int rid_irq;
201         int rid_drq;
202         struct resource* res_ioport;    /* Resource for port range. */
203         struct resource* res_memory;    /* Resource for mem range. */
204         struct resource* res_irq;       /* Resource for irq range. */
205         struct resource* res_drq;       /* Resource for dma channel. */
206         device_t device;
207         struct cdev *dev;
208         void    *intr_cookie;
209         void    *vaddr;                 /* Virtual address of mem resource. */
210         char    buffer[BUFFERSIZE];     /* If we need to buffer something. */
211 };
212
213 /* Function prototypes (these should all be static). */
214 static int ${1}_deallocate_resources(device_t device);
215 static int ${1}_allocate_resources(device_t device);
216 static int ${1}_attach(device_t device, struct ${1}_softc *scp);
217 static int ${1}_detach(device_t device, struct ${1}_softc *scp);
218
219 static d_open_t         ${1}open;
220 static d_close_t        ${1}close;
221 static d_read_t         ${1}read;
222 static d_write_t        ${1}write;
223 static d_ioctl_t        ${1}ioctl;
224 static d_mmap_t         ${1}mmap;
225 static d_poll_t         ${1}poll;
226 static  void            ${1}intr(void *arg);
227
228 static struct cdevsw ${1}_cdevsw = {
229         .d_version =    D_VERSION,
230         .d_open =       ${1}open,
231         .d_close =      ${1}close,
232         .d_read =       ${1}read,
233         .d_write =      ${1}write,
234         .d_ioctl =      ${1}ioctl,
235         .d_poll =       ${1}poll,
236         .d_mmap =       ${1}mmap,
237         .d_name =       "${1}",
238 };
239
240 static devclass_t ${1}_devclass;
241
242 /*
243  ******************************************
244  * ISA Attachment structures and functions.
245  ******************************************
246  */
247 static void ${1}_isa_identify (driver_t *, device_t);
248 static int ${1}_isa_probe (device_t);
249 static int ${1}_isa_attach (device_t);
250 static int ${1}_isa_detach (device_t);
251
252 static struct isa_pnp_id ${1}_ids[] = {
253         {0x12345678,    "ABCco Widget"},
254         {0xfedcba98,    "shining moon Widget ripoff"},
255         {0,             NULL}
256 };
257
258 static device_method_t ${1}_methods[] = {
259         DEVMETHOD(device_identify,      ${1}_isa_identify),
260         DEVMETHOD(device_probe,         ${1}_isa_probe),
261         DEVMETHOD(device_attach,        ${1}_isa_attach),
262         DEVMETHOD(device_detach,        ${1}_isa_detach),
263         DEVMETHOD_END
264 };
265
266 static driver_t ${1}_isa_driver = {
267         "${1}",
268         ${1}_methods,
269         sizeof (struct ${1}_softc)
270 };
271
272 DRIVER_MODULE(${1}, isa, ${1}_isa_driver, ${1}_devclass, 0, 0);
273
274 /*
275  * Here list some port addresses we might expect our widget to appear at:
276  * This list should only be used for cards that have some non-destructive
277  * (to other cards) way of probing these address.  Otherwise the driver
278  * should not go looking for instances of itself, but instead rely on
279  * the hints file.  Strange failures for people with other cards might
280  * result.
281  */
282 static struct localhints {
283         int ioport;
284         int irq;
285         int drq;
286         int mem;
287 } res[] = {
288         { 0x210, 11, 2, 0xcd000},
289         { 0x310, 12, 3, 0xdd000},
290         { 0x320, 9, 6, 0xd4000},
291         {0,0,0,0}
292 };
293
294 #define MAXHINTS 10 /* Just an arbitrary safety limit. */
295 /*
296  * Called once when the driver is somehow connected with the bus,
297  * (Either linked in and the bus is started, or loaded as a module).
298  *
299  * The aim of this routine in an ISA driver is to add child entries to
300  * the parent bus so that it looks as if the devices were detected by
301  * some pnp-like method, or at least mentioned in the hints.
302  *
303  * For NON-PNP "dumb" devices:
304  * Add entries into the bus's list of likely devices, so that
305  * our 'probe routine' will be called for them.
306  * This is similar to what the 'hints' code achieves, except this is
307  * loadable with the driver.
308  * In the 'dumb' case we end up with more children than needed but
309  * some (or all) of them will fail probe() and only waste a little memory.
310  *
311  * For NON-PNP "Smart" devices:
312  * If the device has a NON-PNP way of being detected and setting/sensing
313  * the card, then do that here and add a child for each set of
314  * hardware found.
315  *
316  * For PNP devices:
317  * If the device is always PNP capable then this function can be removed.
318  * The ISA PNP system will have automatically added it to the system and
319  * so your identify routine needn't do anything.
320  *
321  * If the device is mentioned in the 'hints' file then this
322  * function can be removed. All devices mentioned in the hints
323  * file get added as children for probing, whether or not the
324  * driver is linked in. So even as a module it MAY still be there.
325  * See isa/isahint.c for hints being added in.
326  */
327 static void
328 ${1}_isa_identify (driver_t *driver, device_t parent)
329 {
330         u_int32_t       irq=0;
331         u_int32_t       ioport;
332         device_t        child;
333         int i;
334
335         /*
336          * If we've already got ${UPPER} attached somehow, don't try again.
337          * Maybe it was in the hints file. or it was loaded before.
338          */
339         if (device_find_child(parent, "${1}", 0)) {
340                 printf("${UPPER}: already attached\n");
341                 return;
342         }
343 /* XXX Look at dev/acpica/acpi_isa.c for use of ISA_ADD_CONFIG() macro. */
344 /* XXX What is ISA_SET_CONFIG_CALLBACK(parent, child, pnpbios_set_config, 0)? */
345         for (i = 0; i < MAXHINTS; i++) {
346
347                 ioport = res[i].ioport;
348                 irq = res[i].irq;
349                 if ((ioport == 0) && (irq == 0))
350                         return; /* We've added all our local hints. */
351
352                 child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "${1}", -1);
353                 bus_set_resource(child, SYS_RES_IOPORT, 0, ioport, NUMPORTS);
354                 bus_set_resource(child, SYS_RES_IRQ,    0, irq, 1);
355                 bus_set_resource(child, SYS_RES_DRQ,    0, res[i].drq, 1);
356                 bus_set_resource(child, SYS_RES_MEMORY, 0, res[i].mem, MEMSIZE);
357
358 #if 0
359                 /*
360                  * If we wanted to pretend PNP found it
361                  * we could do this, and put matching entries
362                  * in the PNP table, but I think it's probably too hacky.
363                  * As you see, some people have done it though.
364                  * Basically EISA (remember that?) would do this I think.
365                  */
366                 isa_set_vendorid(child, PNP_EISAID("ESS1888"));
367                 isa_set_logicalid(child, PNP_EISAID("ESS1888"));
368 #endif
369         }
370 #if 0
371         /*
372          * Do some smart probing (e.g. like the lnc driver)
373          * and add a child for each one found.
374          */
375 #endif
376
377         return;
378 }
379 /*
380  * The ISA code calls this for each device it knows about,
381  * whether via the PNP code or via the hints etc.
382  * If the device nas no PNP capabilities, remove all the
383  * PNP entries, but keep the call to ISA_PNP_PROBE()
384  * As it will guard against accidentally recognising
385  * foreign hardware. This is because we will be called to check against
386  * ALL PNP hardware.
387  */
388 static int
389 ${1}_isa_probe (device_t device)
390 {
391         int error;
392         device_t parent = device_get_parent(device);
393         struct ${1}_softc *scp = DEVICE2SOFTC(device);
394         u_long  port_start, port_count;
395
396         bzero(scp, sizeof(*scp));
397         scp->device = device;
398
399         /*
400          * Check this device for a PNP match in our table.
401          * There are several possible outcomes.
402          * error == 0           We match a PNP.
403          * error == ENXIO,      It is a PNP device but not in our table.
404          * error == ENOENT,     It is not a PNP device.. try heuristic probes.
405          *    -- logic from if_ed_isa.c, added info from isa/isa_if.m:
406          *
407          * If we had a list of devices that we could handle really well,
408          * and a list which we could handle only basic functions, then
409          * we would call this twice, once for each list,
410          * and return a value of '-2' or something if we could
411          * only handle basic functions. This would allow a specific
412          * Widgetplus driver to make a better offer if it knows how to
413          * do all the extended functions. (See non-pnp part for more info).
414          */
415         error = ISA_PNP_PROBE(parent, device, ${1}_ids);
416         switch (error) {
417         case 0:
418                 /*
419                  * We found a PNP device.
420                  * Do nothing, as it's all done in attach().
421                  */
422                 break;
423         case ENOENT:
424                 /*
425                  * Well it didn't show up in the PNP tables
426                  * so look directly at known ports (if we have any)
427                  * in case we are looking for an old pre-PNP card.
428                  *
429                  * Hopefully the  'identify' routine will have picked these
430                  * up for us first if they use some proprietary detection
431                  * method.
432                  *
433                  * The ports, irqs etc should come from a 'hints' section
434                  * which is read in by code in isa/isahint.c
435                  * and kern/subr_bus.c to create resource entries,
436                  * or have been added by the 'identify routine above.
437                  * Note that HINTS based resource requests have NO
438                  * SIZE for the memory or ports requests  (just a base)
439                  * so we may need to 'correct' this before we
440                  * do any probing.
441                  */
442                 /*
443                  * Find out the values of any resources we
444                  * need for our dumb probe. Also check we have enough ports
445                  * in the request. (could be hints based).
446                  * Should probably do the same for memory regions too.
447                  */
448                 error = bus_get_resource(device, SYS_RES_IOPORT, 0,
449                     &port_start, &port_count);
450                 if (port_count != NUMPORTS) {
451                         bus_set_resource(device, SYS_RES_IOPORT, 0,
452                             port_start, NUMPORTS);
453                 }
454
455                 /*
456                  * Make a temporary resource reservation.
457                  * If we can't get the resources we need then
458                  * we need to abort.  Possibly this indicates
459                  * the resources were used by another device
460                  * in which case the probe would have failed anyhow.
461                  */
462                 if ((error = (${1}_allocate_resources(device)))) {
463                         error = ENXIO;
464                         goto errexit;
465                 }
466
467                 /* Dummy heuristic type probe. */
468                 if (inb(port_start) != EXPECTED_VALUE) {
469                         /*
470                          * It isn't what we hoped, so quit looking for it.
471                          */
472                         error = ENXIO;
473                 } else {
474                         u_long membase = bus_get_resource_start(device,
475                                         SYS_RES_MEMORY, 0 /*rid*/);
476                         u_long memsize;
477                         /*
478                          * If we discover in some way that the device has
479                          * XXX bytes of memory window, we can override
480                          * or set the memory size in the child resource list.
481                          */
482                         memsize = inb(port_start + 1) * 1024; /* for example */
483                         error = bus_set_resource(device, SYS_RES_MEMORY,
484                                 /*rid*/0, membase, memsize);
485                         /*
486                          * We found one, return non-positive numbers..
487                          * Return -N if we can't handle it, but not well.
488                          * Return -2 if we would LIKE the device.
489                          * Return -1 if we want it a lot.
490                          * Return 0 if we MUST get the device.
491                          * This allows drivers to 'bid' for a device.
492                          */
493                         device_set_desc(device, "ACME Widget model 1234");
494                         error = -1; /* We want it but someone else
495                                         may be even better. */
496                 }
497                 /*
498                  * Unreserve the resources for now because
499                  * another driver may bid for device too.
500                  * If we lose the bid, but still hold the resources, we will
501                  * effectively have disabled the other driver from getting them
502                  * which will result in neither driver getting the device.
503                  * We will ask for them again in attach if we win.
504                  */
505                 ${1}_deallocate_resources(device);
506                 break;
507         case  ENXIO:
508                 /* It was PNP but not ours, leave immediately. */
509         default:
510                 error = ENXIO;
511         }
512 errexit:
513         return (error);
514 }
515
516 /*
517  * Called if the probe succeeded and our bid won the device.
518  * We can be destructive here as we know we have the device.
519  * This is the first place we can be sure we have a softc structure.
520  * You would do ISA specific attach things here, but generically there aren't
521  * any (yay new-bus!).
522  */
523 static int
524 ${1}_isa_attach (device_t device)
525 {
526         int     error;
527         struct ${1}_softc *scp = DEVICE2SOFTC(device);
528
529         error =  ${1}_attach(device, scp);
530         if (error)
531                 ${1}_isa_detach(device);
532         return (error);
533 }
534
535 /*
536  * Detach the driver (e.g. module unload),
537  * call the bus independent version
538  * and undo anything we did in the ISA attach routine.
539  */
540 static int
541 ${1}_isa_detach (device_t device)
542 {
543         int     error;
544         struct ${1}_softc *scp = DEVICE2SOFTC(device);
545
546         error =  ${1}_detach(device, scp);
547         return (error);
548 }
549
550 /*
551  ***************************************
552  * PCI Attachment structures and code
553  ***************************************
554  */
555
556 static int      ${1}_pci_probe(device_t);
557 static int      ${1}_pci_attach(device_t);
558 static int      ${1}_pci_detach(device_t);
559
560 static device_method_t ${1}_pci_methods[] = {
561         /* Device interface */
562         DEVMETHOD(device_probe,         ${1}_pci_probe),
563         DEVMETHOD(device_attach,        ${1}_pci_attach),
564         DEVMETHOD(device_detach,        ${1}_pci_detach),
565         { 0, 0 }
566 };
567
568 static driver_t ${1}_pci_driver = {
569         "${1}",
570         ${1}_pci_methods,
571         sizeof(struct ${1}_softc),
572 };
573
574 DRIVER_MODULE(${1}, pci, ${1}_pci_driver, ${1}_devclass, 0, 0);
575 /*
576  * Cardbus is a pci bus plus extra, so use the pci driver unless special
577  * things need to be done only in the cardbus case.
578  */
579 DRIVER_MODULE(${1}, cardbus, ${1}_pci_driver, ${1}_devclass, 0, 0);
580
581 static struct _pcsid
582 {
583         u_int32_t       type;
584         const char      *desc;
585 } pci_ids[] = {
586         { 0x1234abcd,   "ACME PCI Widgetplus"   },
587         { 0x1243fedc,   "Happy moon brand RIPOFFplus"   },
588         { 0x00000000,   NULL                                    }
589 };
590
591 /*
592  * See if this card is specifically mentioned in our list of known devices.
593  * Theoretically we might also put in a weak bid for some devices that
594  * report themselves to be some generic type of device if we can handle
595  * that generic type. (other PCI_XXX calls give that info).
596  * This would allow a specific driver to over-ride us.
597  *
598  * See the comments in the ISA section regarding returning non-positive
599  * values from probe routines.
600  */
601 static int
602 ${1}_pci_probe (device_t device)
603 {
604         u_int32_t       type = pci_get_devid(device);
605         struct _pcsid   *ep =pci_ids;
606
607         while (ep->type && ep->type != type)
608                 ++ep;
609         if (ep->desc) {
610                 device_set_desc(device, ep->desc);
611                 return 0; /* If there might be a better driver, return -2 */
612         } else
613                 return ENXIO;
614 }
615
616 static int
617 ${1}_pci_attach(device_t device)
618 {
619         int     error;
620         struct ${1}_softc *scp = DEVICE2SOFTC(device);
621
622         error =  ${1}_attach(device, scp);
623         if (error)
624                 ${1}_pci_detach(device);
625         return (error);
626 }
627
628 static int
629 ${1}_pci_detach (device_t device)
630 {
631         int     error;
632         struct ${1}_softc *scp = DEVICE2SOFTC(device);
633
634         error =  ${1}_detach(device, scp);
635         return (error);
636 }
637
638 /*
639  ****************************************
640  *  Common Attachment sub-functions
641  ****************************************
642  */
643 static int
644 ${1}_attach(device_t device, struct ${1}_softc * scp)
645 {
646         device_t parent = device_get_parent(device);
647         int     unit    = device_get_unit(device);
648
649         scp->dev = make_dev(&${1}_cdevsw, 0,
650                         UID_ROOT, GID_OPERATOR, 0600, "${1}%d", unit);
651         scp->dev->si_drv1 = scp;
652
653         if (${1}_allocate_resources(device))
654                 goto errexit;
655
656         scp->bt = rman_get_bustag(scp->res_ioport);
657         scp->bh = rman_get_bushandle(scp->res_ioport);
658
659         /* Register the interrupt handler. */
660         /*
661          * The type should be one of:
662          *      INTR_TYPE_TTY
663          *      INTR_TYPE_BIO
664          *      INTR_TYPE_CAM
665          *      INTR_TYPE_NET
666          *      INTR_TYPE_MISC
667          * This will probably change with SMPng.  INTR_TYPE_FAST may be
668          * OR'd into this type to mark the interrupt fast.  However, fast
669          * interrupts cannot be shared at all so special precautions are
670          * necessary when coding fast interrupt routines.
671          */
672         if (scp->res_irq) {
673                 /* Default to the tty mask for registration. */  /* XXX */
674                 if (BUS_SETUP_INTR(parent, device, scp->res_irq, INTR_TYPE_TTY,
675                                 ${1}intr, scp, &scp->intr_cookie) == 0) {
676                         /* Do something if successful. */
677                 } else
678                         goto errexit;
679         }
680
681         /*
682          * If we want to access the memory we will need
683          * to know where it was mapped.
684          *
685          * Use of this function is discouraged, however.  You should
686          * be accessing the device with the bus_space API if at all
687          * possible.
688          */
689         scp->vaddr = rman_get_virtual(scp->res_memory);
690         return 0;
691
692 errexit:
693         /*
694          * Undo anything we may have done.
695          */
696         ${1}_detach(device, scp);
697         return (ENXIO);
698 }
699
700 static int
701 ${1}_detach(device_t device, struct ${1}_softc *scp)
702 {
703         device_t parent = device_get_parent(device);
704
705         /*
706          * At this point stick a strong piece of wood into the device
707          * to make sure it is stopped safely. The alternative is to
708          * simply REFUSE to detach if it's busy. What you do depends on
709          * your specific situation.
710          *
711          * Sometimes the parent bus will detach you anyway, even if you
712          * are busy.  You must cope with that possibility.  Your hardware
713          * might even already be gone in the case of cardbus or pccard
714          * devices.
715          */
716         /* ZAP some register */
717
718         /*
719          * Take our interrupt handler out of the list of handlers
720          * that can handle this irq.
721          */
722         if (scp->intr_cookie != NULL) {
723                 if (BUS_TEARDOWN_INTR(parent, device,
724                         scp->res_irq, scp->intr_cookie) != 0)
725                                 printf("intr teardown failed.. continuing\n");
726                 scp->intr_cookie = NULL;
727         }
728
729         /*
730          * Deallocate any system resources we may have
731          * allocated on behalf of this driver.
732          */
733         scp->vaddr = NULL;
734         return ${1}_deallocate_resources(device);
735 }
736
737 static int
738 ${1}_allocate_resources(device_t device)
739 {
740         int error;
741         struct ${1}_softc *scp = DEVICE2SOFTC(device);
742         int     size = 16; /* SIZE of port range used. */
743
744         scp->res_ioport = bus_alloc_resource(device, SYS_RES_IOPORT,
745                         &scp->rid_ioport, 0ul, ~0ul, size, RF_ACTIVE);
746         if (scp->res_ioport == NULL)
747                 goto errexit;
748
749         scp->res_irq = bus_alloc_resource(device, SYS_RES_IRQ,
750                         &scp->rid_irq, 0ul, ~0ul, 1, RF_SHAREABLE|RF_ACTIVE);
751         if (scp->res_irq == NULL)
752                 goto errexit;
753
754         scp->res_drq = bus_alloc_resource(device, SYS_RES_DRQ,
755                         &scp->rid_drq, 0ul, ~0ul, 1, RF_ACTIVE);
756         if (scp->res_drq == NULL)
757                 goto errexit;
758
759         scp->res_memory = bus_alloc_resource(device, SYS_RES_MEMORY,
760                         &scp->rid_memory, 0ul, ~0ul, MSIZE, RF_ACTIVE);
761         if (scp->res_memory == NULL)
762                 goto errexit;
763         return (0);
764
765 errexit:
766         error = ENXIO;
767         /* Cleanup anything we may have assigned. */
768         ${1}_deallocate_resources(device);
769         return (ENXIO); /* For want of a better idea. */
770 }
771
772 static int
773 ${1}_deallocate_resources(device_t device)
774 {
775         struct ${1}_softc *scp = DEVICE2SOFTC(device);
776
777         if (scp->res_irq != 0) {
778                 bus_deactivate_resource(device, SYS_RES_IRQ,
779                         scp->rid_irq, scp->res_irq);
780                 bus_release_resource(device, SYS_RES_IRQ,
781                         scp->rid_irq, scp->res_irq);
782                 scp->res_irq = 0;
783         }
784         if (scp->res_ioport != 0) {
785                 bus_deactivate_resource(device, SYS_RES_IOPORT,
786                         scp->rid_ioport, scp->res_ioport);
787                 bus_release_resource(device, SYS_RES_IOPORT,
788                         scp->rid_ioport, scp->res_ioport);
789                 scp->res_ioport = 0;
790         }
791         if (scp->res_memory != 0) {
792                 bus_deactivate_resource(device, SYS_RES_MEMORY,
793                         scp->rid_memory, scp->res_memory);
794                 bus_release_resource(device, SYS_RES_MEMORY,
795                         scp->rid_memory, scp->res_memory);
796                 scp->res_memory = 0;
797         }
798         if (scp->res_drq != 0) {
799                 bus_deactivate_resource(device, SYS_RES_DRQ,
800                         scp->rid_drq, scp->res_drq);
801                 bus_release_resource(device, SYS_RES_DRQ,
802                         scp->rid_drq, scp->res_drq);
803                 scp->res_drq = 0;
804         }
805         if (scp->dev)
806                 destroy_dev(scp->dev);
807         return (0);
808 }
809
810 static void
811 ${1}intr(void *arg)
812 {
813         struct ${1}_softc *scp = (struct ${1}_softc *) arg;
814
815         /*
816          * Well we got an interrupt, now what?
817          *
818          * Make sure that the interrupt routine will always terminate,
819          * even in the face of "bogus" data from the card.
820          */
821         (void)scp; /* Delete this line after using scp. */
822         return;
823 }
824
825 static int
826 ${1}ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
827 {
828         struct ${1}_softc *scp = DEV2SOFTC(dev);
829
830         (void)scp; /* Delete this line after using scp. */
831         switch (cmd) {
832         case DHIOCRESET:
833                 /* Whatever resets it. */
834 #if 0
835                 ${UPPER}_OUTB(SOME_PORT, 0xff);
836 #endif
837                 break;
838         default:
839                 return ENXIO;
840         }
841         return (0);
842 }
843 /*
844  * You also need read, write, open, close routines.
845  * This should get you started.
846  */
847 static int
848 ${1}open(struct cdev *dev, int oflags, int devtype, struct thread *td)
849 {
850         struct ${1}_softc *scp = DEV2SOFTC(dev);
851
852         /*
853          * Do processing.
854          */
855         (void)scp; /* Delete this line after using scp. */
856         return (0);
857 }
858
859 static int
860 ${1}close(struct cdev *dev, int fflag, int devtype, struct thread *td)
861 {
862         struct ${1}_softc *scp = DEV2SOFTC(dev);
863
864         /*
865          * Do processing.
866          */
867         (void)scp; /* Delete this line after using scp. */
868         return (0);
869 }
870
871 static int
872 ${1}read(struct cdev *dev, struct uio *uio, int ioflag)
873 {
874         struct ${1}_softc *scp = DEV2SOFTC(dev);
875         int      toread;
876
877         /*
878          * Do processing.
879          * Read from buffer.
880          */
881         (void)scp; /* Delete this line after using scp. */
882         toread = (min(uio->uio_resid, sizeof(scp->buffer)));
883         return(uiomove(scp->buffer, toread, uio));
884 }
885
886 static int
887 ${1}write(struct cdev *dev, struct uio *uio, int ioflag)
888 {
889         struct ${1}_softc *scp = DEV2SOFTC(dev);
890         int     towrite;
891
892         /*
893          * Do processing.
894          * Write to buffer.
895          */
896         (void)scp; /* Delete this line after using scp. */
897         towrite = (min(uio->uio_resid, sizeof(scp->buffer)));
898         return(uiomove(scp->buffer, towrite, uio));
899 }
900
901 static int
902 ${1}mmap(struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
903 {
904         struct ${1}_softc *scp = DEV2SOFTC(dev);
905
906         /*
907          * Given a byte offset into your device, return the PHYSICAL
908          * page number that it would map to.
909          */
910         (void)scp; /* Delete this line after using scp. */
911 #if 0   /* If we had a frame buffer or whatever... do this. */
912         if (offset > FRAMEBUFFERSIZE - PAGE_SIZE)
913                 return (-1);
914         return i386_btop((FRAMEBASE + offset));
915 #else
916         return (-1);
917 #endif
918 }
919
920 static int
921 ${1}poll(struct cdev *dev, int which, struct thread *td)
922 {
923         struct ${1}_softc *scp = DEV2SOFTC(dev);
924
925         /*
926          * Do processing.
927          */
928         (void)scp; /* Delete this line after using scp. */
929         return (0); /* This is the wrong value I'm sure. */
930 }
931
932 DONE
933
934 cat >${TOP}/sys/${1}io.h <<DONE
935 /*
936  * Definitions needed to access the ${1} device (ioctls etc)
937  * see mtio.h, ioctl.h as examples.
938  */
939 #ifndef SYS_DHIO_H
940 #define SYS_DHIO_H
941
942 #ifndef KERNEL
943 #include <sys/types.h>
944 #endif
945 #include <sys/ioccom.h>
946
947 /*
948  * Define an ioctl here.
949  */
950 #define DHIOCRESET _IO('D', 0) /* Reset the ${1} device. */
951 #endif
952 DONE
953
954 if [ ! -d ${TOP}/modules/${1} ]; then
955         mkdir -p ${TOP}/modules/${1}
956 fi
957
958 cat >${TOP}/modules/${1}/Makefile <<DONE
959 #       ${UPPER} Loadable Kernel Module
960 #
961 # \$${RCS_KEYWORD}: $
962
963 .PATH:  \${.CURDIR}/../../dev/${1}
964 KMOD    = ${1}
965 SRCS    = ${1}.c
966 SRCS    += opt_inet.h device_if.h bus_if.h pci_if.h isa_if.h
967
968 # You may need to do this is your device is an if_xxx driver.
969 opt_inet.h:
970         echo "#define INET 1" > opt_inet.h
971
972 .include <bsd.kmod.mk>
973 DONE
974
975 echo -n "Do you want to build the '${1}' module? [Y]"
976 read VAL
977 if [ "-z" "$VAL" ]; then
978         VAL=YES
979 fi
980 case ${VAL} in
981 [yY]*)
982         (cd ${TOP}/modules/${1}; make depend; make )
983         ;;
984 *)
985 #       exit
986         ;;
987 esac
988
989 echo ""
990 echo -n "Do you want to build the '${UPPER}' kernel? [Y]"
991 read VAL
992 if [ "-z" "$VAL" ]; then
993         VAL=YES
994 fi
995 case ${VAL} in
996 [yY]*)
997         (
998          cd ${TOP}/i386/conf; \
999          config ${UPPER}; \
1000          cd ${TOP}/i386/compile/${UPPER}; \
1001          make depend; \
1002          make; \
1003         )
1004         ;;
1005 *)
1006 #       exit
1007         ;;
1008 esac
1009
1010 #--------------end of script---------------
1011 #
1012 # Edit to your taste...
1013 #
1014 #