pnpinfo.c revision 31135
1176434Skaiw/* 2176434Skaiw * Copyright (c) 1996, Sujal M. Patel 3176434Skaiw * All rights reserved. 4176434Skaiw * 5176434Skaiw * Redistribution and use in source and binary forms, with or without 6176434Skaiw * modification, are permitted provided that the following conditions 7176434Skaiw * are met: 8176434Skaiw * 1. Redistributions of source code must retain the above copyright 9176434Skaiw * notice, this list of conditions and the following disclaimer. 10176434Skaiw * 2. Redistributions in binary form must reproduce the above copyright 11176434Skaiw * notice, this list of conditions and the following disclaimer in the 12176434Skaiw * documentation and/or other materials provided with the distribution. 13176434Skaiw * 14176434Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15176434Skaiw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16176434Skaiw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17176434Skaiw * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18176434Skaiw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19176434Skaiw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20176434Skaiw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21176434Skaiw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22176434Skaiw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23176434Skaiw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24176434Skaiw * SUCH DAMAGE. 25176434Skaiw * 26176434Skaiw * $Id: pnpinfo.c,v 1.1.1.1 1997/09/19 15:36:00 jmg Exp $ 27176434Skaiw */ 28176434Skaiw 29176434Skaiw#include <sys/time.h> 30176434Skaiw 31176434Skaiw#include <stdio.h> 32176434Skaiw#include <stdlib.h> 33176434Skaiw#include <unistd.h> 34176434Skaiw#include <fcntl.h> 35176434Skaiw#include <string.h> 36176434Skaiw 37176434Skaiw#include <machine/cpufunc.h> 38176434Skaiw 39176434Skaiw#include <i386/isa/pnp.h> 40176434Skaiw 41176434Skaiw#ifdef DEBUG 42176434Skaiw#define DEB(x) x 43176434Skaiw#else 44285224Semaste#define DEB(x) 45176434Skaiw#endif 46176434Skaiw#define DDB(x) x 47176434Skaiw 48176434Skaiwvoid 49176434Skaiwpnp_write(int d, u_char r) 50176434Skaiw{ 51176434Skaiw outb (_PNP_ADDRESS, d); 52176434Skaiw outb (_PNP_WRITE_DATA, r); 53176434Skaiw} 54176434Skaiw/* The READ_DATA port that we are using currently */ 55176434Skaiwstatic int rd_port; 56176434Skaiw 57176434Skaiwu_char 58176434Skaiwpnp_read(int d) 59176434Skaiw{ 60176434Skaiw outb(_PNP_ADDRESS, d); 61176434Skaiw return inb( (rd_port << 2) + 3) & 0xff; 62224650Semaste} 63176434Skaiw 64176434Skaiwu_short 65285224Semastepnp_readw(int d) 66183218Skaiw{ 67183218Skaiw int c = pnp_read(d) << 8 ; 68176434Skaiw c |= pnp_read(d+1); 69176434Skaiw return c; 70176434Skaiw} 71176434Skaiw 72176434Skaiwint logdevs=0; 73176434Skaiw 74176434Skaiwvoid DELAY __P((int i)); 75176434Skaiwvoid send_Initiation_LFSR(); 76176434Skaiwint get_serial __P((u_char *data)); 77176434Skaiwint get_resource_info __P((u_char *buffer, int len)); 78176434Skaiwint handle_small_res __P((u_char *resinfo, int item, int len)); 79176434Skaiwvoid handle_large_res __P((u_char *resinfo, int item, int len)); 80176434Skaiwvoid dump_resdata __P((u_char *data, int csn)); 81176434Skaiwint isolation_protocol(); 82176434Skaiw 83176434Skaiw 84176434Skaiw/* 85176434Skaiw * DELAY does accurate delaying in user-space. 86176434Skaiw * This function busy-waits. 87176434Skaiw */ 88176434Skaiwvoid 89177064SkaiwDELAY (int i) 90177064Skaiw{ 91177064Skaiw struct timeval t; 92177064Skaiw long start, stop; 93177064Skaiw 94177064Skaiw i *= 4; 95177064Skaiw 96176434Skaiw gettimeofday (&t, NULL); 97176434Skaiw start = t.tv_sec * 1000000 + t.tv_usec; 98176434Skaiw do { 99176434Skaiw gettimeofday (&t, NULL); 100176434Skaiw stop = t.tv_sec * 1000000 + t.tv_usec; 101176434Skaiw } while (start + i > stop); 102176434Skaiw} 103176434Skaiw 104176434Skaiw 105176434Skaiw/* 106176434Skaiw * Send Initiation LFSR as described in "Plug and Play ISA Specification, 107176434Skaiw * Intel May 94." 108176434Skaiw */ 109183218Skaiwvoid 110183218Skaiwsend_Initiation_LFSR() 111183218Skaiw{ 112183218Skaiw int cur, i; 113183218Skaiw 114183218Skaiw pnp_write(CONFIG_CONTROL, 0x2); 115183218Skaiw 116176434Skaiw /* Reset the LSFR */ 117176434Skaiw outb(_PNP_ADDRESS, 0); 118176434Skaiw outb(_PNP_ADDRESS, 0); /* yes, we do need it twice! */ 119222122Sbcr 120176434Skaiw cur = 0x6a; 121176434Skaiw 122176434Skaiw for (i = 0; i < 32; i++) { 123176434Skaiw outb(_PNP_ADDRESS, cur); 124176434Skaiw cur = (cur >> 1) | (((cur ^ (cur >> 1)) << 7) & 0xff); 125176434Skaiw } 126176434Skaiw} 127176434Skaiw 128176434Skaiw/* 129176528Skaiw * Get the device's serial number. Returns 1 if the serial is valid. 130176434Skaiw */ 131176434Skaiwint 132176434Skaiwget_serial(u_char *data) 133176434Skaiw{ 134176434Skaiw int i, bit, valid = 0, sum = 0x6a; 135176434Skaiw 136176434Skaiw bzero(data, sizeof(char) * 9); 137176528Skaiw 138176434Skaiw for (i = 0; i < 72; i++) { 139176434Skaiw bit = inb((rd_port << 2) | 0x3) == 0x55; 140176434Skaiw DELAY(250); /* Delay 250 usec */ 141176434Skaiw 142176434Skaiw /* Can't Short Circuit the next evaluation, so 'and' is last */ 143176434Skaiw bit = (inb((rd_port << 2) | 0x3) == 0xaa) && bit; 144176434Skaiw DELAY(250); /* Delay 250 usec */ 145176434Skaiw 146176434Skaiw valid = valid || bit; 147176434Skaiw 148176434Skaiw if (i < 64) 149176434Skaiw sum = (sum >> 1) | 150176434Skaiw (((sum ^ (sum >> 1) ^ bit) << 7) & 0xff); 151176434Skaiw 152176434Skaiw data[i / 8] = (data[i / 8] >> 1) | (bit ? 0x80 : 0); 153176434Skaiw } 154176434Skaiw 155176434Skaiw valid = valid && (data[8] == sum); 156176434Skaiw 157176434Skaiw return valid; 158176434Skaiw} 159176434Skaiw 160176434Skaiw 161176434Skaiw/* 162176434Skaiw * Fill's the buffer with resource info from the device. 163176434Skaiw * Returns 0 if the device fails to report 164176434Skaiw */ 165176434Skaiwint 166176434Skaiwget_resource_info(u_char *buffer, int len) 167176434Skaiw{ 168176434Skaiw int i, j; 169213643Skientzle 170213643Skientzle for (i = 0; i < len; i++) { 171213643Skientzle outb(_PNP_ADDRESS, STATUS); 172213643Skientzle for (j = 0; j < 100; j++) { 173213643Skientzle if ((inb((rd_port << 2) | 0x3)) & 0x1) 174213643Skientzle break; 175213643Skientzle DELAY(1); 176213643Skientzle } 177213643Skientzle if (j == 100) { 178213643Skientzle printf("PnP device failed to report resource data\n"); 179213643Skientzle return 0; 180213643Skientzle } 181213643Skientzle outb(_PNP_ADDRESS, RESOURCE_DATA); 182213643Skientzle buffer[i] = inb((rd_port << 2) | 0x3); 183213643Skientzle DEB(printf("--- get_resource_info: got 0x%02x\n",(unsigned)buffer[i])); 184213643Skientzle } 185213643Skientzle return 1; 186176434Skaiw} 187176434Skaiw 188176434Skaiwvoid 189176525Skaiwreport_dma_info (x) 190176525Skaiw int x; 191176525Skaiw{ 192176528Skaiw char *s1=NULL, *s2=NULL, *s3=NULL, *s4=NULL, *s5=NULL; 193176525Skaiw 194176525Skaiw switch (x & 0x3) { 195176434Skaiw case 0: 196176434Skaiw s1="8-bit"; 197176434Skaiw break; 198176434Skaiw case 1: 199176434Skaiw s1="8/16-bit"; 200176434Skaiw break; 201176434Skaiw case 2: 202176434Skaiw s1="16-bit"; 203176434Skaiw break; 204176528Skaiw#ifdef DIAGNOSTIC 205176434Skaiw case 3: 206176434Skaiw s1="Reserved"; 207176434Skaiw break; 208176434Skaiw#endif 209176434Skaiw } 210176434Skaiw 211176434Skaiw s2 = (x & 0x4) ? "bus master" : "not a bus master"; 212176528Skaiw 213176434Skaiw s3 = (x & 0x8) ? "count by byte" : ""; 214176434Skaiw 215176434Skaiw s4 = (x & 0x10) ? "count by word" : ""; 216224650Semaste 217224650Semaste switch ((x & 0x60) >> 5) { 218224650Semaste case 0: 219224650Semaste s5="Compatibility mode"; 220224650Semaste break; 221224650Semaste case 1: 222224650Semaste s5="Type A"; 223224650Semaste break; 224224650Semaste case 2: 225224650Semaste s5="Type B"; 226224650Semaste break; 227224650Semaste case 3: 228224650Semaste s5="Type F"; 229224650Semaste break; 230224650Semaste } 231224650Semaste printf("\t%s, %s, %s, %s, %s\n",s1,s2,s3,s4,s5); 232176434Skaiw} 233176434Skaiw 234176434Skaiw 235176434Skaiwvoid 236176434Skaiwreport_memory_info (int x) 237176434Skaiw{ 238176434Skaiw if (x & 0x1) 239176434Skaiw printf ("Memory Range: Writeable\n"); 240176434Skaiw else 241176434Skaiw printf ("Memory Range: Not writeable (ROM)\n"); 242222122Sbcr 243176434Skaiw if (x & 0x2) 244176434Skaiw printf ("Memory Range: Read-cacheable, write-through\n"); 245176434Skaiw else 246176434Skaiw printf ("Memory Range: Non-cacheable\n"); 247176434Skaiw 248176434Skaiw if (x & 0x4) 249176434Skaiw printf ("Memory Range: Decode supports high address\n"); 250176434Skaiw else 251176434Skaiw printf ("Memory Range: Decode supports range length\n"); 252176434Skaiw 253176434Skaiw switch ((x & 0x18) >> 3) { 254176434Skaiw case 0: 255176434Skaiw printf ("Memory Range: 8-bit memory only\n"); 256176434Skaiw break; 257176434Skaiw case 1: 258176434Skaiw printf ("Memory Range: 16-bit memory only\n"); 259176434Skaiw break; 260176434Skaiw case 2: 261176434Skaiw printf ("Memory Range: 8-bit and 16-bit memory supported\n"); 262183218Skaiw break; 263183218Skaiw#ifdef DIAGNOSTIC 264183218Skaiw case 3: 265183218Skaiw printf ("Memory Range: Reserved\n"); 266176434Skaiw break; 267176434Skaiw#endif 268183218Skaiw } 269176434Skaiw 270176434Skaiw if (x & 0x20) 271176434Skaiw printf ("Memory Range: Memory is shadowable\n"); 272183218Skaiw else 273176434Skaiw printf ("Memory Range: Memory is not shadowable\n"); 274176434Skaiw 275176434Skaiw if (x & 0x40) 276176434Skaiw printf ("Memory Range: Memory is an expansion ROM\n"); 277176434Skaiw else 278183218Skaiw printf ("Memory Range: Memory is not an expansion ROM\n"); 279176434Skaiw 280176434Skaiw#ifdef DIAGNOSTIC 281176434Skaiw if (x & 0x80) 282176434Skaiw printf ("Memory Range: Reserved (Device is brain-damaged)\n"); 283183218Skaiw#endif 284176434Skaiw} 285176434Skaiw 286176434Skaiw 287176434Skaiw/* 288176434Skaiw * Small Resource Tag Handler 289176434Skaiw * 290176434Skaiw * Returns 1 if checksum was valid (and an END_TAG was received). 291176434Skaiw * Returns -1 if checksum was invalid (and an END_TAG was received). 292176434Skaiw * Returns 0 for other tags. 293176434Skaiw */ 294176434Skaiwint 295176434Skaiwhandle_small_res(u_char *resinfo, int item, int len) 296176434Skaiw{ 297176434Skaiw int i; 298176434Skaiw 299176434Skaiw DEB(printf("*** ITEM 0x%04x len %d detected\n", item, len)); 300176434Skaiw 301176434Skaiw switch (item) { 302176434Skaiw default: 303176434Skaiw printf("*** ITEM 0x%02x detected\n", item); 304176434Skaiw break; 305176434Skaiw case PNP_VERSION: 306183218Skaiw printf("PnP Version %d.%d, Vendor Version %d\n", 307183218Skaiw resinfo[0] >> 4, resinfo[0] & (0xf), resinfo[1]); 308183218Skaiw break; 309183218Skaiw case LOG_DEVICE_ID: 310183218Skaiw printf("\nLogical Device ID: %c%c%c%02x%02x 0x%08x #%d\n", 311183218Skaiw ((resinfo[0] & 0x7c) >> 2) + 64, 312183218Skaiw (((resinfo[0] & 0x03) << 3) | 313183218Skaiw ((resinfo[1] & 0xe0) >> 5)) + 64, 314183218Skaiw (resinfo[1] & 0x1f) + 64, 315183218Skaiw resinfo[2], resinfo[3], *(int *)(resinfo), 316183218Skaiw logdevs++); 317183218Skaiw 318183218Skaiw if (resinfo[4] & 0x1) 319183218Skaiw printf ("\tDevice powers up active\n"); /* XXX */ 320183218Skaiw if (resinfo[4] & 0x2) 321183218Skaiw printf ("\tDevice supports I/O Range Check\n"); 322183218Skaiw if (resinfo[4] > 0x3) 323183218Skaiw printf ("\tReserved register funcs %02x\n", 324183218Skaiw resinfo[4]); 325183218Skaiw 326183218Skaiw if (len == 6) 327183218Skaiw printf("\tVendor register funcs %02x\n", resinfo[5]); 328183218Skaiw break; 329183218Skaiw case COMP_DEVICE_ID: 330176434Skaiw printf("Compatible Device ID: %c%c%c%02x%02x (%08x)\n", 331176434Skaiw ((resinfo[0] & 0x7c) >> 2) + 64, 332176728Skaiw (((resinfo[0] & 0x03) << 3) | 333176728Skaiw ((resinfo[1] & 0xe0) >> 5)) + 64, 334176728Skaiw (resinfo[1] & 0x1f) + 64, 335176728Skaiw resinfo[2], resinfo[3], *(int *)resinfo); 336176728Skaiw break; 337176728Skaiw case IRQ_FORMAT: 338176728Skaiw printf(" IRQ: "); 339176728Skaiw 340176728Skaiw for (i = 0; i < 8; i++) 341176728Skaiw if (resinfo[0] & (1<<i)) 342176728Skaiw printf("%d ", i); 343176728Skaiw for (i = 0; i < 8; i++) 344176728Skaiw if (resinfo[1] & (1<<i)) 345176434Skaiw printf("%d ", i + 8); 346176434Skaiw if (len == 3) { 347176434Skaiw if (resinfo[2] & 0x1) 348176434Skaiw printf("IRQ: High true edge sensitive\n"); 349176434Skaiw if (resinfo[2] & 0x2) 350176434Skaiw printf("IRQ: Low true edge sensitive\n"); 351176434Skaiw if (resinfo[2] & 0x4) 352176434Skaiw printf("IRQ: High true level sensitive\n"); 353176434Skaiw if (resinfo[2] & 0x8) 354176434Skaiw printf("IRQ: Low true level sensitive\n"); 355176434Skaiw } else { 356176434Skaiw printf(" - only one type (true/edge)\n"); 357176434Skaiw } 358176434Skaiw break; 359176434Skaiw case DMA_FORMAT: 360176434Skaiw printf(" DMA: channel(s) "); 361176434Skaiw for (i = 0; i < 8; i++) 362176434Skaiw if (resinfo[0] & (1<<i)) 363176434Skaiw printf("%d ", i); 364176434Skaiw printf ("\n"); 365176434Skaiw report_dma_info (resinfo[1]); 366176434Skaiw break; 367248612Smm case START_DEPEND_FUNC: 368183218Skaiw printf("TAG Start DF\n"); 369176434Skaiw if (len == 1) { 370183218Skaiw switch (resinfo[0]) { 371183218Skaiw case 0: 372183218Skaiw printf("Good Configuration\n"); 373183218Skaiw break; 374183218Skaiw case 1: 375183218Skaiw printf("Acceptable Configuration\n"); 376183218Skaiw break; 377183218Skaiw case 2: 378183218Skaiw printf("Sub-optimal Configuration\n"); 379183218Skaiw break; 380183218Skaiw } 381183218Skaiw } 382183218Skaiw break; 383183218Skaiw case END_DEPEND_FUNC: 384183218Skaiw printf("TAG End DF\n"); 385183218Skaiw break; 386183218Skaiw case IO_PORT_DESC: 387176434Skaiw printf(" I/O Range 0x%x .. 0x%x, alignment 0x%x, len 0x%x\n", 388183218Skaiw resinfo[1] + (resinfo[2] << 8), 389183218Skaiw resinfo[3] + (resinfo[4] << 8), 390183218Skaiw resinfo[5], resinfo[6] ); 391183218Skaiw if (resinfo[0]) 392183218Skaiw printf("\t[16-bit addr]\n"); 393183218Skaiw else 394183218Skaiw printf("\t[not 16-bit addr]\n"); 395183218Skaiw break; 396183218Skaiw case FIXED_IO_PORT_DESC: 397183218Skaiw printf (" FIXED I/O base address 0x%x length 0x%x\n", 398183218Skaiw resinfo[0] + ( (resinfo[1] & 3 ) << 8), /* XXX */ 399183218Skaiw resinfo[2]); 400183218Skaiw break; 401183218Skaiw#ifdef DIAGNOSTIC 402183218Skaiw case SM_RES_RESERVED: 403183218Skaiw printf("Reserved Tag Detected\n"); 404183218Skaiw break; 405183218Skaiw#endif 406183218Skaiw case SM_VENDOR_DEFINED: 407183218Skaiw printf("*** Small Vendor Tag Detected\n"); 408183218Skaiw break; 409183218Skaiw case END_TAG: 410183218Skaiw printf("End Tag\n\n"); 411183218Skaiw /* XXX Record and Verify Checksum */ 412183218Skaiw return 1; 413183218Skaiw break; 414183218Skaiw } 415183218Skaiw return 0; 416183218Skaiw} 417176434Skaiw 418176434Skaiw 419176434Skaiwvoid 420176434Skaiwhandle_large_res(u_char *resinfo, int item, int len) 421176434Skaiw{ 422176434Skaiw int i; 423177064Skaiw 424177064Skaiw DEB(printf("*** Large ITEM %d len %d found\n", item, len)); 425177064Skaiw switch (item) { 426177064Skaiw case MEMORY_RANGE_DESC: 427177064Skaiw report_memory_info(resinfo[0]); 428177064Skaiw printf("Memory range minimum address: 0x%x\n", 429177064Skaiw (resinfo[1] << 8) + (resinfo[2] << 16)); 430177064Skaiw printf("Memory range maximum address: 0x%x\n", 431183218Skaiw (resinfo[3] << 8) + (resinfo[4] << 16)); 432183218Skaiw printf("Memory range base alignment: 0x%x\n", 433183218Skaiw (i = (resinfo[5] + (resinfo[6] << 8))) ? i : (1 << 16)); 434183218Skaiw printf("Memory range length: 0x%x\n", 435183218Skaiw (resinfo[7] + (resinfo[8] << 8)) * 256); 436183218Skaiw break; 437183218Skaiw case ID_STRING_ANSI: 438183218Skaiw printf("Device Description: "); 439222122Sbcr 440183218Skaiw for (i = 0; i < len; i++) { 441183218Skaiw if (resinfo[i]) /* XXX */ 442183218Skaiw printf("%c", resinfo[i]); 443183218Skaiw } 444183218Skaiw printf("\n"); 445183218Skaiw break; 446183218Skaiw case ID_STRING_UNICODE: 447176434Skaiw printf("ID String Unicode Detected (Undefined)\n"); 448176434Skaiw break; 449176434Skaiw case LG_VENDOR_DEFINED: 450176434Skaiw printf("Large Vendor Defined Detected\n"); 451176434Skaiw break; 452176434Skaiw case _32BIT_MEM_RANGE_DESC: 453176434Skaiw printf("32bit Memory Range Desc Unimplemented\n"); 454176434Skaiw break; 455176434Skaiw case _32BIT_FIXED_LOC_DESC: 456176434Skaiw printf("32bit Fixed Location Desc Unimplemented\n"); 457176434Skaiw break; 458176434Skaiw case LG_RES_RESERVED: 459222122Sbcr printf("Large Reserved Tag Detected\n"); 460176434Skaiw break; 461176434Skaiw } 462176434Skaiw} 463176434Skaiw 464176434Skaiw 465176434Skaiw/* 466176434Skaiw * Dump all the information about configurations. 467176434Skaiw */ 468176434Skaiwvoid 469176434Skaiwdump_resdata(u_char *data, int csn) 470176434Skaiw{ 471176434Skaiw int i, large_len; 472176434Skaiw 473176434Skaiw u_char tag, *resinfo; 474176434Skaiw 475176434Skaiw DDB(printf("\nCard assigned CSN #%d\n", csn)); 476176434Skaiw printf("Vendor ID %c%c%c%02x%02x (0x%08x), Serial Number 0x%08x\n", 477176434Skaiw ((data[0] & 0x7c) >> 2) + 64, 478176434Skaiw (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64, 479176434Skaiw (data[1] & 0x1f) + 64, data[2], data[3], 480176434Skaiw *(int *)&(data[0]), 481176434Skaiw *(int *)&(data[4])); 482176434Skaiw 483176434Skaiw pnp_write(SET_CSN, csn); /* Move this out of this function XXX */ 484176434Skaiw outb(_PNP_ADDRESS, STATUS); 485176434Skaiw 486176434Skaiw /* Allows up to 1kb of Resource Info, Should be plenty */ 487176434Skaiw for (i = 0; i < 1024; i++) { 488176434Skaiw if (!get_resource_info(&tag, 1)) 489176434Skaiw break; 490176434Skaiw 491176434Skaiw#define TYPE (tag >> 7) 492176434Skaiw#define S_ITEM (tag >> 3) 493176434Skaiw#define S_LEN (tag & 0x7) 494176434Skaiw#define L_ITEM (tag & 0x7f) 495224650Semaste 496224650Semaste if (TYPE == 0) { 497176434Skaiw /* Handle small resouce data types */ 498176434Skaiw 499176434Skaiw resinfo = malloc(S_LEN); 500176434Skaiw if (!get_resource_info(resinfo, S_LEN)) 501176434Skaiw break; 502176434Skaiw 503176434Skaiw if (handle_small_res(resinfo, S_ITEM, S_LEN) == 1) 504176434Skaiw break; 505176434Skaiw free(resinfo); 506176434Skaiw } else { 507176434Skaiw /* Handle large resouce data types */ 508176434Skaiw 509176434Skaiw if (!get_resource_info((char *) &large_len, 2)) 510176434Skaiw break; 511176434Skaiw 512176434Skaiw resinfo = malloc(large_len); 513177064Skaiw if (!get_resource_info(resinfo, large_len)) 514177064Skaiw break; 515177064Skaiw 516176434Skaiw handle_large_res(resinfo, L_ITEM, large_len); 517176434Skaiw free(resinfo); 518176434Skaiw } 519177064Skaiw } 520176434Skaiw printf("Successfully got %d resources, %d logical fdevs\n", i, 521176434Skaiw logdevs); 522176434Skaiw printf("-- card select # 0x%04x\n", pnp_read(SET_CSN)); 523176434Skaiw printf("\nCSN %c%c%c%02x%02x (0x%08x), Serial Number 0x%08x\n", 524176434Skaiw ((data[0] & 0x7c) >> 2) + 64, 525176434Skaiw (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64, 526176434Skaiw (data[1] & 0x1f) + 64, data[2], data[3], 527176434Skaiw *(int *)&(data[0]), 528176434Skaiw *(int *)&(data[4])); 529176434Skaiw 530176434Skaiw for (i=0; i<logdevs; i++) { 531176434Skaiw int j; 532176434Skaiw 533176434Skaiw pnp_write(SET_LDN, i); 534176434Skaiw 535176434Skaiw printf("\nLogical device #%d\n", pnp_read(SET_LDN) ); 536176434Skaiw printf("IO: "); 537176434Skaiw for (j=0; j<8; j++) 538176434Skaiw printf(" 0x%04x", pnp_readw(IO_CONFIG_BASE + j*2)); 539176434Skaiw printf("\nIRQ %d %d\n", 540176434Skaiw pnp_read(IRQ_CONFIG), pnp_read(IRQ_CONFIG+2) ); 541176434Skaiw printf("DMA %d %d\n", 542176434Skaiw pnp_read(DRQ_CONFIG), pnp_read(DRQ_CONFIG+1) ); 543176434Skaiw printf("IO range check 0x%02x activate 0x%02x\n", 544224650Semaste pnp_read(IO_RANGE_CHECK), pnp_read(ACTIVATE) ); 545176434Skaiw } 546176434Skaiw} 547176434Skaiw 548176434Skaiw 549176434Skaiw/* 550176434Skaiw * Run the isolation protocol. Use rd_port as the READ_DATA port 551176434Skaiw * value (caller should try multiple READ_DATA locations before giving 552176434Skaiw * up). Upon exiting, all cards are aware that they should use rd_port 553176434Skaiw * as the READ_DATA port; 554176434Skaiw * 555176434Skaiw */ 556285224Semasteint 557285224Semasteisolation_protocol() 558285224Semaste{ 559285224Semaste int csn; 560285224Semaste u_char data[9]; 561285224Semaste 562285224Semaste send_Initiation_LFSR(); 563285224Semaste 564285224Semaste /* Reset CSN for All Cards */ 565285224Semaste pnp_write(CONFIG_CONTROL, 0x04); 566285224Semaste 567285224Semaste for (csn = 1; (csn < MAX_PNP_CARDS); csn++) { 568285224Semaste /* Wake up cards without a CSN */ 569285224Semaste logdevs = 0 ; 570285224Semaste pnp_write(WAKE, 0); 571285224Semaste pnp_write(SET_RD_DATA, rd_port); 572285224Semaste outb(_PNP_ADDRESS, SERIAL_ISOLATION); 573285224Semaste DELAY(1000); /* Delay 1 msec */ 574285224Semaste 575285224Semaste if (get_serial(data)) 576285224Semaste dump_resdata(data, csn); 577285224Semaste else 578285224Semaste break; 579176434Skaiw } 580176434Skaiw return csn - 1; 581176434Skaiw} 582176434Skaiw 583176434Skaiw 584285224Semastevoid 585176434Skaiwmain() 586176434Skaiw{ 587176434Skaiw int num_pnp_devs; 588176434Skaiw 589176434Skaiw /* Hey what about a i386_iopl() call :) */ 590176434Skaiw if (open("/dev/io", O_RDONLY) < 0) { 591176434Skaiw fprintf (stderr, "pnpinfo: Can't get I/O privilege.\n"); 592176434Skaiw exit (1); 593176434Skaiw } 594176434Skaiw printf("Checking for Plug-n-Play devices...\n"); 595176434Skaiw 596176434Skaiw /* Try various READ_DATA ports from 0x203-0x3ff */ 597176434Skaiw for (rd_port = 0x80; (rd_port < 0xff); rd_port += 0x10) { 598176434Skaiw DEB(printf("Trying Read_Port at %x...\n", (rd_port << 2) | 0x3) ); 599176434Skaiw num_pnp_devs = isolation_protocol(rd_port); 600176434Skaiw if (num_pnp_devs) 601176434Skaiw break; 602176434Skaiw } 603176434Skaiw if (!num_pnp_devs) { 604176434Skaiw printf("No Plug-n-Play devices were found\n"); 605176434Skaiw return; 606176434Skaiw } 607176434Skaiw} 608176434Skaiw