Home | History | Annotate | Line # | Download | only in dev
dio.c revision 1.5
      1 /*	$NetBSD: dio.c,v 1.5 1997/04/04 09:53:43 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1996 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
     30  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /*
     40  * Autoconfiguration and mapping support for the DIO bus.
     41  */
     42 
     43 #include <sys/param.h>
     44 #include <sys/systm.h>
     45 #include <sys/device.h>
     46 #include <sys/kernel.h>
     47 #include <sys/device.h>
     48 
     49 #include <machine/autoconf.h>
     50 #include <machine/cpu.h>
     51 
     52 #include <hp300/dev/dioreg.h>
     53 #include <hp300/dev/diovar.h>
     54 
     55 #include <hp300/dev/diodevs.h>
     56 #include <hp300/dev/diodevs_data.h>
     57 
     58 extern	caddr_t internalhpib;
     59 
     60 int	dio_scodesize __P((struct dio_attach_args *));
     61 char	*dio_devinfo __P((struct dio_attach_args *, char *, size_t));
     62 
     63 int	diomatch __P((struct device *, struct cfdata *, void *));
     64 void	dioattach __P((struct device *, struct device *, void *));
     65 int	dioprint __P((void *, const char *));
     66 int	diosubmatch __P((struct device *, struct cfdata *, void *));
     67 
     68 struct cfattach dio_ca = {
     69 	sizeof(struct device), diomatch, dioattach
     70 };
     71 
     72 struct cfdriver dio_cd = {
     73 	NULL, "dio", DV_DULL
     74 };
     75 
     76 int
     77 diomatch(parent, match, aux)
     78 	struct device *parent;
     79 	struct cfdata *match;
     80 	void *aux;
     81 {
     82 	static int dio_matched = 0;
     83 
     84 	/* Allow only one instance. */
     85 	if (dio_matched)
     86 		return (0);
     87 
     88 	dio_matched = 1;
     89 	return (1);
     90 }
     91 
     92 void
     93 dioattach(parent, self, aux)
     94 	struct device *parent, *self;
     95 	void *aux;
     96 {
     97 	struct dio_attach_args da;
     98 	caddr_t pa, va;
     99 	int scode, scmax, didmap, scodesize;
    100 
    101 	scmax = DIO_SCMAX(machineid);
    102 	printf("\n");
    103 
    104 	for (scode = 0; scode < scmax; ) {
    105 		if (DIO_INHOLE(scode)) {
    106 			scode++;
    107 			continue;
    108 		}
    109 
    110 		didmap = 0;
    111 
    112 		/*
    113 		 * Temporarily map the space corresponding to
    114 		 * the current select code unless:
    115 		 *	- this is the internal hpib select code,
    116 		 *	- this is the console select code.
    117 		 */
    118 		pa = dio_scodetopa(scode);
    119 		if (scode == conscode)
    120 			va = conaddr;
    121 		else if ((scode == 7) && internalhpib)
    122 			va = internalhpib = (caddr_t)IIOV(pa);
    123 		else {
    124 			va = iomap(pa, NBPG);
    125 			if (va == NULL) {
    126 				printf("%s: can't map scode %d\n",
    127 				    self->dv_xname, scode);
    128 				scode++;
    129 				continue;
    130 			}
    131 			didmap = 1;
    132 		}
    133 
    134 		/* Check for hardware. */
    135 		if (badaddr(va)) {
    136 			if (didmap)
    137 				iounmap(va, NBPG);
    138 			scode++;
    139 			continue;
    140 		}
    141 
    142 		/* Fill out attach args. */
    143 		bzero(&da, sizeof(da));
    144 		da.da_scode = scode;
    145 		da.da_id = DIO_ID(va);
    146 
    147 		if (DIO_ISFRAMEBUFFER(da.da_id))
    148 			da.da_secid = DIO_SECID(va);
    149 
    150 		da.da_size = DIO_SIZE(scode, va);
    151 		scodesize = dio_scodesize(&da);
    152 		if (DIO_ISDIO(scode))
    153 			da.da_size *= scodesize;
    154 
    155 		/* No longer need the device to be mapped. */
    156 		if (didmap)
    157 			iounmap(va, NBPG);
    158 
    159 		/* Attach matching device. */
    160 		config_found_sm(self, &da, dioprint, diosubmatch);
    161 		scode += scodesize;
    162 	}
    163 }
    164 
    165 int
    166 diosubmatch(parent, cf, aux)
    167 	struct device *parent;
    168 	struct cfdata *cf;
    169 	void *aux;
    170 {
    171 	struct dio_attach_args *da = aux;
    172 
    173 	if (cf->diocf_scode != DIO_UNKNOWN_SCODE &&
    174 	    cf->diocf_scode != da->da_scode)
    175 		return (0);
    176 
    177 	return ((*cf->cf_attach->ca_match)(parent, cf, aux));
    178 }
    179 
    180 int
    181 dioprint(aux, pnp)
    182 	void *aux;
    183 	const char *pnp;
    184 {
    185 	struct dio_attach_args *da = aux;
    186 	char buf[128];
    187 
    188 	if (pnp)
    189 		printf("%s at %s", dio_devinfo(da, buf, sizeof(buf)), pnp);
    190 	printf(" scode %d", da->da_scode);
    191 	return (UNCONF);
    192 }
    193 
    194 /*
    195  * Convert a select code to a system physical address.
    196  */
    197 void *
    198 dio_scodetopa(scode)
    199 	int scode;
    200 {
    201 	u_long rval;
    202 
    203 	if (scode == 7 && internalhpib)
    204 		rval = DIO_IHPIBADDR;
    205 	else if (DIO_ISDIO(scode))
    206 		rval = DIO_BASE + (scode * DIO_DEVSIZE);
    207 	else if (DIO_ISDIOII(scode))
    208 		rval = DIOII_BASE + ((scode - DIOII_SCBASE) * DIOII_DEVSIZE);
    209 	else
    210 		rval = 0;
    211 
    212 	return ((void *)rval);
    213 }
    214 
    215 /*
    216  * Return the select code size for this device, defaulting to 1
    217  * if we don't know what kind of device we have.
    218  */
    219 int
    220 dio_scodesize(da)
    221 	struct dio_attach_args *da;
    222 {
    223 	int i;
    224 
    225 	/*
    226 	 * Deal with lame internal HP-IB controllers which don't have
    227 	 * consistent/reliable device ids.
    228 	 */
    229 	if (da->da_scode == 7 && internalhpib)
    230 		return (1);
    231 
    232 	/*
    233 	 * Find the dio_devdata matchind the primary id.
    234 	 * If we're a framebuffer, we also check the secondary id.
    235 	 */
    236 	for (i = 0; i < DIO_NDEVICES; i++) {
    237 		if (da->da_id == dio_devdatas[i].dd_id) {
    238 			if (DIO_ISFRAMEBUFFER(da->da_id)) {
    239 				if (da->da_secid == dio_devdatas[i].dd_secid) {
    240 					goto foundit;
    241 				}
    242 			} else {
    243 			foundit:
    244 				return (dio_devdatas[i].dd_nscode);
    245 			}
    246 		}
    247 	}
    248 
    249 	/*
    250 	 * Device is unknown.  Print a warning and assume a default.
    251 	 */
    252 	printf("WARNING: select code size unknown for id = 0x%x secid = 0x%x\n",
    253 	    da->da_id, da->da_secid);
    254 	return (1);
    255 }
    256 
    257 /*
    258  * Return a reasonable description of a DIO device.
    259  */
    260 char *
    261 dio_devinfo(da, buf, buflen)
    262 	struct dio_attach_args *da;
    263 	char *buf;
    264 	size_t buflen;
    265 {
    266 #ifdef DIOVERBOSE
    267 	int i;
    268 #endif
    269 
    270 	bzero(buf, buflen);
    271 
    272 	/*
    273 	 * Deal with lame internal HP-IB controllers which don't have
    274 	 * consistent/reliable device ids.
    275 	 */
    276 	if (da->da_scode == 7 && internalhpib) {
    277 		sprintf(buf, DIO_DEVICE_DESC_IHPIB);
    278 		return (buf);
    279 	}
    280 
    281 #ifdef DIOVERBOSE
    282 	/*
    283 	 * Find the description matching our primary id.
    284 	 * If we're a framebuffer, we also check the secondary id.
    285 	 */
    286 	for (i = 0; i < DIO_NDEVICES; i++) {
    287 		if (da->da_id == dio_devdescs[i].dd_id) {
    288 			if (DIO_ISFRAMEBUFFER(da->da_id)) {
    289 				if (da->da_secid == dio_devdescs[i].dd_secid) {
    290 					goto foundit;
    291 				}
    292 			} else {
    293 			foundit:
    294 				sprintf(buf, "%s", dio_devdescs[i].dd_desc);
    295 				return (buf);
    296 			}
    297 		}
    298 	}
    299 #endif /* DIOVERBOSE */
    300 
    301 	/*
    302 	 * Device is unknown.  Construct something reasonable.
    303 	 */
    304 	sprintf(buf, "device id = 0x%x secid = 0x%x",
    305 	    da->da_id, da->da_secid);
    306 	return (buf);
    307 }
    308