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