pnpinfo.c revision 47405
129615Sjmg/* 229615Sjmg * Copyright (c) 1996, Sujal M. Patel 329615Sjmg * All rights reserved. 429615Sjmg * 529615Sjmg * Redistribution and use in source and binary forms, with or without 629615Sjmg * modification, are permitted provided that the following conditions 729615Sjmg * are met: 829615Sjmg * 1. Redistributions of source code must retain the above copyright 929615Sjmg * notice, this list of conditions and the following disclaimer. 1029615Sjmg * 2. Redistributions in binary form must reproduce the above copyright 1129615Sjmg * notice, this list of conditions and the following disclaimer in the 1229615Sjmg * documentation and/or other materials provided with the distribution. 1329615Sjmg * 1429615Sjmg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1529615Sjmg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1629615Sjmg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1729615Sjmg * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1829615Sjmg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1929615Sjmg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2029615Sjmg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2129615Sjmg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2229615Sjmg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2329615Sjmg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2429615Sjmg * SUCH DAMAGE. 2529615Sjmg * 2647405Sdfr * $Id: pnpinfo.c,v 1.4 1999/05/04 16:59:42 luoqi Exp $ 2729615Sjmg */ 2829615Sjmg 2929615Sjmg#include <sys/time.h> 3029615Sjmg 3129615Sjmg#include <stdio.h> 3229615Sjmg#include <stdlib.h> 3329615Sjmg#include <unistd.h> 3429615Sjmg#include <fcntl.h> 3529615Sjmg#include <string.h> 3629615Sjmg 3729615Sjmg#include <machine/cpufunc.h> 3829615Sjmg 3929615Sjmg#include <i386/isa/pnp.h> 4029615Sjmg 4129615Sjmg#ifdef DEBUG 4229615Sjmg#define DEB(x) x 4329615Sjmg#else 4429615Sjmg#define DEB(x) 4529615Sjmg#endif 4629615Sjmg#define DDB(x) x 4729615Sjmg 4829615Sjmgvoid 4929615Sjmgpnp_write(int d, u_char r) 5029615Sjmg{ 5129615Sjmg outb (_PNP_ADDRESS, d); 5229615Sjmg outb (_PNP_WRITE_DATA, r); 5329615Sjmg} 5439144Seivind 5529615Sjmg/* The READ_DATA port that we are using currently */ 5629615Sjmgstatic int rd_port; 5729615Sjmg 5829615Sjmgu_char 5929615Sjmgpnp_read(int d) 6029615Sjmg{ 6129615Sjmg outb(_PNP_ADDRESS, d); 6229615Sjmg return inb( (rd_port << 2) + 3) & 0xff; 6329615Sjmg} 6429615Sjmg 6531135Sjmgu_short 6629615Sjmgpnp_readw(int d) 6729615Sjmg{ 6829615Sjmg int c = pnp_read(d) << 8 ; 6929615Sjmg c |= pnp_read(d+1); 7029615Sjmg return c; 7129615Sjmg} 7229615Sjmg 7329615Sjmgint logdevs=0; 7429615Sjmg 7529615Sjmgvoid DELAY __P((int i)); 7629615Sjmgvoid send_Initiation_LFSR(); 7729615Sjmgint get_serial __P((u_char *data)); 7829615Sjmgint get_resource_info __P((u_char *buffer, int len)); 7929615Sjmgint handle_small_res __P((u_char *resinfo, int item, int len)); 8029615Sjmgvoid handle_large_res __P((u_char *resinfo, int item, int len)); 8129615Sjmgvoid dump_resdata __P((u_char *data, int csn)); 8229615Sjmgint isolation_protocol(); 8329615Sjmg 8429615Sjmg 8529615Sjmg/* 8629615Sjmg * DELAY does accurate delaying in user-space. 8729615Sjmg * This function busy-waits. 8829615Sjmg */ 8929615Sjmgvoid 9029615SjmgDELAY (int i) 9129615Sjmg{ 9229615Sjmg struct timeval t; 9329615Sjmg long start, stop; 9429615Sjmg 9529615Sjmg i *= 4; 9629615Sjmg 9729615Sjmg gettimeofday (&t, NULL); 9829615Sjmg start = t.tv_sec * 1000000 + t.tv_usec; 9929615Sjmg do { 10029615Sjmg gettimeofday (&t, NULL); 10129615Sjmg stop = t.tv_sec * 1000000 + t.tv_usec; 10229615Sjmg } while (start + i > stop); 10329615Sjmg} 10429615Sjmg 10529615Sjmg 10629615Sjmg/* 10729615Sjmg * Send Initiation LFSR as described in "Plug and Play ISA Specification, 10829615Sjmg * Intel May 94." 10929615Sjmg */ 11029615Sjmgvoid 11129615Sjmgsend_Initiation_LFSR() 11229615Sjmg{ 11329615Sjmg int cur, i; 11429615Sjmg 11529615Sjmg pnp_write(CONFIG_CONTROL, 0x2); 11629615Sjmg 11729615Sjmg /* Reset the LSFR */ 11829615Sjmg outb(_PNP_ADDRESS, 0); 11929615Sjmg outb(_PNP_ADDRESS, 0); /* yes, we do need it twice! */ 12029615Sjmg 12129615Sjmg cur = 0x6a; 12229615Sjmg 12329615Sjmg for (i = 0; i < 32; i++) { 12429615Sjmg outb(_PNP_ADDRESS, cur); 12529615Sjmg cur = (cur >> 1) | (((cur ^ (cur >> 1)) << 7) & 0xff); 12629615Sjmg } 12729615Sjmg} 12829615Sjmg 12929615Sjmg/* 13029615Sjmg * Get the device's serial number. Returns 1 if the serial is valid. 13129615Sjmg */ 13229615Sjmgint 13329615Sjmgget_serial(u_char *data) 13429615Sjmg{ 13529615Sjmg int i, bit, valid = 0, sum = 0x6a; 13629615Sjmg 13729615Sjmg bzero(data, sizeof(char) * 9); 13829615Sjmg 13929615Sjmg for (i = 0; i < 72; i++) { 14029615Sjmg bit = inb((rd_port << 2) | 0x3) == 0x55; 14129615Sjmg DELAY(250); /* Delay 250 usec */ 14229615Sjmg 14329615Sjmg /* Can't Short Circuit the next evaluation, so 'and' is last */ 14429615Sjmg bit = (inb((rd_port << 2) | 0x3) == 0xaa) && bit; 14529615Sjmg DELAY(250); /* Delay 250 usec */ 14629615Sjmg 14729615Sjmg valid = valid || bit; 14829615Sjmg 14929615Sjmg if (i < 64) 15029615Sjmg sum = (sum >> 1) | 15129615Sjmg (((sum ^ (sum >> 1) ^ bit) << 7) & 0xff); 15229615Sjmg 15329615Sjmg data[i / 8] = (data[i / 8] >> 1) | (bit ? 0x80 : 0); 15429615Sjmg } 15529615Sjmg 15629615Sjmg valid = valid && (data[8] == sum); 15729615Sjmg 15829615Sjmg return valid; 15929615Sjmg} 16029615Sjmg 16129615Sjmg 16229615Sjmg/* 16329615Sjmg * Fill's the buffer with resource info from the device. 16429615Sjmg * Returns 0 if the device fails to report 16529615Sjmg */ 16629615Sjmgint 16729615Sjmgget_resource_info(u_char *buffer, int len) 16829615Sjmg{ 16929615Sjmg int i, j; 17029615Sjmg 17129615Sjmg for (i = 0; i < len; i++) { 17229615Sjmg outb(_PNP_ADDRESS, STATUS); 17329615Sjmg for (j = 0; j < 100; j++) { 17429615Sjmg if ((inb((rd_port << 2) | 0x3)) & 0x1) 17529615Sjmg break; 17629615Sjmg DELAY(1); 17729615Sjmg } 17829615Sjmg if (j == 100) { 17929615Sjmg printf("PnP device failed to report resource data\n"); 18029615Sjmg return 0; 18129615Sjmg } 18229615Sjmg outb(_PNP_ADDRESS, RESOURCE_DATA); 18329615Sjmg buffer[i] = inb((rd_port << 2) | 0x3); 18429615Sjmg DEB(printf("--- get_resource_info: got 0x%02x\n",(unsigned)buffer[i])); 18529615Sjmg } 18629615Sjmg return 1; 18729615Sjmg} 18829615Sjmg 18929615Sjmgvoid 19029615Sjmgreport_dma_info (x) 19129615Sjmg int x; 19229615Sjmg{ 19329615Sjmg char *s1=NULL, *s2=NULL, *s3=NULL, *s4=NULL, *s5=NULL; 19429615Sjmg 19529615Sjmg switch (x & 0x3) { 19629615Sjmg case 0: 19729615Sjmg s1="8-bit"; 19829615Sjmg break; 19929615Sjmg case 1: 20029615Sjmg s1="8/16-bit"; 20129615Sjmg break; 20229615Sjmg case 2: 20329615Sjmg s1="16-bit"; 20429615Sjmg break; 20529615Sjmg#ifdef DIAGNOSTIC 20629615Sjmg case 3: 20729615Sjmg s1="Reserved"; 20829615Sjmg break; 20929615Sjmg#endif 21029615Sjmg } 21129615Sjmg 21229615Sjmg s2 = (x & 0x4) ? "bus master" : "not a bus master"; 21329615Sjmg 21429615Sjmg s3 = (x & 0x8) ? "count by byte" : ""; 21529615Sjmg 21629615Sjmg s4 = (x & 0x10) ? "count by word" : ""; 21729615Sjmg 21829615Sjmg switch ((x & 0x60) >> 5) { 21929615Sjmg case 0: 22029615Sjmg s5="Compatibility mode"; 22129615Sjmg break; 22229615Sjmg case 1: 22329615Sjmg s5="Type A"; 22429615Sjmg break; 22529615Sjmg case 2: 22629615Sjmg s5="Type B"; 22729615Sjmg break; 22829615Sjmg case 3: 22929615Sjmg s5="Type F"; 23029615Sjmg break; 23129615Sjmg } 23229615Sjmg printf("\t%s, %s, %s, %s, %s\n",s1,s2,s3,s4,s5); 23329615Sjmg} 23429615Sjmg 23529615Sjmg 23629615Sjmgvoid 23729615Sjmgreport_memory_info (int x) 23829615Sjmg{ 23929615Sjmg if (x & 0x1) 24029615Sjmg printf ("Memory Range: Writeable\n"); 24129615Sjmg else 24229615Sjmg printf ("Memory Range: Not writeable (ROM)\n"); 24329615Sjmg 24429615Sjmg if (x & 0x2) 24529615Sjmg printf ("Memory Range: Read-cacheable, write-through\n"); 24629615Sjmg else 24729615Sjmg printf ("Memory Range: Non-cacheable\n"); 24829615Sjmg 24929615Sjmg if (x & 0x4) 25029615Sjmg printf ("Memory Range: Decode supports high address\n"); 25129615Sjmg else 25229615Sjmg printf ("Memory Range: Decode supports range length\n"); 25329615Sjmg 25429615Sjmg switch ((x & 0x18) >> 3) { 25529615Sjmg case 0: 25629615Sjmg printf ("Memory Range: 8-bit memory only\n"); 25729615Sjmg break; 25829615Sjmg case 1: 25929615Sjmg printf ("Memory Range: 16-bit memory only\n"); 26029615Sjmg break; 26129615Sjmg case 2: 26229615Sjmg printf ("Memory Range: 8-bit and 16-bit memory supported\n"); 26329615Sjmg break; 26429615Sjmg#ifdef DIAGNOSTIC 26529615Sjmg case 3: 26629615Sjmg printf ("Memory Range: Reserved\n"); 26729615Sjmg break; 26829615Sjmg#endif 26929615Sjmg } 27029615Sjmg 27129615Sjmg if (x & 0x20) 27229615Sjmg printf ("Memory Range: Memory is shadowable\n"); 27329615Sjmg else 27429615Sjmg printf ("Memory Range: Memory is not shadowable\n"); 27529615Sjmg 27629615Sjmg if (x & 0x40) 27729615Sjmg printf ("Memory Range: Memory is an expansion ROM\n"); 27829615Sjmg else 27929615Sjmg printf ("Memory Range: Memory is not an expansion ROM\n"); 28029615Sjmg 28129615Sjmg#ifdef DIAGNOSTIC 28229615Sjmg if (x & 0x80) 28329615Sjmg printf ("Memory Range: Reserved (Device is brain-damaged)\n"); 28429615Sjmg#endif 28529615Sjmg} 28629615Sjmg 28729615Sjmg 28829615Sjmg/* 28929615Sjmg * Small Resource Tag Handler 29029615Sjmg * 29129615Sjmg * Returns 1 if checksum was valid (and an END_TAG was received). 29229615Sjmg * Returns -1 if checksum was invalid (and an END_TAG was received). 29329615Sjmg * Returns 0 for other tags. 29429615Sjmg */ 29529615Sjmgint 29629615Sjmghandle_small_res(u_char *resinfo, int item, int len) 29729615Sjmg{ 29829615Sjmg int i; 29929615Sjmg 30029615Sjmg DEB(printf("*** ITEM 0x%04x len %d detected\n", item, len)); 30129615Sjmg 30229615Sjmg switch (item) { 30329615Sjmg default: 30429615Sjmg printf("*** ITEM 0x%02x detected\n", item); 30529615Sjmg break; 30629615Sjmg case PNP_VERSION: 30729615Sjmg printf("PnP Version %d.%d, Vendor Version %d\n", 30829615Sjmg resinfo[0] >> 4, resinfo[0] & (0xf), resinfo[1]); 30929615Sjmg break; 31029615Sjmg case LOG_DEVICE_ID: 31129615Sjmg printf("\nLogical Device ID: %c%c%c%02x%02x 0x%08x #%d\n", 31229615Sjmg ((resinfo[0] & 0x7c) >> 2) + 64, 31329615Sjmg (((resinfo[0] & 0x03) << 3) | 31429615Sjmg ((resinfo[1] & 0xe0) >> 5)) + 64, 31529615Sjmg (resinfo[1] & 0x1f) + 64, 31629615Sjmg resinfo[2], resinfo[3], *(int *)(resinfo), 31729615Sjmg logdevs++); 31829615Sjmg 31929615Sjmg if (resinfo[4] & 0x1) 32029615Sjmg printf ("\tDevice powers up active\n"); /* XXX */ 32129615Sjmg if (resinfo[4] & 0x2) 32229615Sjmg printf ("\tDevice supports I/O Range Check\n"); 32329615Sjmg if (resinfo[4] > 0x3) 32429615Sjmg printf ("\tReserved register funcs %02x\n", 32529615Sjmg resinfo[4]); 32629615Sjmg 32729615Sjmg if (len == 6) 32829615Sjmg printf("\tVendor register funcs %02x\n", resinfo[5]); 32929615Sjmg break; 33029615Sjmg case COMP_DEVICE_ID: 33129615Sjmg printf("Compatible Device ID: %c%c%c%02x%02x (%08x)\n", 33229615Sjmg ((resinfo[0] & 0x7c) >> 2) + 64, 33329615Sjmg (((resinfo[0] & 0x03) << 3) | 33429615Sjmg ((resinfo[1] & 0xe0) >> 5)) + 64, 33529615Sjmg (resinfo[1] & 0x1f) + 64, 33629615Sjmg resinfo[2], resinfo[3], *(int *)resinfo); 33729615Sjmg break; 33829615Sjmg case IRQ_FORMAT: 33929615Sjmg printf(" IRQ: "); 34029615Sjmg 34129615Sjmg for (i = 0; i < 8; i++) 34229615Sjmg if (resinfo[0] & (1<<i)) 34329615Sjmg printf("%d ", i); 34429615Sjmg for (i = 0; i < 8; i++) 34529615Sjmg if (resinfo[1] & (1<<i)) 34629615Sjmg printf("%d ", i + 8); 34729615Sjmg if (len == 3) { 34829615Sjmg if (resinfo[2] & 0x1) 34929615Sjmg printf("IRQ: High true edge sensitive\n"); 35029615Sjmg if (resinfo[2] & 0x2) 35129615Sjmg printf("IRQ: Low true edge sensitive\n"); 35229615Sjmg if (resinfo[2] & 0x4) 35329615Sjmg printf("IRQ: High true level sensitive\n"); 35429615Sjmg if (resinfo[2] & 0x8) 35529615Sjmg printf("IRQ: Low true level sensitive\n"); 35629615Sjmg } else { 35729615Sjmg printf(" - only one type (true/edge)\n"); 35829615Sjmg } 35929615Sjmg break; 36029615Sjmg case DMA_FORMAT: 36129615Sjmg printf(" DMA: channel(s) "); 36229615Sjmg for (i = 0; i < 8; i++) 36329615Sjmg if (resinfo[0] & (1<<i)) 36429615Sjmg printf("%d ", i); 36529615Sjmg printf ("\n"); 36629615Sjmg report_dma_info (resinfo[1]); 36729615Sjmg break; 36829615Sjmg case START_DEPEND_FUNC: 36929615Sjmg printf("TAG Start DF\n"); 37029615Sjmg if (len == 1) { 37129615Sjmg switch (resinfo[0]) { 37229615Sjmg case 0: 37329615Sjmg printf("Good Configuration\n"); 37429615Sjmg break; 37529615Sjmg case 1: 37629615Sjmg printf("Acceptable Configuration\n"); 37729615Sjmg break; 37829615Sjmg case 2: 37929615Sjmg printf("Sub-optimal Configuration\n"); 38029615Sjmg break; 38129615Sjmg } 38229615Sjmg } 38329615Sjmg break; 38429615Sjmg case END_DEPEND_FUNC: 38529615Sjmg printf("TAG End DF\n"); 38629615Sjmg break; 38729615Sjmg case IO_PORT_DESC: 38829615Sjmg printf(" I/O Range 0x%x .. 0x%x, alignment 0x%x, len 0x%x\n", 38929615Sjmg resinfo[1] + (resinfo[2] << 8), 39029615Sjmg resinfo[3] + (resinfo[4] << 8), 39129615Sjmg resinfo[5], resinfo[6] ); 39229615Sjmg if (resinfo[0]) 39329615Sjmg printf("\t[16-bit addr]\n"); 39429615Sjmg else 39529615Sjmg printf("\t[not 16-bit addr]\n"); 39629615Sjmg break; 39729615Sjmg case FIXED_IO_PORT_DESC: 39829615Sjmg printf (" FIXED I/O base address 0x%x length 0x%x\n", 39929615Sjmg resinfo[0] + ( (resinfo[1] & 3 ) << 8), /* XXX */ 40029615Sjmg resinfo[2]); 40129615Sjmg break; 40229615Sjmg#ifdef DIAGNOSTIC 40329615Sjmg case SM_RES_RESERVED: 40429615Sjmg printf("Reserved Tag Detected\n"); 40529615Sjmg break; 40629615Sjmg#endif 40729615Sjmg case SM_VENDOR_DEFINED: 40829615Sjmg printf("*** Small Vendor Tag Detected\n"); 40929615Sjmg break; 41029615Sjmg case END_TAG: 41129615Sjmg printf("End Tag\n\n"); 41229615Sjmg /* XXX Record and Verify Checksum */ 41329615Sjmg return 1; 41429615Sjmg break; 41529615Sjmg } 41629615Sjmg return 0; 41729615Sjmg} 41829615Sjmg 41929615Sjmg 42029615Sjmgvoid 42129615Sjmghandle_large_res(u_char *resinfo, int item, int len) 42229615Sjmg{ 42329615Sjmg int i; 42429615Sjmg 42529615Sjmg DEB(printf("*** Large ITEM %d len %d found\n", item, len)); 42629615Sjmg switch (item) { 42729615Sjmg case MEMORY_RANGE_DESC: 42829615Sjmg report_memory_info(resinfo[0]); 42929615Sjmg printf("Memory range minimum address: 0x%x\n", 43029615Sjmg (resinfo[1] << 8) + (resinfo[2] << 16)); 43129615Sjmg printf("Memory range maximum address: 0x%x\n", 43229615Sjmg (resinfo[3] << 8) + (resinfo[4] << 16)); 43329615Sjmg printf("Memory range base alignment: 0x%x\n", 43429615Sjmg (i = (resinfo[5] + (resinfo[6] << 8))) ? i : (1 << 16)); 43529615Sjmg printf("Memory range length: 0x%x\n", 43629615Sjmg (resinfo[7] + (resinfo[8] << 8)) * 256); 43729615Sjmg break; 43829615Sjmg case ID_STRING_ANSI: 43929615Sjmg printf("Device Description: "); 44029615Sjmg 44129615Sjmg for (i = 0; i < len; i++) { 44229615Sjmg if (resinfo[i]) /* XXX */ 44329615Sjmg printf("%c", resinfo[i]); 44429615Sjmg } 44529615Sjmg printf("\n"); 44629615Sjmg break; 44729615Sjmg case ID_STRING_UNICODE: 44829615Sjmg printf("ID String Unicode Detected (Undefined)\n"); 44929615Sjmg break; 45029615Sjmg case LG_VENDOR_DEFINED: 45129615Sjmg printf("Large Vendor Defined Detected\n"); 45229615Sjmg break; 45329615Sjmg case _32BIT_MEM_RANGE_DESC: 45429615Sjmg printf("32bit Memory Range Desc Unimplemented\n"); 45529615Sjmg break; 45629615Sjmg case _32BIT_FIXED_LOC_DESC: 45729615Sjmg printf("32bit Fixed Location Desc Unimplemented\n"); 45829615Sjmg break; 45929615Sjmg case LG_RES_RESERVED: 46029615Sjmg printf("Large Reserved Tag Detected\n"); 46129615Sjmg break; 46229615Sjmg } 46329615Sjmg} 46429615Sjmg 46529615Sjmg 46629615Sjmg/* 46729615Sjmg * Dump all the information about configurations. 46829615Sjmg */ 46929615Sjmgvoid 47029615Sjmgdump_resdata(u_char *data, int csn) 47129615Sjmg{ 47229615Sjmg int i, large_len; 47329615Sjmg 47429615Sjmg u_char tag, *resinfo; 47529615Sjmg 47629615Sjmg DDB(printf("\nCard assigned CSN #%d\n", csn)); 47729615Sjmg printf("Vendor ID %c%c%c%02x%02x (0x%08x), Serial Number 0x%08x\n", 47829615Sjmg ((data[0] & 0x7c) >> 2) + 64, 47929615Sjmg (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64, 48029615Sjmg (data[1] & 0x1f) + 64, data[2], data[3], 48129615Sjmg *(int *)&(data[0]), 48229615Sjmg *(int *)&(data[4])); 48329615Sjmg 48429615Sjmg pnp_write(SET_CSN, csn); /* Move this out of this function XXX */ 48529615Sjmg outb(_PNP_ADDRESS, STATUS); 48629615Sjmg 48729615Sjmg /* Allows up to 1kb of Resource Info, Should be plenty */ 48829615Sjmg for (i = 0; i < 1024; i++) { 48929615Sjmg if (!get_resource_info(&tag, 1)) 49029615Sjmg break; 49129615Sjmg 49239144Seivind if (PNP_RES_TYPE(tag) == 0) { 49329615Sjmg /* Handle small resouce data types */ 49429615Sjmg 49539144Seivind resinfo = malloc(PNP_SRES_LEN(tag)); 49639144Seivind if (!get_resource_info(resinfo, PNP_SRES_LEN(tag))) 49729615Sjmg break; 49829615Sjmg 49939144Seivind if (handle_small_res(resinfo, PNP_SRES_NUM(tag), PNP_SRES_LEN(tag)) == 1) 50029615Sjmg break; 50129615Sjmg free(resinfo); 50229615Sjmg } else { 50329615Sjmg /* Handle large resouce data types */ 50446422Sluoqi u_char buf[2]; 50546422Sluoqi if (!get_resource_info((char *)buf, 2)) 50629615Sjmg break; 50746422Sluoqi large_len = (buf[1] << 8) + buf[0]; 50829615Sjmg 50929615Sjmg resinfo = malloc(large_len); 51029615Sjmg if (!get_resource_info(resinfo, large_len)) 51129615Sjmg break; 51229615Sjmg 51339144Seivind handle_large_res(resinfo, PNP_LRES_NUM(tag), large_len); 51429615Sjmg free(resinfo); 51529615Sjmg } 51629615Sjmg } 51729615Sjmg printf("Successfully got %d resources, %d logical fdevs\n", i, 51829615Sjmg logdevs); 51929615Sjmg printf("-- card select # 0x%04x\n", pnp_read(SET_CSN)); 52029615Sjmg printf("\nCSN %c%c%c%02x%02x (0x%08x), Serial Number 0x%08x\n", 52129615Sjmg ((data[0] & 0x7c) >> 2) + 64, 52229615Sjmg (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64, 52329615Sjmg (data[1] & 0x1f) + 64, data[2], data[3], 52429615Sjmg *(int *)&(data[0]), 52529615Sjmg *(int *)&(data[4])); 52629615Sjmg 52729615Sjmg for (i=0; i<logdevs; i++) { 52829615Sjmg int j; 52929615Sjmg 53029615Sjmg pnp_write(SET_LDN, i); 53129615Sjmg 53229615Sjmg printf("\nLogical device #%d\n", pnp_read(SET_LDN) ); 53329615Sjmg printf("IO: "); 53429615Sjmg for (j=0; j<8; j++) 53529615Sjmg printf(" 0x%04x", pnp_readw(IO_CONFIG_BASE + j*2)); 53629615Sjmg printf("\nIRQ %d %d\n", 53729615Sjmg pnp_read(IRQ_CONFIG), pnp_read(IRQ_CONFIG+2) ); 53829615Sjmg printf("DMA %d %d\n", 53929615Sjmg pnp_read(DRQ_CONFIG), pnp_read(DRQ_CONFIG+1) ); 54029615Sjmg printf("IO range check 0x%02x activate 0x%02x\n", 54129615Sjmg pnp_read(IO_RANGE_CHECK), pnp_read(ACTIVATE) ); 54229615Sjmg } 54329615Sjmg} 54429615Sjmg 54529615Sjmg 54629615Sjmg/* 54729615Sjmg * Run the isolation protocol. Use rd_port as the READ_DATA port 54829615Sjmg * value (caller should try multiple READ_DATA locations before giving 54929615Sjmg * up). Upon exiting, all cards are aware that they should use rd_port 55029615Sjmg * as the READ_DATA port; 55129615Sjmg * 55229615Sjmg */ 55329615Sjmgint 55429615Sjmgisolation_protocol() 55529615Sjmg{ 55629615Sjmg int csn; 55729615Sjmg u_char data[9]; 55829615Sjmg 55929615Sjmg send_Initiation_LFSR(); 56029615Sjmg 56129615Sjmg /* Reset CSN for All Cards */ 56229615Sjmg pnp_write(CONFIG_CONTROL, 0x04); 56329615Sjmg 56429615Sjmg for (csn = 1; (csn < MAX_PNP_CARDS); csn++) { 56529615Sjmg /* Wake up cards without a CSN */ 56629615Sjmg logdevs = 0 ; 56729615Sjmg pnp_write(WAKE, 0); 56829615Sjmg pnp_write(SET_RD_DATA, rd_port); 56929615Sjmg outb(_PNP_ADDRESS, SERIAL_ISOLATION); 57029615Sjmg DELAY(1000); /* Delay 1 msec */ 57129615Sjmg 57229615Sjmg if (get_serial(data)) 57329615Sjmg dump_resdata(data, csn); 57429615Sjmg else 57529615Sjmg break; 57629615Sjmg } 57729615Sjmg return csn - 1; 57829615Sjmg} 57929615Sjmg 58029615Sjmg 58147405Sdfrint 58247405Sdfrmain(int argc, char **argv) 58329615Sjmg{ 58429615Sjmg int num_pnp_devs; 58529615Sjmg 58647405Sdfr#ifdef __i386__ 58729615Sjmg /* Hey what about a i386_iopl() call :) */ 58829615Sjmg if (open("/dev/io", O_RDONLY) < 0) { 58929615Sjmg fprintf (stderr, "pnpinfo: Can't get I/O privilege.\n"); 59029615Sjmg exit (1); 59129615Sjmg } 59247405Sdfr#endif 59347405Sdfr#ifdef __alpha__ 59447405Sdfr ioperm(0x203, 0x400 - 0x203, 1); 59547405Sdfr#endif 59647405Sdfr 59729615Sjmg printf("Checking for Plug-n-Play devices...\n"); 59829615Sjmg 59929615Sjmg /* Try various READ_DATA ports from 0x203-0x3ff */ 60029615Sjmg for (rd_port = 0x80; (rd_port < 0xff); rd_port += 0x10) { 60129615Sjmg DEB(printf("Trying Read_Port at %x...\n", (rd_port << 2) | 0x3) ); 60229615Sjmg num_pnp_devs = isolation_protocol(rd_port); 60329615Sjmg if (num_pnp_devs) 60429615Sjmg break; 60529615Sjmg } 60629615Sjmg if (!num_pnp_devs) { 60729615Sjmg printf("No Plug-n-Play devices were found\n"); 60847405Sdfr return 0; 60929615Sjmg } 61029615Sjmg} 611