Home | History | Annotate | Line # | Download | only in eisa
eisa_machdep.c revision 1.3
      1 /* $NetBSD: eisa_machdep.c,v 1.3 2000/08/11 00:43:20 thorpej Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2000 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 FOUNDATION OR CONTRIBUTORS
     30  * BE 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 #include <sys/cdefs.h>
     40 
     41 __KERNEL_RCSID(0, "$NetBSD: eisa_machdep.c,v 1.3 2000/08/11 00:43:20 thorpej Exp $");
     42 
     43 #include <sys/param.h>
     44 #include <sys/systm.h>
     45 #include <sys/device.h>
     46 #include <sys/malloc.h>
     47 #include <sys/queue.h>
     48 
     49 #include <machine/intr.h>
     50 #include <machine/rpb.h>
     51 
     52 #include <dev/eisa/eisareg.h>
     53 #include <dev/eisa/eisavar.h>
     54 
     55 #define	EISA_SLOT_HEADER_SIZE	31
     56 #define	EISA_SLOT_INFO_OFFSET	20
     57 
     58 #define	EISA_FUNC_INFO_OFFSET	34
     59 #define	EISA_CONFIG_BLOCK_SIZE	320
     60 
     61 #define	ECUF_TYPE_STRING	0x01
     62 #define	ECUF_MEM_ENTRY		0x02
     63 #define	ECUF_IRQ_ENTRY		0x04
     64 #define	ECUF_DMA_ENTRY		0x08
     65 #define	ECUF_IO_ENTRY		0x10
     66 #define	ECUF_INIT_ENTRY		0x20
     67 #define	ECUF_DISABLED		0x80
     68 
     69 #define	ECUF_SELECTIONS_SIZE	26
     70 #define	ECUF_TYPE_STRING_SIZE	80
     71 #define	ECUF_MEM_ENTRY_SIZE	7
     72 #define	ECUF_IRQ_ENTRY_SIZE	2
     73 #define	ECUF_DMA_ENTRY_SIZE	2
     74 #define	ECUF_IO_ENTRY_SIZE	3
     75 #define	ECUF_INIT_ENTRY_SIZE	60
     76 
     77 #define	ECUF_MEM_ENTRY_CNT	9
     78 #define	ECUF_IRQ_ENTRY_CNT	7
     79 #define	ECUF_DMA_ENTRY_CNT	4
     80 #define	ECUF_IO_ENTRY_CNT	20
     81 
     82 /*
     83  * EISA configuration space, as set up by the ECU, may be sparse.
     84  */
     85 bus_size_t eisa_config_stride;
     86 paddr_t eisa_config_addr;		/* defaults to 0 */
     87 paddr_t eisa_config_header_addr;
     88 
     89 struct ecu_mem {
     90 	SIMPLEQ_ENTRY(ecu_mem) ecum_list;
     91 	struct eisa_cfg_mem ecum_mem;
     92 };
     93 
     94 struct ecu_irq {
     95 	SIMPLEQ_ENTRY(ecu_irq) ecui_list;
     96 	struct eisa_cfg_irq ecui_irq;
     97 };
     98 
     99 struct ecu_dma {
    100 	SIMPLEQ_ENTRY(ecu_dma) ecud_list;
    101 	struct eisa_cfg_dma ecud_dma;
    102 };
    103 
    104 struct ecu_io {
    105 	SIMPLEQ_ENTRY(ecu_io) ecuio_list;
    106 	struct eisa_cfg_io ecuio_io;
    107 };
    108 
    109 struct ecu_func {
    110 	SIMPLEQ_ENTRY(ecu_func) ecuf_list;
    111 	int ecuf_funcno;
    112 	u_int32_t ecuf_id;
    113 	u_int16_t ecuf_slot_info;
    114 	u_int16_t ecuf_cfg_ext;
    115 	u_int8_t ecuf_selections[ECUF_SELECTIONS_SIZE];
    116 	u_int8_t ecuf_func_info;
    117 	u_int8_t ecuf_type_string[ECUF_TYPE_STRING_SIZE];
    118 	u_int8_t ecuf_init[ECUF_INIT_ENTRY_SIZE];
    119 	SIMPLEQ_HEAD(, ecu_mem) ecuf_mem;
    120 	SIMPLEQ_HEAD(, ecu_irq) ecuf_irq;
    121 	SIMPLEQ_HEAD(, ecu_dma) ecuf_dma;
    122 	SIMPLEQ_HEAD(, ecu_io) ecuf_io;
    123 };
    124 
    125 struct ecu_data {
    126 	SIMPLEQ_ENTRY(ecu_data) ecud_list;
    127 	int ecud_slot;
    128 	u_int8_t ecud_eisaid[EISA_IDSTRINGLEN];
    129 	u_int32_t ecud_offset;
    130 
    131 	/* General slot info. */
    132 	u_int8_t ecud_slot_info;
    133 	u_int16_t ecud_ecu_major_rev;
    134 	u_int16_t ecud_ecu_minor_rev;
    135 	u_int16_t ecud_cksum;
    136 	u_int16_t ecud_ndevfuncs;
    137 	u_int8_t ecud_funcinfo;
    138 	u_int32_t ecud_comp_id;
    139 
    140 	/* The functions */
    141 	SIMPLEQ_HEAD(, ecu_func) ecud_funcs;
    142 };
    143 
    144 SIMPLEQ_HEAD(, ecu_data) ecu_data_list =
    145     SIMPLEQ_HEAD_INITIALIZER(ecu_data_list);
    146 
    147 static void
    148 ecuf_init(struct ecu_func *ecuf)
    149 {
    150 
    151 	memset(ecuf, 0, sizeof(*ecuf));
    152 	SIMPLEQ_INIT(&ecuf->ecuf_mem);
    153 	SIMPLEQ_INIT(&ecuf->ecuf_irq);
    154 	SIMPLEQ_INIT(&ecuf->ecuf_dma);
    155 	SIMPLEQ_INIT(&ecuf->ecuf_io);
    156 }
    157 
    158 static void
    159 eisa_parse_mem(struct ecu_func *ecuf, u_int8_t *dp)
    160 {
    161 	struct ecu_mem *ecum;
    162 	int i;
    163 
    164 	for (i = 0; i < ECUF_MEM_ENTRY_CNT; i++) {
    165 		ecum = malloc(sizeof(*ecum), M_DEVBUF, M_WAITOK);
    166 
    167 		ecum->ecum_mem.ecm_isram = dp[0] & 0x1;
    168 		ecum->ecum_mem.ecm_unitsize = dp[1] & 0x3;
    169 		ecum->ecum_mem.ecm_decode = (dp[1] >> 2) & 0x3;
    170 		ecum->ecum_mem.ecm_addr =
    171 		    (dp[2] | (dp[3] << 8) | (dp[4] << 16)) << 8;
    172 		ecum->ecum_mem.ecm_size = (dp[5] | (dp[6] << 8)) << 10;
    173 		if (ecum->ecum_mem.ecm_size == 0)
    174 			ecum->ecum_mem.ecm_size = (1 << 26);
    175 		SIMPLEQ_INSERT_TAIL(&ecuf->ecuf_mem, ecum, ecum_list);
    176 
    177 #if 0
    178 		printf("MEM 0x%lx 0x%lx %d %d %d\n",
    179 		    ecum->ecum_mem.ecm_addr, ecum->ecum_mem.ecm_size,
    180 		    ecum->ecum_mem.ecm_isram, ecum->ecum_mem.ecm_unitsize,
    181 		    ecum->ecum_mem.ecm_decode);
    182 #endif
    183 
    184 		if ((dp[0] & 0x80) == 0)
    185 			break;
    186 		dp += ECUF_MEM_ENTRY_SIZE;
    187 	}
    188 }
    189 
    190 static void
    191 eisa_parse_irq(struct ecu_func *ecuf, u_int8_t *dp)
    192 {
    193 	struct ecu_irq *ecui;
    194 	int i;
    195 
    196 	for (i = 0; i < ECUF_IRQ_ENTRY_CNT; i++) {
    197 		ecui = malloc(sizeof(*ecui), M_DEVBUF, M_WAITOK);
    198 
    199 		ecui->ecui_irq.eci_irq = dp[0] & 0xf;
    200 		ecui->ecui_irq.eci_ist = (dp[0] & 0x20) ? IST_LEVEL : IST_EDGE;
    201 		ecui->ecui_irq.eci_shared = (dp[0] & 0x40) ? 1 : 0;
    202 		SIMPLEQ_INSERT_TAIL(&ecuf->ecuf_irq, ecui, ecui_list);
    203 
    204 #if 0
    205 		printf("IRQ %d %s%s\n", ecui->eci_irq.ecui_irq,
    206 		    ecui->eci_irq.ecui_ist == IST_LEVEL ? "level" : "edge",
    207 		    ecui->eci_irq.ecui_shared ? " shared" : "");
    208 #endif
    209 
    210 		if ((dp[0] & 0x80) == 0)
    211 			break;
    212 		dp += ECUF_IRQ_ENTRY_SIZE;
    213 	}
    214 }
    215 
    216 static void
    217 eisa_parse_dma(struct ecu_func *ecuf, u_int8_t *dp)
    218 {
    219 	struct ecu_dma *ecud;
    220 	int i;
    221 
    222 	for (i = 0; i < ECUF_DMA_ENTRY_CNT; i++) {
    223 		ecud = malloc(sizeof(*ecud), M_DEVBUF, M_WAITOK);
    224 
    225 		ecud->ecud_dma.ecd_drq = dp[0] & 0x7;
    226 		ecud->ecud_dma.ecd_shared = dp[0] & 0x40;
    227 		ecud->ecud_dma.ecd_size = (dp[1] >> 2) & 0x3;
    228 		ecud->ecud_dma.ecd_timing = (dp[1] >> 4) & 0x3;
    229 		SIMPLEQ_INSERT_TAIL(&ecuf->ecuf_dma, ecud, ecud_list);
    230 
    231 #if 0
    232 		printf("DRQ %d%s %d %d\n", ecud->ecud_dma.ecd_drq,
    233 		    ecud->ecud_dma.ecd_shared ? " shared" : "",
    234 		    ecud->ecud_dma.ecd_size, ecud->ecud_dma.ecd_timing);
    235 #endif
    236 
    237 		if ((dp[0] & 0x80) == 0)
    238 			break;
    239 		dp += ECUF_DMA_ENTRY_SIZE;
    240 	}
    241 }
    242 
    243 static void
    244 eisa_parse_io(struct ecu_func *ecuf, u_int8_t *dp)
    245 {
    246 	struct ecu_io *ecuio;
    247 	int i;
    248 
    249 	for (i = 0; i < ECUF_IO_ENTRY_CNT; i++) {
    250 		ecuio = malloc(sizeof(*ecuio), M_DEVBUF, M_WAITOK);
    251 
    252 		ecuio->ecuio_io.ecio_addr = dp[1] | (dp[2] << 8);
    253 		ecuio->ecuio_io.ecio_size = (dp[0] & 0x1f) + 1;
    254 		ecuio->ecuio_io.ecio_shared = (dp[0] & 0x40) ? 1 : 0;
    255 
    256 #if 0
    257 		printf("IO 0x%lx 0x%lx%s\n", ecuio->ecuio_io.ecio_addr,
    258 		    ecuio->ecuio_io.ecio_size,
    259 		    ecuio->ecuio_io.ecio_shared ? " shared" : "");
    260 #endif
    261 
    262 		if ((dp[0] & 0x80) == 0)
    263 			break;
    264 		dp += ECUF_IO_ENTRY_SIZE;
    265 	}
    266 }
    267 
    268 static void
    269 eisa_read_config_bytes(paddr_t addr, void *buf, size_t count)
    270 {
    271 	const u_int8_t *src = (const u_int8_t *)ALPHA_PHYS_TO_K0SEG(addr);
    272 	u_int8_t *dst = buf;
    273 
    274 	for (; count != 0; count--) {
    275 		*dst++ = *src;
    276 		src += eisa_config_stride;
    277 	}
    278 }
    279 
    280 static void
    281 eisa_read_config_word(paddr_t addr, u_int32_t *valp)
    282 {
    283 	const u_int8_t *src = (const u_int8_t *)ALPHA_PHYS_TO_K0SEG(addr);
    284 	u_int32_t val = 0;
    285 	int i;
    286 
    287 	for (i = 0; i < sizeof(val); i++) {
    288 		val |= (u_int)(*src << (i * 8));
    289 		src += eisa_config_stride;
    290 	}
    291 
    292 	*valp = val;
    293 }
    294 
    295 static size_t
    296 eisa_uncompress(void *cbufp, void *ucbufp, size_t count)
    297 {
    298 	const u_int8_t *cbuf = cbufp;
    299 	u_int8_t *ucbuf = ucbufp;
    300 	u_int zeros = 0;
    301 
    302 	while (count--) {
    303 		if (zeros) {
    304 			zeros--;
    305 			*ucbuf++ = '\0';
    306 		} else if (*cbuf == '\0') {
    307 			*ucbuf++ = *cbuf++;
    308 			zeros = *cbuf++ - 1;
    309 		} else
    310 			*ucbuf++ = *cbuf++;
    311 	}
    312 
    313 	return ((size_t)cbuf - (size_t)cbufp);
    314 }
    315 
    316 void
    317 eisa_init()
    318 {
    319 	struct ecu_data *ecud;
    320 	paddr_t cfgaddr;
    321 	u_int32_t offset;
    322 	u_int8_t eisaid[EISA_IDSTRINGLEN];
    323 	u_int8_t *cdata, *data;
    324 	u_int8_t *cdp, *dp;
    325 	struct ecu_func *ecuf;
    326 	int i, func;
    327 
    328 	/*
    329 	 * Locate EISA configuration space.
    330 	 */
    331 	if (hwrpb->rpb_condat_off == 0UL ||
    332 	    (hwrpb->rpb_condat_off >> 63) != 0) {
    333 		printf(": WARNING: no EISA configuration space");
    334 		return;
    335 	}
    336 
    337 	if (eisa_config_header_addr) {
    338 		printf("\n");
    339 		panic("eisa_init: EISA config space already initialized");
    340 	}
    341 
    342 	eisa_config_header_addr = hwrpb->rpb_condat_off;
    343 #if 0
    344 	printf("\nEISA config header at 0x%lx\n", eisa_config_header_addr);
    345 #endif
    346 	if (eisa_config_stride == 0)
    347 		eisa_config_stride = 1;
    348 
    349 	/*
    350 	 * Read the slot headers, and allocate config structures for
    351 	 * valid slots.
    352 	 */
    353 	for (cfgaddr = eisa_config_header_addr, i = 0; i < 16 /* XXX */; i++) {
    354 		eisa_read_config_bytes(cfgaddr, eisaid, sizeof(eisaid));
    355 		eisaid[EISA_IDSTRINGLEN - 1] = '\0';	/* sanity */
    356 		cfgaddr += sizeof(eisaid) * eisa_config_stride;
    357 		eisa_read_config_word(cfgaddr, &offset);
    358 		cfgaddr += sizeof(offset) * eisa_config_stride;
    359 
    360 		if (offset != 0) {
    361 #if 0
    362 			printf("SLOT %d: offset 0x%08x eisaid %s\n",
    363 			    i, offset, eisaid);
    364 #endif
    365 			ecud = malloc(sizeof(*ecud), M_DEVBUF, M_WAITOK);
    366 			memset(ecud, 0, sizeof(*ecud));
    367 
    368 			SIMPLEQ_INIT(&ecud->ecud_funcs);
    369 
    370 			ecud->ecud_slot = i;
    371 			memcpy(ecud->ecud_eisaid, eisaid, sizeof(eisaid));
    372 			ecud->ecud_offset = offset;
    373 			SIMPLEQ_INSERT_TAIL(&ecu_data_list, ecud, ecud_list);
    374 		}
    375 	}
    376 
    377 	/*
    378 	 * Now traverse the valid slots and read the info.
    379 	 */
    380 
    381 	cdata = malloc(512, M_TEMP, M_WAITOK);
    382 	data = malloc(512, M_TEMP, M_WAITOK);
    383 
    384 	for (ecud = SIMPLEQ_FIRST(&ecu_data_list); ecud != NULL;
    385 	     ecud = SIMPLEQ_NEXT(ecud, ecud_list)) {
    386 		cfgaddr = eisa_config_addr + ecud->ecud_offset;
    387 		eisa_read_config_bytes(cfgaddr, &cdata[0], 1);
    388 		cfgaddr += eisa_config_stride;
    389 
    390 		for (i = 1; ; cfgaddr += eisa_config_stride, i++) {
    391 			eisa_read_config_bytes(cfgaddr, &cdata[i], 1);
    392 			if (cdata[i - 1] == 0 && cdata[i] == 0)
    393 				break;
    394 		}
    395 		i++;	/* index -> length */
    396 
    397 #if 0
    398 		printf("SLOT %d compressed data length %d:",
    399 		    ecud->ecud_slot, i);
    400 		{
    401 			int j;
    402 
    403 			for (j = 0; j < i; j++) {
    404 				if ((j % 16) == 0)
    405 					printf("\n");
    406 				printf("0x%02x ", cdata[j]);
    407 			}
    408 			printf("\n");
    409 		}
    410 #endif
    411 
    412 		cdp = cdata;
    413 		dp = data;
    414 
    415 		/* Uncompress the slot header. */
    416 		cdp += eisa_uncompress(cdp, dp, EISA_SLOT_HEADER_SIZE);
    417 #if 0
    418 		printf("SLOT %d uncompressed header data:",
    419 		    ecud->ecud_slot);
    420 		{
    421 			int j;
    422 
    423 			for (j = 0; j < EISA_SLOT_HEADER_SIZE; j++) {
    424 				if ((j % 16) == 0)
    425 					printf("\n");
    426 				printf("0x%02x ", dp[j]);
    427 			}
    428 			printf("\n");
    429 		}
    430 #endif
    431 
    432 		dp = &data[EISA_SLOT_INFO_OFFSET];
    433 		ecud->ecud_slot_info = *dp++;
    434 		ecud->ecud_ecu_major_rev = *dp++;
    435 		ecud->ecud_ecu_minor_rev = *dp++;
    436 		memcpy(&ecud->ecud_cksum, dp, sizeof(ecud->ecud_cksum));
    437 		dp += sizeof(ecud->ecud_cksum);
    438 		ecud->ecud_ndevfuncs = *dp++;
    439 		ecud->ecud_funcinfo = *dp++;
    440 		memcpy(&ecud->ecud_comp_id, dp, sizeof(ecud->ecud_comp_id));
    441 		dp += sizeof(ecud->ecud_comp_id);
    442 
    443 #if 0
    444 		printf("SLOT %d: ndevfuncs %d\n", ecud->ecud_slot,
    445 		    ecud->ecud_ndevfuncs);
    446 #endif
    447 
    448 		for (func = 0; func < ecud->ecud_ndevfuncs; func++) {
    449 			dp = data;
    450 			cdp += eisa_uncompress(cdp, dp, EISA_CONFIG_BLOCK_SIZE);
    451 #if 0
    452 			printf("SLOT %d:%d uncompressed data:",
    453 			    ecud->ecud_slot, func);
    454 			{
    455 				int j;
    456 
    457 				for (j = 0; i < EISA_CONFIG_BLOCK_SIZE; j++) {
    458 					if ((j % 16) == 0)
    459 						printf("\n");
    460 					printf("0x%02x ", dp[j]);
    461 				}
    462 				printf("\n");
    463 			}
    464 #endif
    465 
    466 			/* Skip disabled functions. */
    467 			if (dp[EISA_FUNC_INFO_OFFSET] & ECUF_DISABLED) {
    468 				printf("SLOT %d:%d disabled\n",
    469 				    ecud->ecud_slot, func);
    470 				continue;
    471 			}
    472 
    473 			ecuf = malloc(sizeof(*ecuf), M_DEVBUF, M_WAITOK);
    474 			ecuf_init(ecuf);
    475 			ecuf->ecuf_funcno = func;
    476 			SIMPLEQ_INSERT_TAIL(&ecud->ecud_funcs, ecuf,
    477 			    ecuf_list);
    478 
    479 			memcpy(&ecuf->ecuf_id, dp, sizeof(ecuf->ecuf_id));
    480 			dp += sizeof(ecuf->ecuf_id);
    481 
    482 			memcpy(&ecuf->ecuf_slot_info, dp,
    483 			    sizeof(ecuf->ecuf_slot_info));
    484 			dp += sizeof(ecuf->ecuf_slot_info);
    485 
    486 			memcpy(&ecuf->ecuf_cfg_ext, dp,
    487 			    sizeof(ecuf->ecuf_cfg_ext));
    488 			dp += sizeof(ecuf->ecuf_cfg_ext);
    489 
    490 			memcpy(&ecuf->ecuf_selections, dp,
    491 			    sizeof(ecuf->ecuf_selections));
    492 			dp += sizeof(ecuf->ecuf_selections);
    493 
    494 			memcpy(&ecuf->ecuf_func_info, dp,
    495 			    sizeof(ecuf->ecuf_func_info));
    496 			dp += sizeof(ecuf->ecuf_func_info);
    497 
    498 			if (ecuf->ecuf_func_info & ECUF_TYPE_STRING)
    499 				memcpy(ecuf->ecuf_type_string, dp,
    500 				    sizeof(ecuf->ecuf_type_string));
    501 			dp += sizeof(ecuf->ecuf_type_string);
    502 
    503 			if (ecuf->ecuf_func_info & ECUF_MEM_ENTRY)
    504 				eisa_parse_mem(ecuf, dp);
    505 			dp += ECUF_MEM_ENTRY_SIZE * ECUF_MEM_ENTRY_CNT;
    506 
    507 			if (ecuf->ecuf_func_info & ECUF_IRQ_ENTRY)
    508 				eisa_parse_irq(ecuf, dp);
    509 			dp += ECUF_IRQ_ENTRY_SIZE * ECUF_IRQ_ENTRY_CNT;
    510 
    511 			if (ecuf->ecuf_func_info & ECUF_DMA_ENTRY)
    512 				eisa_parse_dma(ecuf, dp);
    513 			dp += ECUF_DMA_ENTRY_SIZE * ECUF_DMA_ENTRY_CNT;
    514 
    515 			if (ecuf->ecuf_func_info & ECUF_IO_ENTRY)
    516 				eisa_parse_io(ecuf, dp);
    517 			dp += ECUF_IO_ENTRY_SIZE * ECUF_IO_ENTRY_CNT;
    518 
    519 			if (ecuf->ecuf_func_info & ECUF_INIT_ENTRY)
    520 				memcpy(ecuf->ecuf_init, dp,
    521 				    sizeof(ecuf->ecuf_init));
    522 			dp += sizeof(ecuf->ecuf_init);
    523 		}
    524 	}
    525 
    526 	free(cdata, M_TEMP);
    527 	free(data, M_TEMP);
    528 }
    529 
    530 static struct ecu_data *
    531 eisa_lookup_data(int slot)
    532 {
    533 	struct ecu_data *ecud;
    534 
    535 	for (ecud = SIMPLEQ_FIRST(&ecu_data_list); ecud != NULL;
    536 	     ecud = SIMPLEQ_NEXT(ecud, ecud_list)) {
    537 		if (ecud->ecud_slot == slot)
    538 			return (ecud);
    539 	}
    540 	return (NULL);
    541 }
    542 
    543 static struct ecu_func *
    544 eisa_lookup_func(int slot, int func)
    545 {
    546 	struct ecu_data *ecud;
    547 	struct ecu_func *ecuf;
    548 
    549 	ecud = eisa_lookup_data(slot);
    550 	if (ecud == NULL)
    551 		return (NULL);
    552 
    553 	for (ecuf = SIMPLEQ_FIRST(&ecud->ecud_funcs); ecuf != NULL;
    554 	     ecuf = SIMPLEQ_NEXT(ecuf, ecuf_list)) {
    555 		if (ecuf->ecuf_funcno == func)
    556 			return (ecuf);
    557 	}
    558 	return (NULL);
    559 }
    560 
    561 int
    562 eisa_conf_read_mem(eisa_chipset_tag_t ec, int slot, int func, int entry,
    563     struct eisa_cfg_mem *dp)
    564 {
    565 	struct ecu_func *ecuf;
    566 	struct ecu_mem *ecum;
    567 
    568 	ecuf = eisa_lookup_func(slot, func);
    569 	if (ecuf == NULL)
    570 		return (ENOENT);
    571 
    572 	for (ecum = SIMPLEQ_FIRST(&ecuf->ecuf_mem); ecum != NULL;
    573 	     ecum = SIMPLEQ_NEXT(ecum, ecum_list)) {
    574 		if (entry-- == 0)
    575 			break;
    576 	}
    577 	if (ecum == NULL)
    578 		return (ENOENT);
    579 
    580 	*dp = ecum->ecum_mem;
    581 	return (0);
    582 }
    583 
    584 int
    585 eisa_conf_read_irq(eisa_chipset_tag_t ec, int slot, int func, int entry,
    586     struct eisa_cfg_irq *dp)
    587 {
    588 	struct ecu_func *ecuf;
    589 	struct ecu_irq *ecui;
    590 
    591 	ecuf = eisa_lookup_func(slot, func);
    592 	if (ecuf == NULL)
    593 		return (ENOENT);
    594 
    595 	for (ecui = SIMPLEQ_FIRST(&ecuf->ecuf_irq); ecui != NULL;
    596 	     ecui = SIMPLEQ_NEXT(ecui, ecui_list)) {
    597 		if (entry-- == 0)
    598 			break;
    599 	}
    600 	if (ecui == NULL)
    601 		return (ENOENT);
    602 
    603 	*dp = ecui->ecui_irq;
    604 	return (0);
    605 }
    606 
    607 int
    608 eisa_conf_read_dma(eisa_chipset_tag_t ec, int slot, int func, int entry,
    609     struct eisa_cfg_dma *dp)
    610 {
    611 	struct ecu_func *ecuf;
    612 	struct ecu_dma *ecud;
    613 
    614 	ecuf = eisa_lookup_func(slot, func);
    615 	if (ecuf == NULL)
    616 		return (ENOENT);
    617 
    618 	for (ecud = SIMPLEQ_FIRST(&ecuf->ecuf_dma); ecud != NULL;
    619 	     ecud = SIMPLEQ_NEXT(ecud, ecud_list)) {
    620 		if (entry-- == 0)
    621 			break;
    622 	}
    623 	if (ecud == NULL)
    624 		return (ENOENT);
    625 
    626 	*dp = ecud->ecud_dma;
    627 	return (0);
    628 }
    629 
    630 int
    631 eisa_conf_read_io(eisa_chipset_tag_t ec, int slot, int func, int entry,
    632     struct eisa_cfg_io *dp)
    633 {
    634 	struct ecu_func *ecuf;
    635 	struct ecu_io *ecuio;
    636 
    637 	ecuf = eisa_lookup_func(slot, func);
    638 	if (ecuf == NULL)
    639 		return (ENOENT);
    640 
    641 	for (ecuio = SIMPLEQ_FIRST(&ecuf->ecuf_io); ecuio != NULL;
    642 	     ecuio = SIMPLEQ_NEXT(ecuio, ecuio_list)) {
    643 		if (entry-- == 0)
    644 			break;
    645 	}
    646 	if (ecuio == NULL)
    647 		return (ENOENT);
    648 
    649 	*dp = ecuio->ecuio_io;
    650 	return (0);
    651 }
    652