pnpinfo.c revision 124125
1121986Sjhb/* 2121986Sjhb * Copyright (c) 1996, Sujal M. Patel 3121986Sjhb * All rights reserved. 4121986Sjhb * 5121986Sjhb * Redistribution and use in source and binary forms, with or without 6121986Sjhb * modification, are permitted provided that the following conditions 7121986Sjhb * are met: 8121986Sjhb * 1. Redistributions of source code must retain the above copyright 9121986Sjhb * notice, this list of conditions and the following disclaimer. 10121986Sjhb * 2. Redistributions in binary form must reproduce the above copyright 11121986Sjhb * notice, this list of conditions and the following disclaimer in the 12121986Sjhb * documentation and/or other materials provided with the distribution. 13121986Sjhb * 14121986Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15121986Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16121986Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17121986Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18121986Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19121986Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20121986Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21121986Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22121986Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23121986Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24121986Sjhb * SUCH DAMAGE. 25121986Sjhb */ 26121986Sjhb 27121986Sjhb#include <sys/cdefs.h> 28121986Sjhb__FBSDID("$FreeBSD: head/contrib/pnpinfo/pnpinfo.c 124125 2004-01-04 11:11:02Z charnier $"); 29121986Sjhb 30121986Sjhb#include <sys/time.h> 31121986Sjhb 32121986Sjhb#include <err.h> 33121986Sjhb#include <stdio.h> 34121986Sjhb#include <stdlib.h> 35121986Sjhb#include <unistd.h> 36167240Sjhb#include <fcntl.h> 37121986Sjhb#include <string.h> 38167240Sjhb 39121986Sjhb#include <machine/cpufunc.h> 40148538Sjhb 41121986Sjhb#include <isa/pnpreg.h> 42167240Sjhb 43167240Sjhb#ifdef DEBUG 44167240Sjhb#define DEB(x) x 45121986Sjhb#else 46121986Sjhb#define DEB(x) 47121986Sjhb#endif 48214631Sjhb#define DDB(x) x 49121986Sjhb 50121986Sjhbvoid 51121986Sjhbpnp_write(int d, u_char r) 52167747Sjhb{ 53121986Sjhb outb (_PNP_ADDRESS, d); 54121986Sjhb outb (_PNP_WRITE_DATA, r); 55121986Sjhb} 56121986Sjhb 57121986Sjhb/* The READ_DATA port that we are using currently */ 58121986Sjhbstatic int rd_port; 59121986Sjhb 60151979Sjhbu_char 61151979Sjhbpnp_read(int d) 62151979Sjhb{ 63151979Sjhb outb(_PNP_ADDRESS, d); 64121986Sjhb return inb( (rd_port << 2) + 3) & 0xff; 65151897Srwatson} 66121986Sjhb 67121986Sjhbu_short 68151979Sjhbpnp_readw(int d) 69151979Sjhb{ 70151979Sjhb int c = pnp_read(d) << 8 ; 71151979Sjhb c |= pnp_read(d+1); 72151979Sjhb return c; 73151979Sjhb} 74151979Sjhb 75152461Sandreint logdevs=0; 76152461Sandre 77152461Sandrevoid DELAY __P((int i)); 78152461Sandrevoid send_Initiation_LFSR(); 79121986Sjhbint get_serial __P((u_char *data)); 80121986Sjhbint get_resource_info __P((u_char *buffer, int len)); 81121986Sjhbint handle_small_res __P((u_char *resinfo, int item, int len)); 82121986Sjhbvoid handle_large_res __P((u_char *resinfo, int item, int len)); 83151979Sjhbvoid dump_resdata __P((u_char *data, int csn)); 84122124Sjhbint isolation_protocol(); 85122124Sjhb 86156124Sjhb 87122124Sjhb/* 88122124Sjhb * DELAY does accurate delaying in user-space. 89122124Sjhb * This function busy-waits. 90130980Sjhb */ 91157541Sjhbvoid 92121986SjhbDELAY (int i) 93121986Sjhb{ 94121986Sjhb struct timeval t; 95121986Sjhb long start, stop; 96121986Sjhb 97121986Sjhb i *= 4; 98121986Sjhb 99121986Sjhb gettimeofday (&t, NULL); 100121986Sjhb start = t.tv_sec * 1000000 + t.tv_usec; 101167747Sjhb do { 102121986Sjhb gettimeofday (&t, NULL); 103121986Sjhb stop = t.tv_sec * 1000000 + t.tv_usec; 104121986Sjhb } while (start + i > stop); 105121986Sjhb} 106121986Sjhb 107121986Sjhb 108130980Sjhb/* 109151979Sjhb * Send Initiation LFSR as described in "Plug and Play ISA Specification, 110121986Sjhb * Intel May 94." 111133017Sscottl */ 112121986Sjhbvoid 113121986Sjhbsend_Initiation_LFSR() 114169391Sjhb{ 115121986Sjhb int cur, i; 116121986Sjhb 117128931Sjhb pnp_write(PNP_CONFIG_CONTROL, 0x2); 118128931Sjhb 119163219Sjhb /* Reset the LSFR */ 120195249Sjhb outb(_PNP_ADDRESS, 0); 121129964Sjhb outb(_PNP_ADDRESS, 0); /* yes, we do need it twice! */ 122121986Sjhb 123129097Sjhb cur = 0x6a; 124121986Sjhb 125121986Sjhb for (i = 0; i < 32; i++) { 126169391Sjhb outb(_PNP_ADDRESS, cur); 127169391Sjhb cur = (cur >> 1) | (((cur ^ (cur >> 1)) << 7) & 0xff); 128156124Sjhb } 129121986Sjhb} 130156124Sjhb 131156124Sjhb/* 132156124Sjhb * Get the device's serial number. Returns 1 if the serial is valid. 133248085Smarius */ 134148538Sjhbint 135148538Sjhbget_serial(u_char *data) 136148538Sjhb{ 137148538Sjhb int i, bit, valid = 0, sum = 0x6a; 138148538Sjhb 139133017Sscottl bzero(data, sizeof(char) * 9); 140133017Sscottl 141133017Sscottl for (i = 0; i < 72; i++) { 142133017Sscottl bit = inb((rd_port << 2) | 0x3) == 0x55; 143133017Sscottl DELAY(250); /* Delay 250 usec */ 144133017Sscottl 145121986Sjhb /* Can't Short Circuit the next evaluation, so 'and' is last */ 146121986Sjhb bit = (inb((rd_port << 2) | 0x3) == 0xaa) && bit; 147121986Sjhb DELAY(250); /* Delay 250 usec */ 148121986Sjhb 149121986Sjhb valid = valid || bit; 150121986Sjhb 151121986Sjhb if (i < 64) 152121986Sjhb sum = (sum >> 1) | 153121986Sjhb (((sum ^ (sum >> 1) ^ bit) << 7) & 0xff); 154121986Sjhb 155121986Sjhb data[i / 8] = (data[i / 8] >> 1) | (bit ? 0x80 : 0); 156121986Sjhb } 157121986Sjhb 158121986Sjhb valid = valid && (data[8] == sum); 159121986Sjhb 160121986Sjhb return valid; 161121986Sjhb} 162121986Sjhb 163130980Sjhb 164130980Sjhb/* 165130980Sjhb * Fill's the buffer with resource info from the device. 166130980Sjhb * Returns 0 if the device fails to report 167130980Sjhb */ 168130980Sjhbint 169130980Sjhbget_resource_info(u_char *buffer, int len) 170130980Sjhb{ 171130980Sjhb int i, j; 172130980Sjhb 173130980Sjhb for (i = 0; i < len; i++) { 174130980Sjhb outb(_PNP_ADDRESS, PNP_STATUS); 175130980Sjhb for (j = 0; j < 100; j++) { 176130980Sjhb if ((inb((rd_port << 2) | 0x3)) & 0x1) 177130980Sjhb break; 178130980Sjhb DELAY(1); 179121986Sjhb } 180151979Sjhb if (j == 100) { 181130980Sjhb printf("PnP device failed to report resource data\n"); 182130980Sjhb return 0; 183151979Sjhb } 184151979Sjhb outb(_PNP_ADDRESS, PNP_RESOURCE_DATA); 185130980Sjhb buffer[i] = inb((rd_port << 2) | 0x3); 186130980Sjhb DEB(printf("--- get_resource_info: got 0x%02x\n",(unsigned)buffer[i])); 187151979Sjhb } 188130980Sjhb return 1; 189130980Sjhb} 190151979Sjhb 191130980Sjhbvoid 192130980Sjhbreport_dma_info (x) 193151979Sjhb int x; 194130980Sjhb{ 195130980Sjhb char *s1=NULL, *s2=NULL, *s3=NULL, *s4=NULL, *s5=NULL; 196130980Sjhb 197130980Sjhb switch (x & 0x3) { 198151979Sjhb case 0: 199130980Sjhb s1="8-bit"; 200130980Sjhb break; 201130980Sjhb case 1: 202130980Sjhb s1="8/16-bit"; 203121986Sjhb break; 204121986Sjhb case 2: 205121986Sjhb s1="16-bit"; 206121986Sjhb break; 207121986Sjhb#ifdef DIAGNOSTIC 208121986Sjhb case 3: 209121986Sjhb s1="Reserved"; 210121986Sjhb break; 211157541Sjhb#endif 212121986Sjhb } 213121986Sjhb 214121986Sjhb s2 = (x & 0x4) ? "bus master" : "not a bus master"; 215121986Sjhb 216121986Sjhb s3 = (x & 0x8) ? "count by byte" : ""; 217121986Sjhb 218121986Sjhb s4 = (x & 0x10) ? "count by word" : ""; 219121986Sjhb 220133017Sscottl switch ((x & 0x60) >> 5) { 221121986Sjhb case 0: 222121986Sjhb s5="Compatibility mode"; 223121986Sjhb break; 224121986Sjhb case 1: 225121986Sjhb s5="Type A"; 226121986Sjhb break; 227121986Sjhb case 2: 228157541Sjhb s5="Type B"; 229121986Sjhb break; 230121986Sjhb case 3: 231121986Sjhb s5="Type F"; 232121986Sjhb break; 233133017Sscottl } 234133017Sscottl printf("\t%s, %s, %s, %s, %s\n",s1,s2,s3,s4,s5); 235133017Sscottl} 236133017Sscottl 237121986Sjhb 238121986Sjhbvoid 239121986Sjhbreport_memory_info (int x) 240121986Sjhb{ 241121986Sjhb if (x & 0x1) 242121986Sjhb printf ("Memory Range: Writeable\n"); 243122148Sjhb else 244133017Sscottl printf ("Memory Range: Not writeable (ROM)\n"); 245121986Sjhb 246121986Sjhb if (x & 0x2) 247121986Sjhb printf ("Memory Range: Read-cacheable, write-through\n"); 248129964Sjhb else 249129964Sjhb printf ("Memory Range: Non-cacheable\n"); 250129964Sjhb 251129964Sjhb if (x & 0x4) 252129964Sjhb printf ("Memory Range: Decode supports high address\n"); 253129964Sjhb else 254129964Sjhb printf ("Memory Range: Decode supports range length\n"); 255129964Sjhb 256129964Sjhb switch ((x & 0x18) >> 3) { 257151979Sjhb case 0: 258151979Sjhb printf ("Memory Range: 8-bit memory only\n"); 259151979Sjhb break; 260151979Sjhb case 1: 261208915Sjhb printf ("Memory Range: 16-bit memory only\n"); 262151979Sjhb break; 263151979Sjhb case 2: 264129964Sjhb printf ("Memory Range: 8-bit and 16-bit memory supported\n"); 265129964Sjhb break; 266129964Sjhb#ifdef DIAGNOSTIC 267129964Sjhb case 3: 268129964Sjhb printf ("Memory Range: Reserved\n"); 269129964Sjhb break; 270129964Sjhb#endif 271129964Sjhb } 272129964Sjhb 273129964Sjhb if (x & 0x20) 274156124Sjhb printf ("Memory Range: Memory is shadowable\n"); 275156124Sjhb else 276129964Sjhb printf ("Memory Range: Memory is not shadowable\n"); 277129964Sjhb 278129964Sjhb if (x & 0x40) 279129964Sjhb printf ("Memory Range: Memory is an expansion ROM\n"); 280129964Sjhb else 281129964Sjhb printf ("Memory Range: Memory is not an expansion ROM\n"); 282129964Sjhb 283129964Sjhb#ifdef DIAGNOSTIC 284129964Sjhb if (x & 0x80) 285129964Sjhb printf ("Memory Range: Reserved (Device is brain-damaged)\n"); 286129964Sjhb#endif 287129964Sjhb} 288151979Sjhb 289151979Sjhb 290129964Sjhb/* 291148538Sjhb * Small Resource Tag Handler 292129964Sjhb * 293129964Sjhb * Returns 1 if checksum was valid (and an END_TAG was received). 294151979Sjhb * Returns -1 if checksum was invalid (and an END_TAG was received). 295129964Sjhb * Returns 0 for other tags. 296129964Sjhb */ 297129964Sjhbint 298129964Sjhbhandle_small_res(u_char *resinfo, int item, int len) 299151979Sjhb{ 300129964Sjhb int i; 301129964Sjhb 302129964Sjhb DEB(printf("*** ITEM 0x%04x len %d detected\n", item, len)); 303129964Sjhb 304129964Sjhb switch (item) { 305151979Sjhb default: 306151979Sjhb printf("*** ITEM 0x%02x detected\n", item); 307156124Sjhb break; 308129964Sjhb case PNP_TAG_VERSION: 309129964Sjhb printf("PnP Version %d.%d, Vendor Version %d\n", 310129964Sjhb resinfo[0] >> 4, resinfo[0] & (0xf), resinfo[1]); 311157541Sjhb break; 312129964Sjhb case PNP_TAG_LOGICAL_DEVICE: 313129964Sjhb printf("\nLogical Device ID: %c%c%c%02x%02x 0x%08x #%d\n", 314129964Sjhb ((resinfo[0] & 0x7c) >> 2) + 64, 315129964Sjhb (((resinfo[0] & 0x03) << 3) | 316129964Sjhb ((resinfo[1] & 0xe0) >> 5)) + 64, 317129964Sjhb (resinfo[1] & 0x1f) + 64, 318129964Sjhb resinfo[2], resinfo[3], *(int *)(resinfo), 319195249Sjhb logdevs++); 320156124Sjhb 321121986Sjhb if (resinfo[4] & 0x1) 322156124Sjhb printf ("\tDevice powers up active\n"); /* XXX */ 323156124Sjhb if (resinfo[4] & 0x2) 324195415Sjhb printf ("\tDevice supports I/O Range Check\n"); 325187880Sjeff if (resinfo[4] > 0x3) 326121986Sjhb printf ("\tReserved register funcs %02x\n", 327187880Sjeff resinfo[4]); 328187880Sjeff 329187880Sjeff if (len == 6) 330187880Sjeff printf("\tVendor register funcs %02x\n", resinfo[5]); 331187880Sjeff break; 332187880Sjeff case PNP_TAG_COMPAT_DEVICE: 333187880Sjeff printf("Compatible Device ID: %c%c%c%02x%02x (%08x)\n", 334187880Sjeff ((resinfo[0] & 0x7c) >> 2) + 64, 335187880Sjeff (((resinfo[0] & 0x03) << 3) | 336187880Sjeff ((resinfo[1] & 0xe0) >> 5)) + 64, 337187880Sjeff (resinfo[1] & 0x1f) + 64, 338187880Sjeff resinfo[2], resinfo[3], *(int *)resinfo); 339195249Sjhb break; 340187880Sjeff case PNP_TAG_IRQ_FORMAT: 341187880Sjeff printf(" IRQ: "); 342187880Sjeff 343187880Sjeff for (i = 0; i < 8; i++) 344187880Sjeff if (resinfo[0] & (1<<i)) 345195415Sjhb printf("%d ", i); 346195415Sjhb for (i = 0; i < 8; i++) 347195249Sjhb if (resinfo[1] & (1<<i)) 348195249Sjhb printf("%d ", i + 8); 349208915Sjhb if (len == 3) { 350208915Sjhb if (resinfo[2] & 0x1) 351208915Sjhb printf("IRQ: High true edge sensitive\n"); 352208915Sjhb if (resinfo[2] & 0x2) 353208915Sjhb printf("IRQ: Low true edge sensitive\n"); 354208915Sjhb if (resinfo[2] & 0x4) 355208915Sjhb printf("IRQ: High true level sensitive\n"); 356208991Smav if (resinfo[2] & 0x8) 357208915Sjhb printf("IRQ: Low true level sensitive\n"); 358208915Sjhb } else { 359216679Sjhb printf(" - only one type (true/edge)\n"); 360208915Sjhb } 361216679Sjhb break; 362208915Sjhb case PNP_TAG_DMA_FORMAT: 363208915Sjhb printf(" DMA: channel(s) "); 364195415Sjhb for (i = 0; i < 8; i++) 365195415Sjhb if (resinfo[0] & (1<<i)) 366195415Sjhb printf("%d ", i); 367195415Sjhb printf ("\n"); 368121986Sjhb report_dma_info (resinfo[1]); 369187880Sjeff break; 370187880Sjeff case PNP_TAG_START_DEPENDANT: 371151979Sjhb printf("TAG Start DF\n"); 372187880Sjeff if (len == 1) { 373187880Sjeff switch (resinfo[0]) { 374121986Sjhb case 0: 375129964Sjhb printf("Good Configuration\n"); 376208915Sjhb break; 377208915Sjhb case 1: 378187880Sjeff printf("Acceptable Configuration\n"); 379187880Sjeff break; 380187880Sjeff case 2: 381187880Sjeff printf("Sub-optimal Configuration\n"); 382195415Sjhb break; 383195415Sjhb } 384195415Sjhb } 385187880Sjeff break; 386195415Sjhb case PNP_TAG_END_DEPENDANT: 387195249Sjhb printf("TAG End DF\n"); 388121986Sjhb break; 389121986Sjhb case PNP_TAG_IO_RANGE: 390121986Sjhb printf(" I/O Range 0x%x .. 0x%x, alignment 0x%x, len 0x%x\n", 391121986Sjhb resinfo[1] + (resinfo[2] << 8), 392121986Sjhb resinfo[3] + (resinfo[4] << 8), 393121986Sjhb resinfo[5], resinfo[6] ); 394121986Sjhb if (resinfo[0]) 395187880Sjeff printf("\t[16-bit addr]\n"); 396195249Sjhb else 397195249Sjhb printf("\t[not 16-bit addr]\n"); 398195249Sjhb break; 399187880Sjeff case PNP_TAG_IO_FIXED: 400121986Sjhb printf (" FIXED I/O base address 0x%x length 0x%x\n", 401121986Sjhb resinfo[0] + ( (resinfo[1] & 3 ) << 8), /* XXX */ 402187880Sjeff resinfo[2]); 403169391Sjhb break; 404169391Sjhb#ifdef DIAGNOSTIC 405169391Sjhb case PNP_TAG_RESERVED: 406169391Sjhb printf("Reserved Tag Detected\n"); 407169391Sjhb break; 408169391Sjhb#endif 409169391Sjhb case PNP_TAG_VENDOR: 410169391Sjhb printf("*** Small Vendor Tag Detected\n"); 411169391Sjhb break; 412187880Sjeff case PNP_TAG_END: 413208915Sjhb printf("End Tag\n\n"); 414169391Sjhb /* XXX Record and Verify Checksum */ 415169391Sjhb return 1; 416169391Sjhb break; 417208915Sjhb } 418187880Sjeff return 0; 419169391Sjhb} 420169391Sjhb 421169391Sjhb 422121986Sjhbvoid 423121986Sjhbhandle_large_res(u_char *resinfo, int item, int len) 424121986Sjhb{ 425121986Sjhb int i; 426121986Sjhb 427121986Sjhb DEB(printf("*** Large ITEM %d len %d found\n", item, len)); 428151979Sjhb switch (item) { 429121986Sjhb case PNP_TAG_MEMORY_RANGE: 430121986Sjhb report_memory_info(resinfo[0]); 431121986Sjhb printf("Memory range minimum address: 0x%x\n", 432121986Sjhb (resinfo[1] << 8) + (resinfo[2] << 16)); 433121986Sjhb printf("Memory range maximum address: 0x%x\n", 434121986Sjhb (resinfo[3] << 8) + (resinfo[4] << 16)); 435121986Sjhb printf("Memory range base alignment: 0x%x\n", 436151979Sjhb (i = (resinfo[5] + (resinfo[6] << 8))) ? i : (1 << 16)); 437151979Sjhb printf("Memory range length: 0x%x\n", 438121986Sjhb (resinfo[7] + (resinfo[8] << 8)) * 256); 439121986Sjhb break; 440121986Sjhb case PNP_TAG_ID_ANSI: 441128931Sjhb printf("Device Description: "); 442128931Sjhb 443128931Sjhb for (i = 0; i < len; i++) { 444128931Sjhb if (resinfo[i]) /* XXX */ 445128931Sjhb printf("%c", resinfo[i]); 446128931Sjhb } 447130984Sjhb printf("\n"); 448128931Sjhb break; 449128931Sjhb case PNP_TAG_ID_UNICODE: 450128931Sjhb printf("ID String Unicode Detected (Undefined)\n"); 451128931Sjhb break; 452128931Sjhb case PNP_TAG_LARGE_VENDOR: 453130984Sjhb printf("Large Vendor Defined Detected\n"); 454130984Sjhb break; 455130984Sjhb case PNP_TAG_MEMORY32_RANGE: 456130984Sjhb printf("32bit Memory Range Desc Unimplemented\n"); 457140452Sjhb break; 458128931Sjhb case PNP_TAG_MEMORY32_FIXED: 459208915Sjhb printf("32bit Fixed Location Desc Unimplemented\n"); 460130984Sjhb break; 461130984Sjhb#ifdef DIAGNOSTIC 462130984Sjhb case PNP_TAG_LARGE_RESERVED: 463130984Sjhb printf("Large Reserved Tag Detected\n"); 464130984Sjhb break; 465130984Sjhb#endif 466130984Sjhb } 467130984Sjhb} 468130984Sjhb 469130984Sjhb 470130984Sjhb/* 471130984Sjhb * Dump all the information about configurations. 472130984Sjhb */ 473130984Sjhbvoid 474130984Sjhbdump_resdata(u_char *data, int csn) 475130984Sjhb{ 476130984Sjhb int i, large_len; 477130984Sjhb 478130984Sjhb u_char tag, *resinfo; 479130984Sjhb 480130984Sjhb DDB(printf("\nCard assigned CSN #%d\n", csn)); 481208915Sjhb printf("Vendor ID %c%c%c%02x%02x (0x%08x), Serial Number 0x%08x\n", 482128931Sjhb ((data[0] & 0x7c) >> 2) + 64, 483128931Sjhb (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64, 484128931Sjhb (data[1] & 0x1f) + 64, data[2], data[3], 485121986Sjhb *(int *)&(data[0]), 486163219Sjhb *(int *)&(data[4])); 487121986Sjhb 488163219Sjhb pnp_write(PNP_SET_CSN, csn); /* Move this out of this function XXX */ 489163219Sjhb outb(_PNP_ADDRESS, PNP_STATUS); 490121986Sjhb 491208915Sjhb /* Allows up to 1kb of Resource Info, Should be plenty */ 492163219Sjhb for (i = 0; i < 1024; i++) { 493163219Sjhb if (!get_resource_info(&tag, 1)) 494208915Sjhb break; 495121986Sjhb 496121986Sjhb if (PNP_RES_TYPE(tag) == 0) { 497121986Sjhb /* Handle small resouce data types */ 498121986Sjhb 499121986Sjhb resinfo = malloc(PNP_SRES_LEN(tag)); 500121986Sjhb if (!get_resource_info(resinfo, PNP_SRES_LEN(tag))) 501167247Sjhb break; 502121986Sjhb 503121986Sjhb if (handle_small_res(resinfo, PNP_SRES_NUM(tag), PNP_SRES_LEN(tag)) == 1) 504121986Sjhb break; 505121986Sjhb free(resinfo); 506121986Sjhb } else { 507121986Sjhb /* Handle large resouce data types */ 508121986Sjhb u_char buf[2]; 509145054Sjhb if (!get_resource_info((char *)buf, 2)) 510156920Sjhb break; 511121986Sjhb large_len = (buf[1] << 8) + buf[0]; 512145054Sjhb 513121986Sjhb resinfo = malloc(large_len); 514145054Sjhb if (!get_resource_info(resinfo, large_len)) 515145054Sjhb break; 516152528Sjhb 517145057Sjhb handle_large_res(resinfo, PNP_LRES_NUM(tag), large_len); 518145054Sjhb free(resinfo); 519145054Sjhb } 520145054Sjhb } 521145054Sjhb printf("Successfully got %d resources, %d logical fdevs\n", i, 522145054Sjhb logdevs); 523121986Sjhb printf("-- card select # 0x%04x\n", pnp_read(PNP_SET_CSN)); 524121986Sjhb printf("\nCSN %c%c%c%02x%02x (0x%08x), Serial Number 0x%08x\n", 525121986Sjhb ((data[0] & 0x7c) >> 2) + 64, 526121986Sjhb (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64, 527121986Sjhb (data[1] & 0x1f) + 64, data[2], data[3], 528195249Sjhb *(int *)&(data[0]), 529121986Sjhb *(int *)&(data[4])); 530121986Sjhb 531121986Sjhb for (i=0; i<logdevs; i++) { 532121986Sjhb int j; 533121986Sjhb 534121986Sjhb pnp_write(PNP_SET_LDN, i); 535121986Sjhb 536121986Sjhb printf("\nLogical device #%d\n", pnp_read(PNP_SET_LDN) ); 537121986Sjhb printf("IO: "); 538121986Sjhb for (j=0; j<8; j++) 539121986Sjhb printf(" 0x%02x%02x", pnp_read(PNP_IO_BASE_HIGH(j)), 540121986Sjhb pnp_read(PNP_IO_BASE_LOW(j))); 541170340Sjhb printf("\nIRQ %d %d\n", 542121986Sjhb pnp_read(PNP_IRQ_LEVEL(0)), pnp_read(PNP_IRQ_LEVEL(1)) ); 543121986Sjhb printf("DMA %d %d\n", 544121986Sjhb pnp_read(PNP_DMA_CHANNEL(0)), pnp_read(PNP_DMA_CHANNEL(1)) ); 545122124Sjhb printf("IO range check 0x%02x activate 0x%02x\n", 546121986Sjhb pnp_read(PNP_IO_RANGE_CHECK), pnp_read(PNP_ACTIVATE) ); 547121986Sjhb } 548167747Sjhb} 549121986Sjhb 550121986Sjhb 551121986Sjhb/* 552121986Sjhb * Run the isolation protocol. Use rd_port as the READ_DATA port 553121986Sjhb * value (caller should try multiple READ_DATA locations before giving 554121986Sjhb * up). Upon exiting, all cards are aware that they should use rd_port 555121986Sjhb * as the READ_DATA port; 556121986Sjhb * 557121986Sjhb */ 558121986Sjhbint 559121986Sjhbisolation_protocol() 560151979Sjhb{ 561121986Sjhb int csn; 562121986Sjhb u_char data[9]; 563145080Sjhb 564142256Sjhb send_Initiation_LFSR(); 565130980Sjhb 566121986Sjhb /* Reset CSN for All Cards */ 567151979Sjhb pnp_write(PNP_CONFIG_CONTROL, 0x04); 568130980Sjhb 569151979Sjhb for (csn = 1; (csn < PNP_MAX_CARDS); csn++) { 570130980Sjhb /* Wake up cards without a CSN */ 571121986Sjhb logdevs = 0 ; 572121986Sjhb pnp_write(PNP_WAKE, 0); 573121986Sjhb pnp_write(PNP_SET_RD_DATA, rd_port); 574121986Sjhb outb(_PNP_ADDRESS, PNP_SERIAL_ISOLATION); 575130980Sjhb DELAY(1000); /* Delay 1 msec */ 576121986Sjhb 577121986Sjhb if (get_serial(data)) 578121986Sjhb dump_resdata(data, csn); 579121986Sjhb else 580121986Sjhb break; 581121986Sjhb } 582156124Sjhb return csn - 1; 583156124Sjhb} 584121986Sjhb 585156124Sjhb 586121986Sjhbint 587121986Sjhbmain(int argc, char **argv) 588121986Sjhb{ 589121986Sjhb int num_pnp_devs; 590121986Sjhb 591121986Sjhb#ifdef __i386__ 592121986Sjhb /* Hey what about a i386_iopl() call :) */ 593121986Sjhb if (open("/dev/io", O_RDONLY) < 0) 594121986Sjhb errx(1, "can't get I/O privilege"); 595121986Sjhb#endif 596121986Sjhb#ifdef __alpha__ 597121986Sjhb ioperm(0x203, 0x400 - 0x203, 1); 598121986Sjhb#endif 599121986Sjhb 600121986Sjhb printf("Checking for Plug-n-Play devices...\n"); 601121986Sjhb 602151979Sjhb /* Try various READ_DATA ports from 0x203-0x3ff */ 603121986Sjhb for (rd_port = 0x80; (rd_port < 0xff); rd_port += 0x10) { 604121986Sjhb DEB(printf("Trying Read_Port at %x...\n", (rd_port << 2) | 0x3) ); 605121986Sjhb num_pnp_devs = isolation_protocol(rd_port); 606121986Sjhb if (num_pnp_devs) 607121986Sjhb break; 608121986Sjhb } 609121986Sjhb if (!num_pnp_devs) { 610121986Sjhb printf("No Plug-n-Play devices were found\n"); 611121986Sjhb return (0); 612121986Sjhb } 613151979Sjhb return (0); 614121986Sjhb} 615151979Sjhb