1 /* 2 * Copyright (c) 1996, Sujal M. Patel 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/time.h> 28 29 #include <err.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <fcntl.h> 34 #include <string.h> 35 36 #include <machine/cpufunc.h> 37 38 #include <isa/pnpreg.h> 39 40 #ifdef DEBUG 41 #define DEB(x) x 42 #else 43 #define DEB(x) 44 #endif 45 #define DDB(x) x 46 47 void 48 pnp_write(int d, u_char r) 49 { 50 outb(_PNP_ADDRESS, d); 51 outb(_PNP_WRITE_DATA, r); 52 } 53 54 /* The READ_DATA port that we are using currently */ 55 static int rd_port; 56 57 u_char 58 pnp_read(int d) 59 { 60 outb(_PNP_ADDRESS, d); 61 return inb( (rd_port << 2) + 3) & 0xff; 62 } 63 64 u_short 65 pnp_readw(int d) 66 { 67 int c = pnp_read(d) << 8 ; 68 c |= pnp_read(d+1); 69 return c; 70 } 71 72 int logdevs=0; 73 74 void DELAY(int i); 75 void send_Initiation_LFSR(void); 76 int get_serial(u_char *data); 77 int get_resource_info(u_char *buffer, int len); 78 int handle_small_res(u_char *resinfo, int item, int len); 79 void handle_large_res(u_char *resinfo, int item, int len); 80 void dump_resdata(u_char *data, int csn); 81 int isolation_protocol(void); 82 83 84 /* 85 * DELAY does accurate delaying in user-space. 86 * This function busy-waits. 87 */ 88 void 89 DELAY(int i) 90 { 91 struct timeval t; 92 long start, stop; 93 94 i *= 4; 95 96 gettimeofday (&t, NULL); 97 start = t.tv_sec * 1000000 + t.tv_usec; 98 do { 99 gettimeofday (&t, NULL); 100 stop = t.tv_sec * 1000000 + t.tv_usec; 101 } while (start + i > stop); 102 } 103 104 105 /* 106 * Send Initiation LFSR as described in "Plug and Play ISA Specification, 107 * Intel May 94." 108 */ 109 void 110 send_Initiation_LFSR(void) 111 { 112 int cur, i; 113 114 pnp_write(PNP_CONFIG_CONTROL, 0x2); 115 116 /* Reset the LSFR */ 117 outb(_PNP_ADDRESS, 0); 118 outb(_PNP_ADDRESS, 0); /* yes, we do need it twice! */ 119 120 cur = 0x6a; 121 122 for (i = 0; i < 32; i++) { 123 outb(_PNP_ADDRESS, cur); 124 cur = (cur >> 1) | (((cur ^ (cur >> 1)) << 7) & 0xff); 125 } 126 } 127 128 /* 129 * Get the device's serial number. Returns 1 if the serial is valid. 130 */ 131 int 132 get_serial(u_char *data) 133 { 134 int i, bit, valid = 0, sum = 0x6a; 135 136 bzero(data, sizeof(char) * 9); 137 138 for (i = 0; i < 72; i++) { 139 bit = inb((rd_port << 2) | 0x3) == 0x55; 140 DELAY(250); /* Delay 250 usec */ 141 142 /* Can't Short Circuit the next evaluation, so 'and' is last */ 143 bit = (inb((rd_port << 2) | 0x3) == 0xaa) && bit; 144 DELAY(250); /* Delay 250 usec */ 145 146 valid = valid || bit; 147 148 if (i < 64) 149 sum = (sum >> 1) | 150 (((sum ^ (sum >> 1) ^ bit) << 7) & 0xff); 151 152 data[i / 8] = (data[i / 8] >> 1) | (bit ? 0x80 : 0); 153 } 154 155 valid = valid && (data[8] == sum); 156 157 return valid; 158 } 159 160 161 /* 162 * Fill's the buffer with resource info from the device. 163 * Returns 0 if the device fails to report 164 */ 165 int 166 get_resource_info(u_char *buffer, int len) 167 { 168 int i, j; 169 170 for (i = 0; i < len; i++) { 171 outb(_PNP_ADDRESS, PNP_STATUS); 172 for (j = 0; j < 100; j++) { 173 if ((inb((rd_port << 2) | 0x3)) & 0x1) 174 break; 175 DELAY(1); 176 } 177 if (j == 100) { 178 printf("PnP device failed to report resource data\n"); 179 return 0; 180 } 181 outb(_PNP_ADDRESS, PNP_RESOURCE_DATA); 182 buffer[i] = inb((rd_port << 2) | 0x3); 183 DEB(printf("--- get_resource_info: got 0x%02x\n",(unsigned)buffer[i])); 184 } 185 return 1; 186 } 187 188 void 189 report_dma_info(int x) 190 { 191 char *s1=NULL, *s2=NULL, *s3=NULL, *s4=NULL, *s5=NULL; 192 193 switch (x & 0x3) { 194 case 0: 195 s1="8-bit"; 196 break; 197 case 1: 198 s1="8/16-bit"; 199 break; 200 case 2: 201 s1="16-bit"; 202 break; 203 #ifdef DIAGNOSTIC 204 case 3: 205 s1="Reserved"; 206 break; 207 #endif 208 } 209 210 s2 = (x & 0x4) ? "bus master" : "not a bus master"; 211 212 s3 = (x & 0x8) ? "count by byte" : ""; 213 214 s4 = (x & 0x10) ? "count by word" : ""; 215 216 switch ((x & 0x60) >> 5) { 217 case 0: 218 s5="Compatibility mode"; 219 break; 220 case 1: 221 s5="Type A"; 222 break; 223 case 2: 224 s5="Type B"; 225 break; 226 case 3: 227 s5="Type F"; 228 break; 229 } 230 printf("\t%s, %s, %s, %s, %s\n",s1,s2,s3,s4,s5); 231 } 232 233 234 void 235 report_memory_info(int x) 236 { 237 if (x & 0x1) 238 printf ("Memory Range: Writeable\n"); 239 else 240 printf ("Memory Range: Not writeable (ROM)\n"); 241 242 if (x & 0x2) 243 printf ("Memory Range: Read-cacheable, write-through\n"); 244 else 245 printf ("Memory Range: Non-cacheable\n"); 246 247 if (x & 0x4) 248 printf ("Memory Range: Decode supports high address\n"); 249 else 250 printf ("Memory Range: Decode supports range length\n"); 251 252 switch ((x & 0x18) >> 3) { 253 case 0: 254 printf ("Memory Range: 8-bit memory only\n"); 255 break; 256 case 1: 257 printf ("Memory Range: 16-bit memory only\n"); 258 break; 259 case 2: 260 printf ("Memory Range: 8-bit and 16-bit memory supported\n"); 261 break; 262 #ifdef DIAGNOSTIC 263 case 3: 264 printf ("Memory Range: Reserved\n"); 265 break; 266 #endif 267 } 268 269 if (x & 0x20) 270 printf ("Memory Range: Memory is shadowable\n"); 271 else 272 printf ("Memory Range: Memory is not shadowable\n"); 273 274 if (x & 0x40) 275 printf ("Memory Range: Memory is an expansion ROM\n"); 276 else 277 printf ("Memory Range: Memory is not an expansion ROM\n"); 278 279 #ifdef DIAGNOSTIC 280 if (x & 0x80) 281 printf ("Memory Range: Reserved (Device is brain-damaged)\n"); 282 #endif 283 } 284 285 286 /* 287 * Small Resource Tag Handler 288 * 289 * Returns 1 if checksum was valid (and an END_TAG was received). 290 * Returns -1 if checksum was invalid (and an END_TAG was received). 291 * Returns 0 for other tags. 292 */ 293 int 294 handle_small_res(u_char *resinfo, int item, int len) 295 { 296 int i; 297 298 DEB(printf("*** ITEM 0x%04x len %d detected\n", item, len)); 299 300 switch (item) { 301 default: 302 printf("*** ITEM 0x%02x detected\n", item); 303 break; 304 case PNP_TAG_VERSION: 305 printf("PnP Version %d.%d, Vendor Version %d\n", 306 resinfo[0] >> 4, resinfo[0] & (0xf), resinfo[1]); 307 break; 308 case PNP_TAG_LOGICAL_DEVICE: 309 printf("\nLogical Device ID: %c%c%c%02x%02x 0x%08x #%d\n", 310 ((resinfo[0] & 0x7c) >> 2) + 64, 311 (((resinfo[0] & 0x03) << 3) | 312 ((resinfo[1] & 0xe0) >> 5)) + 64, 313 (resinfo[1] & 0x1f) + 64, 314 resinfo[2], resinfo[3], *(int *)(resinfo), 315 logdevs++); 316 317 if (resinfo[4] & 0x1) 318 printf ("\tDevice powers up active\n"); /* XXX */ 319 if (resinfo[4] & 0x2) 320 printf ("\tDevice supports I/O Range Check\n"); 321 if (resinfo[4] > 0x3) 322 printf ("\tReserved register funcs %02x\n", 323 resinfo[4]); 324 325 if (len == 6) 326 printf("\tVendor register funcs %02x\n", resinfo[5]); 327 break; 328 case PNP_TAG_COMPAT_DEVICE: 329 printf("Compatible Device ID: %c%c%c%02x%02x (%08x)\n", 330 ((resinfo[0] & 0x7c) >> 2) + 64, 331 (((resinfo[0] & 0x03) << 3) | 332 ((resinfo[1] & 0xe0) >> 5)) + 64, 333 (resinfo[1] & 0x1f) + 64, 334 resinfo[2], resinfo[3], *(int *)resinfo); 335 break; 336 case PNP_TAG_IRQ_FORMAT: 337 printf(" IRQ: "); 338 339 for (i = 0; i < 8; i++) 340 if (resinfo[0] & (1<<i)) 341 printf("%d ", i); 342 for (i = 0; i < 8; i++) 343 if (resinfo[1] & (1<<i)) 344 printf("%d ", i + 8); 345 if (len == 3) { 346 if (resinfo[2] & 0x1) 347 printf("IRQ: High true edge sensitive\n"); 348 if (resinfo[2] & 0x2) 349 printf("IRQ: Low true edge sensitive\n"); 350 if (resinfo[2] & 0x4) 351 printf("IRQ: High true level sensitive\n"); 352 if (resinfo[2] & 0x8) 353 printf("IRQ: Low true level sensitive\n"); 354 } else { 355 printf(" - only one type (true/edge)\n"); 356 } 357 break; 358 case PNP_TAG_DMA_FORMAT: 359 printf(" DMA: channel(s) "); 360 for (i = 0; i < 8; i++) 361 if (resinfo[0] & (1<<i)) 362 printf("%d ", i); 363 printf ("\n"); 364 report_dma_info (resinfo[1]); 365 break; 366 case PNP_TAG_START_DEPENDANT: 367 printf("TAG Start DF\n"); 368 if (len == 1) { 369 switch (resinfo[0]) { 370 case 0: 371 printf("Good Configuration\n"); 372 break; 373 case 1: 374 printf("Acceptable Configuration\n"); 375 break; 376 case 2: 377 printf("Sub-optimal Configuration\n"); 378 break; 379 } 380 } 381 break; 382 case PNP_TAG_END_DEPENDANT: 383 printf("TAG End DF\n"); 384 break; 385 case PNP_TAG_IO_RANGE: 386 printf(" I/O Range 0x%x .. 0x%x, alignment 0x%x, len 0x%x\n", 387 resinfo[1] + (resinfo[2] << 8), 388 resinfo[3] + (resinfo[4] << 8), 389 resinfo[5], resinfo[6] ); 390 if (resinfo[0]) 391 printf("\t[16-bit addr]\n"); 392 else 393 printf("\t[not 16-bit addr]\n"); 394 break; 395 case PNP_TAG_IO_FIXED: 396 printf (" FIXED I/O base address 0x%x length 0x%x\n", 397 resinfo[0] + ( (resinfo[1] & 3 ) << 8), /* XXX */ 398 resinfo[2]); 399 break; 400 #ifdef DIAGNOSTIC 401 case PNP_TAG_RESERVED: 402 printf("Reserved Tag Detected\n"); 403 break; 404 #endif 405 case PNP_TAG_VENDOR: 406 printf("*** Small Vendor Tag Detected\n"); 407 break; 408 case PNP_TAG_END: 409 printf("End Tag\n\n"); 410 /* XXX Record and Verify Checksum */ 411 return 1; 412 break; 413 } 414 return 0; 415 } 416 417 418 void 419 handle_large_res(u_char *resinfo, int item, int len) 420 { 421 int i; 422 423 DEB(printf("*** Large ITEM %d len %d found\n", item, len)); 424 switch (item) { 425 case PNP_TAG_MEMORY_RANGE: 426 report_memory_info(resinfo[0]); 427 printf("Memory range minimum address: 0x%x\n", 428 (resinfo[1] << 8) + (resinfo[2] << 16)); 429 printf("Memory range maximum address: 0x%x\n", 430 (resinfo[3] << 8) + (resinfo[4] << 16)); 431 printf("Memory range base alignment: 0x%x\n", 432 (i = (resinfo[5] + (resinfo[6] << 8))) ? i : (1 << 16)); 433 printf("Memory range length: 0x%x\n", 434 (resinfo[7] + (resinfo[8] << 8)) * 256); 435 break; 436 case PNP_TAG_ID_ANSI: 437 printf("Device Description: "); 438 439 for (i = 0; i < len; i++) { 440 if (resinfo[i]) /* XXX */ 441 printf("%c", resinfo[i]); 442 } 443 printf("\n"); 444 break; 445 case PNP_TAG_ID_UNICODE: 446 printf("ID String Unicode Detected (Undefined)\n"); 447 break; 448 case PNP_TAG_LARGE_VENDOR: 449 printf("Large Vendor Defined Detected\n"); 450 break; 451 case PNP_TAG_MEMORY32_RANGE: 452 printf("32bit Memory Range Desc Unimplemented\n"); 453 break; 454 case PNP_TAG_MEMORY32_FIXED: 455 printf("32bit Fixed Location Desc Unimplemented\n"); 456 break; 457 #ifdef DIAGNOSTIC 458 case PNP_TAG_LARGE_RESERVED: 459 printf("Large Reserved Tag Detected\n"); 460 break; 461 #endif 462 } 463 } 464 465 466 /* 467 * Dump all the information about configurations. 468 */ 469 void 470 dump_resdata(u_char *data, int csn) 471 { 472 int i, large_len; 473 474 u_char tag, *resinfo; 475 476 DDB(printf("\nCard assigned CSN #%d\n", csn)); 477 printf("Vendor ID %c%c%c%02x%02x (0x%08x), Serial Number 0x%08x\n", 478 ((data[0] & 0x7c) >> 2) + 64, 479 (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64, 480 (data[1] & 0x1f) + 64, data[2], data[3], 481 *(int *)&(data[0]), 482 *(int *)&(data[4])); 483 484 pnp_write(PNP_SET_CSN, csn); /* Move this out of this function XXX */ 485 outb(_PNP_ADDRESS, PNP_STATUS); 486 487 /* Allows up to 1kb of Resource Info, Should be plenty */ 488 for (i = 0; i < 1024; i++) { 489 if (!get_resource_info(&tag, 1)) 490 break; 491 492 if (PNP_RES_TYPE(tag) == 0) { 493 /* Handle small resouce data types */ 494 495 resinfo = malloc(PNP_SRES_LEN(tag)); 496 if (!get_resource_info(resinfo, PNP_SRES_LEN(tag))) 497 break; 498 499 if (handle_small_res(resinfo, PNP_SRES_NUM(tag), PNP_SRES_LEN(tag)) == 1) 500 break; 501 free(resinfo); 502 } else { 503 /* Handle large resouce data types */ 504 u_char buf[2]; 505 if (!get_resource_info((char *)buf, 2)) 506 break; 507 large_len = (buf[1] << 8) + buf[0]; 508 509 resinfo = malloc(large_len); 510 if (!get_resource_info(resinfo, large_len)) 511 break; 512 513 handle_large_res(resinfo, PNP_LRES_NUM(tag), large_len); 514 free(resinfo); 515 } 516 } 517 printf("Successfully got %d resources, %d logical fdevs\n", i, 518 logdevs); 519 printf("-- card select # 0x%04x\n", pnp_read(PNP_SET_CSN)); 520 printf("\nCSN %c%c%c%02x%02x (0x%08x), Serial Number 0x%08x\n", 521 ((data[0] & 0x7c) >> 2) + 64, 522 (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64, 523 (data[1] & 0x1f) + 64, data[2], data[3], 524 *(int *)&(data[0]), 525 *(int *)&(data[4])); 526 527 for (i=0; i<logdevs; i++) { 528 int j; 529 530 pnp_write(PNP_SET_LDN, i); 531 532 printf("\nLogical device #%d\n", pnp_read(PNP_SET_LDN) ); 533 printf("IO: "); 534 for (j=0; j<8; j++) 535 printf(" 0x%02x%02x", pnp_read(PNP_IO_BASE_HIGH(j)), 536 pnp_read(PNP_IO_BASE_LOW(j))); 537 printf("\nIRQ %d %d\n", 538 pnp_read(PNP_IRQ_LEVEL(0)), pnp_read(PNP_IRQ_LEVEL(1)) ); 539 printf("DMA %d %d\n", 540 pnp_read(PNP_DMA_CHANNEL(0)), pnp_read(PNP_DMA_CHANNEL(1)) ); 541 printf("IO range check 0x%02x activate 0x%02x\n", 542 pnp_read(PNP_IO_RANGE_CHECK), pnp_read(PNP_ACTIVATE) ); 543 } 544 } 545 546 547 /* 548 * Run the isolation protocol. Use rd_port as the READ_DATA port 549 * value (caller should try multiple READ_DATA locations before giving 550 * up). Upon exiting, all cards are aware that they should use rd_port 551 * as the READ_DATA port; 552 * 553 */ 554 int 555 isolation_protocol(void) 556 { 557 int csn; 558 u_char data[9]; 559 560 send_Initiation_LFSR(); 561 562 /* Reset CSN for All Cards */ 563 pnp_write(PNP_CONFIG_CONTROL, 0x04); 564 565 for (csn = 1; (csn < PNP_MAX_CARDS); csn++) { 566 /* Wake up cards without a CSN */ 567 logdevs = 0 ; 568 pnp_write(PNP_WAKE, 0); 569 pnp_write(PNP_SET_RD_DATA, rd_port); 570 outb(_PNP_ADDRESS, PNP_SERIAL_ISOLATION); 571 DELAY(1000); /* Delay 1 msec */ 572 573 if (get_serial(data)) 574 dump_resdata(data, csn); 575 else 576 break; 577 } 578 return csn - 1; 579 } 580 581 582 int 583 main(int argc, char **argv) 584 { 585 int num_pnp_devs; 586 587 #ifdef __i386__ 588 /* Hey what about a i386_iopl() call :) */ 589 if (open("/dev/io", O_RDONLY) < 0) 590 errx(1, "can't get I/O privilege"); 591 #endif 592 593 printf("Checking for Plug-n-Play devices...\n"); 594 595 /* Try various READ_DATA ports from 0x203-0x3ff */ 596 for (rd_port = 0x80; (rd_port < 0xff); rd_port += 0x10) { 597 DEB(printf("Trying Read_Port at %x...\n", (rd_port << 2) | 0x3) ); 598 num_pnp_devs = isolation_protocol(); 599 if (num_pnp_devs) 600 break; 601 } 602 if (!num_pnp_devs) { 603 printf("No Plug-n-Play devices were found\n"); 604 return (0); 605 } 606 return (0); 607 } 608