Home | History | Annotate | Line # | Download | only in kern
subr_autoconf.c revision 1.21.4.1
      1  1.21.4.1       cgd /*	$NetBSD: subr_autoconf.c,v 1.21.4.1 1996/06/13 18:49:07 cgd Exp $	*/
      2       1.9       cgd 
      3       1.1     glass /*
      4       1.7     glass  * Copyright (c) 1992, 1993
      5       1.7     glass  *	The Regents of the University of California.  All rights reserved.
      6       1.1     glass  *
      7       1.1     glass  * This software was developed by the Computer Systems Engineering group
      8       1.1     glass  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
      9       1.1     glass  * contributed to Berkeley.
     10       1.1     glass  *
     11       1.1     glass  * All advertising materials mentioning features or use of this software
     12       1.1     glass  * must display the following acknowledgement:
     13       1.1     glass  *	This product includes software developed by the University of
     14       1.1     glass  *	California, Lawrence Berkeley Laboratories.
     15       1.1     glass  *
     16       1.7     glass  * Redistribution and use in source and binary forms, with or without
     17       1.7     glass  * modification, are permitted provided that the following conditions
     18       1.7     glass  * are met:
     19       1.7     glass  * 1. Redistributions of source code must retain the above copyright
     20       1.7     glass  *    notice, this list of conditions and the following disclaimer.
     21       1.7     glass  * 2. Redistributions in binary form must reproduce the above copyright
     22       1.7     glass  *    notice, this list of conditions and the following disclaimer in the
     23       1.7     glass  *    documentation and/or other materials provided with the distribution.
     24       1.7     glass  * 3. All advertising materials mentioning features or use of this software
     25       1.7     glass  *    must display the following acknowledgement:
     26       1.7     glass  *	This product includes software developed by the University of
     27       1.7     glass  *	California, Berkeley and its contributors.
     28       1.7     glass  * 4. Neither the name of the University nor the names of its contributors
     29       1.7     glass  *    may be used to endorse or promote products derived from this software
     30       1.7     glass  *    without specific prior written permission.
     31       1.1     glass  *
     32       1.7     glass  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     33       1.7     glass  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     34       1.7     glass  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     35       1.7     glass  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     36       1.7     glass  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     37       1.7     glass  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     38       1.7     glass  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39       1.7     glass  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     40       1.7     glass  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     41       1.7     glass  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     42       1.7     glass  * SUCH DAMAGE.
     43       1.1     glass  *
     44       1.8       cgd  * from: Header: subr_autoconf.c,v 1.12 93/02/01 19:31:48 torek Exp  (LBL)
     45       1.9       cgd  *
     46       1.9       cgd  *	@(#)subr_autoconf.c	8.1 (Berkeley) 6/10/93
     47       1.1     glass  */
     48       1.1     glass 
     49       1.4   mycroft #include <sys/param.h>
     50       1.4   mycroft #include <sys/device.h>
     51       1.4   mycroft #include <sys/malloc.h>
     52      1.17  christos #include <sys/systm.h>
     53      1.16   mycroft #include <machine/limits.h>
     54       1.1     glass 
     55       1.1     glass /*
     56       1.1     glass  * Autoconfiguration subroutines.
     57       1.1     glass  */
     58       1.1     glass 
     59       1.1     glass /*
     60       1.1     glass  * ioconf.c exports exactly two names: cfdata and cfroots.  All system
     61       1.1     glass  * devices and drivers are found via these tables.
     62       1.1     glass  */
     63       1.1     glass extern struct cfdata cfdata[];
     64       1.1     glass extern short cfroots[];
     65       1.1     glass 
     66       1.1     glass #define	ROOT ((struct device *)NULL)
     67       1.1     glass 
     68      1.13   mycroft struct device *config_make_softc __P((struct device *, struct cfdata *));
     69      1.12   mycroft 
     70      1.16   mycroft struct matchinfo {
     71      1.16   mycroft 	cfmatch_t fn;
     72      1.16   mycroft 	struct	device *parent;
     73      1.16   mycroft 	void	*match, *aux;
     74      1.16   mycroft 	int	indirect, pri;
     75      1.16   mycroft };
     76      1.17  christos 
     77      1.17  christos static char *number __P((char *, int));
     78      1.17  christos static void mapply __P((struct matchinfo *, struct cfdata *));
     79      1.16   mycroft 
     80      1.20       cgd struct devicelist alldevs;		/* list of all devices */
     81      1.20       cgd struct evcntlist allevents;		/* list of all event counters */
     82      1.20       cgd 
     83      1.20       cgd /*
     84      1.20       cgd  * Initialize autoconfiguration data structures.
     85      1.20       cgd  */
     86      1.20       cgd void
     87      1.20       cgd config_init()
     88      1.20       cgd {
     89      1.20       cgd 
     90      1.20       cgd 	TAILQ_INIT(&alldevs);
     91      1.20       cgd 	TAILQ_INIT(&allevents);
     92      1.20       cgd }
     93      1.20       cgd 
     94       1.1     glass /*
     95       1.1     glass  * Apply the matching function and choose the best.  This is used
     96       1.1     glass  * a few times and we want to keep the code small.
     97       1.1     glass  */
     98      1.16   mycroft static void
     99      1.16   mycroft mapply(m, cf)
    100       1.1     glass 	register struct matchinfo *m;
    101       1.1     glass 	register struct cfdata *cf;
    102       1.1     glass {
    103       1.1     glass 	register int pri;
    104      1.12   mycroft 	void *match;
    105      1.12   mycroft 
    106      1.16   mycroft 	if (m->indirect)
    107      1.13   mycroft 		match = config_make_softc(m->parent, cf);
    108      1.16   mycroft 	else
    109      1.12   mycroft 		match = cf;
    110       1.1     glass 
    111       1.1     glass 	if (m->fn != NULL)
    112      1.12   mycroft 		pri = (*m->fn)(m->parent, match, m->aux);
    113       1.3     glass 	else {
    114      1.19   thorpej 	        if (cf->cf_attach->ca_match == NULL) {
    115      1.16   mycroft 			panic("mapply: no match function for '%s' device\n",
    116      1.12   mycroft 			    cf->cf_driver->cd_name);
    117       1.3     glass 		}
    118      1.19   thorpej 		pri = (*cf->cf_attach->ca_match)(m->parent, match, m->aux);
    119       1.3     glass 	}
    120      1.12   mycroft 
    121       1.1     glass 	if (pri > m->pri) {
    122      1.14   mycroft 		if (m->indirect && m->match)
    123      1.12   mycroft 			free(m->match, M_DEVBUF);
    124      1.12   mycroft 		m->match = match;
    125       1.1     glass 		m->pri = pri;
    126      1.12   mycroft 	} else {
    127      1.14   mycroft 		if (m->indirect)
    128      1.12   mycroft 			free(match, M_DEVBUF);
    129       1.1     glass 	}
    130       1.1     glass }
    131       1.1     glass 
    132       1.1     glass /*
    133       1.1     glass  * Iterate over all potential children of some device, calling the given
    134       1.1     glass  * function (default being the child's match function) for each one.
    135       1.1     glass  * Nonzero returns are matches; the highest value returned is considered
    136       1.1     glass  * the best match.  Return the `found child' if we got a match, or NULL
    137       1.1     glass  * otherwise.  The `aux' pointer is simply passed on through.
    138       1.1     glass  *
    139       1.1     glass  * Note that this function is designed so that it can be used to apply
    140       1.1     glass  * an arbitrary function to all potential children (its return value
    141       1.1     glass  * can be ignored).
    142       1.1     glass  */
    143      1.12   mycroft void *
    144       1.1     glass config_search(fn, parent, aux)
    145       1.1     glass 	cfmatch_t fn;
    146       1.1     glass 	register struct device *parent;
    147       1.1     glass 	void *aux;
    148       1.1     glass {
    149       1.1     glass 	register struct cfdata *cf;
    150       1.1     glass 	register short *p;
    151       1.1     glass 	struct matchinfo m;
    152       1.1     glass 
    153       1.1     glass 	m.fn = fn;
    154       1.1     glass 	m.parent = parent;
    155      1.14   mycroft 	m.match = NULL;
    156       1.1     glass 	m.aux = aux;
    157      1.14   mycroft 	m.indirect = parent && parent->dv_cfdata->cf_driver->cd_indirect;
    158       1.1     glass 	m.pri = 0;
    159       1.1     glass 	for (cf = cfdata; cf->cf_driver; cf++) {
    160       1.1     glass 		/*
    161       1.1     glass 		 * Skip cf if no longer eligible, otherwise scan through
    162       1.1     glass 		 * parents for one matching `parent', and try match function.
    163       1.1     glass 		 */
    164       1.1     glass 		if (cf->cf_fstate == FSTATE_FOUND)
    165       1.1     glass 			continue;
    166       1.1     glass 		for (p = cf->cf_parents; *p >= 0; p++)
    167       1.1     glass 			if (parent->dv_cfdata == &cfdata[*p])
    168      1.16   mycroft 				mapply(&m, cf);
    169       1.1     glass 	}
    170       1.1     glass 	return (m.match);
    171       1.1     glass }
    172       1.1     glass 
    173       1.1     glass /*
    174      1.16   mycroft  * Iterate over all potential children of some device, calling the given
    175      1.16   mycroft  * function for each one.
    176      1.16   mycroft  *
    177      1.16   mycroft  * Note that this function is designed so that it can be used to apply
    178      1.16   mycroft  * an arbitrary function to all potential children (its return value
    179      1.16   mycroft  * can be ignored).
    180      1.16   mycroft  */
    181      1.16   mycroft void
    182      1.16   mycroft config_scan(fn, parent)
    183      1.16   mycroft 	cfscan_t fn;
    184      1.16   mycroft 	register struct device *parent;
    185      1.16   mycroft {
    186      1.16   mycroft 	register struct cfdata *cf;
    187      1.16   mycroft 	register short *p;
    188      1.16   mycroft 	void *match;
    189      1.16   mycroft 	int indirect;
    190      1.16   mycroft 
    191      1.16   mycroft 	indirect = parent && parent->dv_cfdata->cf_driver->cd_indirect;
    192      1.16   mycroft 	for (cf = cfdata; cf->cf_driver; cf++) {
    193      1.16   mycroft 		/*
    194      1.16   mycroft 		 * Skip cf if no longer eligible, otherwise scan through
    195      1.16   mycroft 		 * parents for one matching `parent', and try match function.
    196      1.16   mycroft 		 */
    197      1.16   mycroft 		if (cf->cf_fstate == FSTATE_FOUND)
    198      1.16   mycroft 			continue;
    199      1.16   mycroft 		for (p = cf->cf_parents; *p >= 0; p++)
    200      1.16   mycroft 			if (parent->dv_cfdata == &cfdata[*p]) {
    201      1.16   mycroft 				if (indirect)
    202      1.16   mycroft 					match = config_make_softc(parent, cf);
    203      1.16   mycroft 				else
    204      1.16   mycroft 					match = cf;
    205      1.16   mycroft 				(*fn)(parent, match);
    206      1.16   mycroft 			}
    207      1.16   mycroft 	}
    208      1.16   mycroft }
    209      1.16   mycroft 
    210      1.16   mycroft /*
    211       1.1     glass  * Find the given root device.
    212       1.1     glass  * This is much like config_search, but there is no parent.
    213       1.1     glass  */
    214      1.12   mycroft void *
    215       1.1     glass config_rootsearch(fn, rootname, aux)
    216       1.1     glass 	register cfmatch_t fn;
    217       1.1     glass 	register char *rootname;
    218       1.1     glass 	register void *aux;
    219       1.1     glass {
    220       1.1     glass 	register struct cfdata *cf;
    221       1.1     glass 	register short *p;
    222       1.1     glass 	struct matchinfo m;
    223       1.1     glass 
    224       1.1     glass 	m.fn = fn;
    225       1.1     glass 	m.parent = ROOT;
    226      1.14   mycroft 	m.match = NULL;
    227       1.1     glass 	m.aux = aux;
    228      1.14   mycroft 	m.indirect = 0;
    229       1.1     glass 	m.pri = 0;
    230       1.1     glass 	/*
    231       1.1     glass 	 * Look at root entries for matching name.  We do not bother
    232       1.1     glass 	 * with found-state here since only one root should ever be
    233       1.1     glass 	 * searched (and it must be done first).
    234       1.1     glass 	 */
    235       1.1     glass 	for (p = cfroots; *p >= 0; p++) {
    236       1.1     glass 		cf = &cfdata[*p];
    237       1.1     glass 		if (strcmp(cf->cf_driver->cd_name, rootname) == 0)
    238      1.16   mycroft 			mapply(&m, cf);
    239       1.1     glass 	}
    240       1.1     glass 	return (m.match);
    241       1.1     glass }
    242       1.1     glass 
    243       1.1     glass static char *msgs[3] = { "", " not configured\n", " unsupported\n" };
    244       1.1     glass 
    245       1.1     glass /*
    246       1.1     glass  * The given `aux' argument describes a device that has been found
    247       1.1     glass  * on the given parent, but not necessarily configured.  Locate the
    248      1.18       cgd  * configuration data for that device (using the submatch function
    249      1.18       cgd  * provided, or using candidates' cd_match configuration driver
    250      1.18       cgd  * functions) and attach it, and return true.  If the device was
    251       1.1     glass  * not configured, call the given `print' function and return 0.
    252       1.1     glass  */
    253      1.21       cgd struct device *
    254      1.18       cgd config_found_sm(parent, aux, print, submatch)
    255       1.1     glass 	struct device *parent;
    256       1.1     glass 	void *aux;
    257       1.1     glass 	cfprint_t print;
    258      1.18       cgd 	cfmatch_t submatch;
    259       1.1     glass {
    260      1.12   mycroft 	void *match;
    261       1.1     glass 
    262      1.21       cgd 	if ((match = config_search(submatch, parent, aux)) != NULL)
    263      1.21       cgd 		return (config_attach(parent, match, aux, print));
    264       1.3     glass 	if (print)
    265      1.12   mycroft 		printf(msgs[(*print)(aux, parent->dv_xname)]);
    266      1.21       cgd 	return (NULL);
    267       1.1     glass }
    268       1.1     glass 
    269       1.1     glass /*
    270       1.1     glass  * As above, but for root devices.
    271       1.1     glass  */
    272      1.21       cgd struct device *
    273       1.1     glass config_rootfound(rootname, aux)
    274       1.1     glass 	char *rootname;
    275       1.1     glass 	void *aux;
    276       1.1     glass {
    277      1.12   mycroft 	void *match;
    278       1.1     glass 
    279      1.21       cgd 	if ((match = config_rootsearch((cfmatch_t)NULL, rootname, aux)) != NULL)
    280      1.21       cgd 		return (config_attach(ROOT, match, aux, (cfprint_t)NULL));
    281       1.1     glass 	printf("root device %s not configured\n", rootname);
    282      1.21       cgd 	return (NULL);
    283       1.1     glass }
    284       1.1     glass 
    285       1.1     glass /* just like sprintf(buf, "%d") except that it works from the end */
    286       1.1     glass static char *
    287       1.1     glass number(ep, n)
    288       1.1     glass 	register char *ep;
    289       1.1     glass 	register int n;
    290       1.1     glass {
    291       1.1     glass 
    292       1.1     glass 	*--ep = 0;
    293       1.1     glass 	while (n >= 10) {
    294       1.1     glass 		*--ep = (n % 10) + '0';
    295       1.1     glass 		n /= 10;
    296       1.1     glass 	}
    297       1.1     glass 	*--ep = n + '0';
    298       1.1     glass 	return (ep);
    299       1.1     glass }
    300       1.1     glass 
    301       1.1     glass /*
    302       1.1     glass  * Attach a found device.  Allocates memory for device variables.
    303       1.1     glass  */
    304      1.21       cgd struct device *
    305      1.12   mycroft config_attach(parent, match, aux, print)
    306       1.1     glass 	register struct device *parent;
    307      1.12   mycroft 	void *match;
    308       1.1     glass 	register void *aux;
    309       1.1     glass 	cfprint_t print;
    310       1.1     glass {
    311      1.12   mycroft 	register struct cfdata *cf;
    312      1.12   mycroft 	register struct device *dev;
    313      1.13   mycroft 	register struct cfdriver *cd;
    314      1.19   thorpej 	register struct cfattach *ca;
    315      1.12   mycroft 
    316      1.13   mycroft 	if (parent && parent->dv_cfdata->cf_driver->cd_indirect) {
    317      1.12   mycroft 		dev = match;
    318      1.12   mycroft 		cf = dev->dv_cfdata;
    319      1.12   mycroft 	} else {
    320      1.12   mycroft 		cf = match;
    321      1.13   mycroft 		dev = config_make_softc(parent, cf);
    322      1.12   mycroft 	}
    323      1.12   mycroft 
    324      1.13   mycroft 	cd = cf->cf_driver;
    325      1.19   thorpej 	ca = cf->cf_attach;
    326      1.13   mycroft 	cd->cd_devs[cf->cf_unit] = dev;
    327      1.12   mycroft 
    328      1.12   mycroft 	if (cf->cf_fstate == FSTATE_STAR)
    329      1.12   mycroft 		cf->cf_unit++;
    330      1.12   mycroft 	else
    331      1.12   mycroft 		cf->cf_fstate = FSTATE_FOUND;
    332      1.12   mycroft 
    333      1.20       cgd 	TAILQ_INSERT_TAIL(&alldevs, dev, dv_list);
    334      1.12   mycroft 
    335      1.12   mycroft 	if (parent == ROOT)
    336      1.12   mycroft 		printf("%s (root)", dev->dv_xname);
    337      1.12   mycroft 	else {
    338      1.12   mycroft 		printf("%s at %s", dev->dv_xname, parent->dv_xname);
    339      1.12   mycroft 		if (print)
    340      1.12   mycroft 			(void) (*print)(aux, (char *)0);
    341      1.12   mycroft 	}
    342      1.12   mycroft 
    343      1.12   mycroft 	/*
    344      1.12   mycroft 	 * Before attaching, clobber any unfound devices that are
    345      1.19   thorpej 	 * otherwise identical, or bump the unit number on all starred
    346      1.19   thorpej 	 * cfdata for this device.
    347      1.12   mycroft 	 */
    348      1.12   mycroft 	for (cf = cfdata; cf->cf_driver; cf++)
    349      1.19   thorpej 		if (cf->cf_driver == cd && cf->cf_unit == dev->dv_unit) {
    350      1.19   thorpej 			if (cf->cf_fstate == FSTATE_NOTFOUND)
    351      1.19   thorpej 				cf->cf_fstate = FSTATE_FOUND;
    352      1.19   thorpej 			if (cf->cf_fstate == FSTATE_STAR)
    353      1.19   thorpej 				cf->cf_unit++;
    354      1.19   thorpej 		}
    355  1.21.4.1       cgd #ifdef __alpha__
    356  1.21.4.1       cgd 	device_register(dev, aux);
    357  1.21.4.1       cgd #endif
    358      1.19   thorpej 	(*ca->ca_attach)(parent, dev, aux);
    359      1.21       cgd 	return (dev);
    360      1.12   mycroft }
    361      1.12   mycroft 
    362      1.12   mycroft struct device *
    363      1.13   mycroft config_make_softc(parent, cf)
    364      1.13   mycroft 	struct device *parent;
    365      1.12   mycroft 	struct cfdata *cf;
    366      1.12   mycroft {
    367       1.1     glass 	register struct device *dev;
    368       1.1     glass 	register struct cfdriver *cd;
    369      1.19   thorpej 	register struct cfattach *ca;
    370       1.1     glass 	register size_t lname, lunit;
    371       1.1     glass 	register char *xunit;
    372       1.1     glass 	char num[10];
    373       1.1     glass 
    374       1.1     glass 	cd = cf->cf_driver;
    375      1.19   thorpej 	ca = cf->cf_attach;
    376      1.19   thorpej 	if (ca->ca_devsize < sizeof(struct device))
    377      1.12   mycroft 		panic("config_make_softc");
    378       1.1     glass 
    379       1.1     glass 	/* compute length of name and decimal expansion of unit number */
    380       1.1     glass 	lname = strlen(cd->cd_name);
    381      1.12   mycroft 	xunit = number(&num[sizeof num], cf->cf_unit);
    382       1.1     glass 	lunit = &num[sizeof num] - xunit;
    383       1.1     glass 	if (lname + lunit >= sizeof(dev->dv_xname))
    384       1.1     glass 		panic("config_attach: device name too long");
    385       1.1     glass 
    386       1.1     glass 	/* get memory for all device vars */
    387      1.19   thorpej 	dev = (struct device *)malloc(ca->ca_devsize, M_DEVBUF, M_NOWAIT);
    388       1.3     glass 	if (!dev)
    389       1.3     glass 	    panic("config_attach: memory allocation for device softc failed");
    390      1.19   thorpej 	bzero(dev, ca->ca_devsize);
    391       1.1     glass 	dev->dv_class = cd->cd_class;
    392       1.1     glass 	dev->dv_cfdata = cf;
    393      1.12   mycroft 	dev->dv_unit = cf->cf_unit;
    394       1.1     glass 	bcopy(cd->cd_name, dev->dv_xname, lname);
    395       1.1     glass 	bcopy(xunit, dev->dv_xname + lname, lunit);
    396       1.1     glass 	dev->dv_parent = parent;
    397       1.1     glass 
    398       1.1     glass 	/* put this device in the devices array */
    399       1.1     glass 	if (dev->dv_unit >= cd->cd_ndevs) {
    400       1.1     glass 		/*
    401       1.1     glass 		 * Need to expand the array.
    402       1.1     glass 		 */
    403      1.10   mycroft 		int old = cd->cd_ndevs, new;
    404       1.1     glass 		void **nsp;
    405       1.1     glass 
    406      1.10   mycroft 		if (old == 0)
    407      1.10   mycroft 			new = MINALLOCSIZE / sizeof(void *);
    408      1.10   mycroft 		else
    409      1.10   mycroft 			new = old * 2;
    410      1.10   mycroft 		while (new <= dev->dv_unit)
    411      1.10   mycroft 			new *= 2;
    412      1.10   mycroft 		cd->cd_ndevs = new;
    413      1.10   mycroft 		nsp = malloc(new * sizeof(void *), M_DEVBUF, M_NOWAIT);
    414      1.10   mycroft 		if (nsp == 0)
    415      1.10   mycroft 			panic("config_attach: %sing dev array",
    416      1.10   mycroft 			    old != 0 ? "expand" : "creat");
    417      1.10   mycroft 		bzero(nsp + old, (new - old) * sizeof(void *));
    418      1.10   mycroft 		if (old != 0) {
    419      1.10   mycroft 			bcopy(cd->cd_devs, nsp, old * sizeof(void *));
    420       1.1     glass 			free(cd->cd_devs, M_DEVBUF);
    421       1.1     glass 		}
    422       1.1     glass 		cd->cd_devs = nsp;
    423       1.1     glass 	}
    424       1.1     glass 	if (cd->cd_devs[dev->dv_unit])
    425       1.1     glass 		panic("config_attach: duplicate %s", dev->dv_xname);
    426       1.1     glass 
    427      1.12   mycroft 	return (dev);
    428       1.1     glass }
    429       1.1     glass 
    430       1.1     glass /*
    431       1.1     glass  * Attach an event.  These must come from initially-zero space (see
    432       1.1     glass  * commented-out assignments below), but that occurs naturally for
    433       1.1     glass  * device instance variables.
    434       1.1     glass  */
    435       1.1     glass void
    436       1.1     glass evcnt_attach(dev, name, ev)
    437       1.1     glass 	struct device *dev;
    438       1.1     glass 	const char *name;
    439       1.1     glass 	struct evcnt *ev;
    440       1.1     glass {
    441       1.1     glass 
    442       1.1     glass #ifdef DIAGNOSTIC
    443       1.1     glass 	if (strlen(name) >= sizeof(ev->ev_name))
    444       1.1     glass 		panic("evcnt_attach");
    445       1.1     glass #endif
    446       1.1     glass 	/* ev->ev_next = NULL; */
    447       1.1     glass 	ev->ev_dev = dev;
    448       1.1     glass 	/* ev->ev_count = 0; */
    449       1.1     glass 	strcpy(ev->ev_name, name);
    450      1.20       cgd 	TAILQ_INSERT_TAIL(&allevents, ev, ev_list);
    451       1.1     glass }
    452