pnpinfo.c revision 101611
139211Sgibbs/* 239211Sgibbs * Copyright (c) 1996, Sujal M. Patel 339211Sgibbs * All rights reserved. 439211Sgibbs * 539211Sgibbs * Redistribution and use in source and binary forms, with or without 639211Sgibbs * modification, are permitted provided that the following conditions 739211Sgibbs * are met: 839211Sgibbs * 1. Redistributions of source code must retain the above copyright 939211Sgibbs * notice, this list of conditions and the following disclaimer. 1039211Sgibbs * 2. Redistributions in binary form must reproduce the above copyright 1139211Sgibbs * notice, this list of conditions and the following disclaimer in the 1239211Sgibbs * documentation and/or other materials provided with the distribution. 1339211Sgibbs * 1439211Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1539211Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1639211Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1739211Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1839211Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1939211Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2039211Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2139211Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2239211Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2339211Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2439211Sgibbs * SUCH DAMAGE. 2539211Sgibbs * 2639211Sgibbs * $FreeBSD: head/contrib/pnpinfo/pnpinfo.c 101611 2002-08-09 22:04:54Z iedowse $ 2739211Sgibbs */ 2839211Sgibbs 2983551Sdillon#include <sys/time.h> 3083551Sdillon 3183551Sdillon#include <stdio.h> 3239211Sgibbs#include <stdlib.h> 3339211Sgibbs#include <unistd.h> 3439211Sgibbs#include <fcntl.h> 35110998Sphk#include <string.h> 3681133Stmm 3739211Sgibbs#include <machine/cpufunc.h> 3839451Sken 3939211Sgibbs#include <isa/pnpreg.h> 4081133Stmm 4181133Stmm#ifdef DEBUG 4239211Sgibbs#define DEB(x) x 4339211Sgibbs#else 4439211Sgibbs#define DEB(x) 4581133Stmm#endif 4681133Stmm#define DDB(x) x 47121064Sbde 4839211Sgibbsvoid 4939211Sgibbspnp_write(int d, u_char r) 5039211Sgibbs{ 51113710Sphk outb (_PNP_ADDRESS, d); 52113710Sphk outb (_PNP_WRITE_DATA, r); 53113710Sphk} 54113710Sphk 55113710Sphk/* The READ_DATA port that we are using currently */ 56113710Sphkstatic int rd_port; 57113710Sphk 58113710Sphku_char 5981133Stmmpnp_read(int d) 6081133Stmm{ 6181133Stmm outb(_PNP_ADDRESS, d); 6281883Sken return inb( (rd_port << 2) + 3) & 0xff; 6381883Sken} 6481133Stmm 6581133Stmmu_short 6639211Sgibbspnp_readw(int d) 6739211Sgibbs{ 6839211Sgibbs int c = pnp_read(d) << 8 ; 6939211Sgibbs c |= pnp_read(d+1); 7039211Sgibbs return c; 7139211Sgibbs} 7239211Sgibbs 7339211Sgibbsint logdevs=0; 7439211Sgibbs 7539211Sgibbsvoid DELAY __P((int i)); 7639211Sgibbsvoid send_Initiation_LFSR(); 7739211Sgibbsint get_serial __P((u_char *data)); 7839211Sgibbsint get_resource_info __P((u_char *buffer, int len)); 7939211Sgibbsint handle_small_res __P((u_char *resinfo, int item, int len)); 8039211Sgibbsvoid handle_large_res __P((u_char *resinfo, int item, int len)); 8139211Sgibbsvoid dump_resdata __P((u_char *data, int csn)); 8239211Sgibbsint isolation_protocol(); 8339211Sgibbs 8439211Sgibbs 8539211Sgibbs/* 8639211Sgibbs * DELAY does accurate delaying in user-space. 8739211Sgibbs * This function busy-waits. 8839211Sgibbs */ 8939211Sgibbsvoid 9039211SgibbsDELAY (int i) 9139211Sgibbs{ 9239211Sgibbs struct timeval t; 9381133Stmm long start, stop; 9481133Stmm 9581133Stmm i *= 4; 9681133Stmm 9781133Stmm gettimeofday (&t, NULL); 9881133Stmm start = t.tv_sec * 1000000 + t.tv_usec; 9981133Stmm do { 10081133Stmm gettimeofday (&t, NULL); 10181133Stmm stop = t.tv_sec * 1000000 + t.tv_usec; 10281133Stmm } while (start + i > stop); 10381133Stmm} 104112405Sphk 10581133Stmm 10681133Stmm/* 10781133Stmm * Send Initiation LFSR as described in "Plug and Play ISA Specification, 10881133Stmm * Intel May 94." 10981133Stmm */ 11081133Stmmvoid 11181133Stmmsend_Initiation_LFSR() 11281133Stmm{ 11381133Stmm int cur, i; 11481133Stmm 11581133Stmm pnp_write(PNP_CONFIG_CONTROL, 0x2); 11681133Stmm 11781133Stmm /* Reset the LSFR */ 11881133Stmm outb(_PNP_ADDRESS, 0); 11981133Stmm outb(_PNP_ADDRESS, 0); /* yes, we do need it twice! */ 12081133Stmm 12181133Stmm cur = 0x6a; 12281133Stmm 12381883Sken for (i = 0; i < 32; i++) { 124112406Sphk outb(_PNP_ADDRESS, cur); 125112405Sphk cur = (cur >> 1) | (((cur ^ (cur >> 1)) << 7) & 0xff); 126112405Sphk } 127112405Sphk} 128112405Sphk 129112405Sphk/* 130112405Sphk * Get the device's serial number. Returns 1 if the serial is valid. 131112405Sphk */ 132112405Sphkint 133112373Sphkget_serial(u_char *data) 134112373Sphk{ 135112373Sphk int i, bit, valid = 0, sum = 0x6a; 136244270Strociny 137244270Strociny bzero(data, sizeof(char) * 9); 138244270Strociny 139244270Strociny for (i = 0; i < 72; i++) { 140244270Strociny bit = inb((rd_port << 2) | 0x3) == 0x55; 141244270Strociny DELAY(250); /* Delay 250 usec */ 14281133Stmm 14381133Stmm /* Can't Short Circuit the next evaluation, so 'and' is last */ 14483868Sken bit = (inb((rd_port << 2) | 0x3) == 0xaa) && bit; 14581133Stmm DELAY(250); /* Delay 250 usec */ 14681133Stmm 14781133Stmm valid = valid || bit; 14881133Stmm 14981133Stmm if (i < 64) 15081133Stmm sum = (sum >> 1) | 15181133Stmm (((sum ^ (sum >> 1) ^ bit) << 7) & 0xff); 15281133Stmm 15381133Stmm data[i / 8] = (data[i / 8] >> 1) | (bit ? 0x80 : 0); 15481133Stmm } 15581133Stmm 15639211Sgibbs valid = valid && (data[8] == sum); 15739211Sgibbs 15839211Sgibbs return valid; 15939211Sgibbs} 16081133Stmm 16183868Sken 16281133Stmm/* 16339211Sgibbs * Fill's the buffer with resource info from the device. 16481133Stmm * Returns 0 if the device fails to report 16581133Stmm */ 16681133Stmmint 16739211Sgibbsget_resource_info(u_char *buffer, int len) 16881133Stmm{ 16939211Sgibbs int i, j; 17039211Sgibbs 17139211Sgibbs for (i = 0; i < len; i++) { 17239211Sgibbs outb(_PNP_ADDRESS, PNP_STATUS); 17339211Sgibbs for (j = 0; j < 100; j++) { 17439211Sgibbs if ((inb((rd_port << 2) | 0x3)) & 0x1) 17539211Sgibbs break; 17639211Sgibbs DELAY(1); 17739211Sgibbs } 17881133Stmm if (j == 100) { 17981133Stmm printf("PnP device failed to report resource data\n"); 18081133Stmm return 0; 18181133Stmm } 18282028Sken outb(_PNP_ADDRESS, PNP_RESOURCE_DATA); 183145553Smux buffer[i] = inb((rd_port << 2) | 0x3); 18482028Sken DEB(printf("--- get_resource_info: got 0x%02x\n",(unsigned)buffer[i])); 18581133Stmm } 18681133Stmm return 1; 18781133Stmm} 18881133Stmm 18983868Skenvoid 19081133Stmmreport_dma_info (x) 19181133Stmm int x; 19281133Stmm{ 19381133Stmm char *s1=NULL, *s2=NULL, *s3=NULL, *s4=NULL, *s5=NULL; 19481133Stmm 19539211Sgibbs switch (x & 0x3) { 19639211Sgibbs case 0: 19739211Sgibbs s1="8-bit"; 19839211Sgibbs break; 19939211Sgibbs case 1: 20039211Sgibbs s1="8/16-bit"; 20139211Sgibbs break; 20239211Sgibbs case 2: 20339211Sgibbs s1="16-bit"; 20439498Sken break; 20581133Stmm#ifdef DIAGNOSTIC 20639211Sgibbs case 3: 20739211Sgibbs s1="Reserved"; 20839498Sken break; 20939211Sgibbs#endif 21039498Sken } 21139211Sgibbs 21239211Sgibbs s2 = (x & 0x4) ? "bus master" : "not a bus master"; 21339211Sgibbs 21439211Sgibbs s3 = (x & 0x8) ? "count by byte" : ""; 21581133Stmm 21681133Stmm s4 = (x & 0x10) ? "count by word" : ""; 21781133Stmm 21881133Stmm switch ((x & 0x60) >> 5) { 21982028Sken case 0: 220145553Smux s5="Compatibility mode"; 22181133Stmm break; 22281133Stmm case 1: 22381133Stmm s5="Type A"; 22481133Stmm break; 22581133Stmm case 2: 22681133Stmm s5="Type B"; 22781133Stmm break; 22881133Stmm case 3: 22981133Stmm s5="Type F"; 23039211Sgibbs break; 23139211Sgibbs } 23239211Sgibbs printf("\t%s, %s, %s, %s, %s\n",s1,s2,s3,s4,s5); 23339211Sgibbs} 23439211Sgibbs 23539211Sgibbs 23639211Sgibbsvoid 23739211Sgibbsreport_memory_info (int x) 23839211Sgibbs{ 23981133Stmm if (x & 0x1) 24039211Sgibbs printf ("Memory Range: Writeable\n"); 24139211Sgibbs else 24239211Sgibbs printf ("Memory Range: Not writeable (ROM)\n"); 24339211Sgibbs 24439211Sgibbs if (x & 0x2) 24539211Sgibbs printf ("Memory Range: Read-cacheable, write-through\n"); 24639211Sgibbs else 24739211Sgibbs printf ("Memory Range: Non-cacheable\n"); 24839211Sgibbs 24981133Stmm if (x & 0x4) 25081133Stmm printf ("Memory Range: Decode supports high address\n"); 25181133Stmm else 25281133Stmm printf ("Memory Range: Decode supports range length\n"); 25382028Sken 254145553Smux switch ((x & 0x18) >> 3) { 25581133Stmm case 0: 25681133Stmm printf ("Memory Range: 8-bit memory only\n"); 25781133Stmm break; 25881133Stmm case 1: 25981133Stmm printf ("Memory Range: 16-bit memory only\n"); 26081133Stmm break; 26181133Stmm case 2: 26281133Stmm printf ("Memory Range: 8-bit and 16-bit memory supported\n"); 26381133Stmm break; 26439211Sgibbs#ifdef DIAGNOSTIC 26539211Sgibbs case 3: 26639211Sgibbs printf ("Memory Range: Reserved\n"); 26739211Sgibbs break; 26839211Sgibbs#endif 26939211Sgibbs } 27039211Sgibbs 27139211Sgibbs if (x & 0x20) 27281133Stmm printf ("Memory Range: Memory is shadowable\n"); 27339211Sgibbs else 27481984Sbrian printf ("Memory Range: Memory is not shadowable\n"); 27539211Sgibbs 27681133Stmm if (x & 0x40) 27739451Sken printf ("Memory Range: Memory is an expansion ROM\n"); 27839451Sken else 27939451Sken printf ("Memory Range: Memory is not an expansion ROM\n"); 28081984Sbrian 28139451Sken#ifdef DIAGNOSTIC 28239451Sken if (x & 0x80) 28339451Sken printf ("Memory Range: Reserved (Device is brain-damaged)\n"); 28439451Sken#endif 28581984Sbrian} 28639451Sken 28781984Sbrian 28881984Sbrian/* 28939451Sken * Small Resource Tag Handler 29081984Sbrian * 29182028Sken * Returns 1 if checksum was valid (and an END_TAG was received). 29282028Sken * Returns -1 if checksum was invalid (and an END_TAG was received). 29382028Sken * Returns 0 for other tags. 29482028Sken */ 295145553Smuxint 29639211Sgibbshandle_small_res(u_char *resinfo, int item, int len) 29781984Sbrian{ 29881984Sbrian int i; 29939451Sken 30081984Sbrian DEB(printf("*** ITEM 0x%04x len %d detected\n", item, len)); 30182028Sken 30281984Sbrian switch (item) { 30382028Sken default: 30482028Sken printf("*** ITEM 0x%02x detected\n", item); 305145553Smux break; 30682028Sken case PNP_TAG_VERSION: 30781984Sbrian printf("PnP Version %d.%d, Vendor Version %d\n", 30882028Sken resinfo[0] >> 4, resinfo[0] & (0xf), resinfo[1]); 30982028Sken break; 310145553Smux case PNP_TAG_LOGICAL_DEVICE: 31139211Sgibbs printf("\nLogical Device ID: %c%c%c%02x%02x 0x%08x #%d\n", 31281984Sbrian ((resinfo[0] & 0x7c) >> 2) + 64, 31381984Sbrian (((resinfo[0] & 0x03) << 3) | 31439211Sgibbs ((resinfo[1] & 0xe0) >> 5)) + 64, 31539211Sgibbs (resinfo[1] & 0x1f) + 64, 31639211Sgibbs resinfo[2], resinfo[3], *(int *)(resinfo), 31739211Sgibbs logdevs++); 31839211Sgibbs 31939211Sgibbs if (resinfo[4] & 0x1) 32039211Sgibbs printf ("\tDevice powers up active\n"); /* XXX */ 32139211Sgibbs if (resinfo[4] & 0x2) 32239211Sgibbs printf ("\tDevice supports I/O Range Check\n"); 32339211Sgibbs if (resinfo[4] > 0x3) 32439211Sgibbs printf ("\tReserved register funcs %02x\n", 32539211Sgibbs resinfo[4]); 32639211Sgibbs 32739211Sgibbs if (len == 6) 32839211Sgibbs printf("\tVendor register funcs %02x\n", resinfo[5]); 32939211Sgibbs break; 33039211Sgibbs case PNP_TAG_COMPAT_DEVICE: 33181133Stmm printf("Compatible Device ID: %c%c%c%02x%02x (%08x)\n", 33239211Sgibbs ((resinfo[0] & 0x7c) >> 2) + 64, 33339211Sgibbs (((resinfo[0] & 0x03) << 3) | 33439211Sgibbs ((resinfo[1] & 0xe0) >> 5)) + 64, 33539498Sken (resinfo[1] & 0x1f) + 64, 33639498Sken resinfo[2], resinfo[3], *(int *)resinfo); 33739211Sgibbs break; 33839211Sgibbs case PNP_TAG_IRQ_FORMAT: 339112288Sphk printf(" IRQ: "); 34039211Sgibbs 34139211Sgibbs for (i = 0; i < 8; i++) 34239211Sgibbs if (resinfo[0] & (1<<i)) 34339211Sgibbs printf("%d ", i); 34481133Stmm for (i = 0; i < 8; i++) 345145553Smux if (resinfo[1] & (1<<i)) 34639211Sgibbs printf("%d ", i + 8); 34739211Sgibbs if (len == 3) { 34839211Sgibbs if (resinfo[2] & 0x1) 34939211Sgibbs printf("IRQ: High true edge sensitive\n"); 35039211Sgibbs if (resinfo[2] & 0x2) 35139211Sgibbs printf("IRQ: Low true edge sensitive\n"); 352112288Sphk if (resinfo[2] & 0x4) 353112288Sphk printf("IRQ: High true level sensitive\n"); 35439211Sgibbs if (resinfo[2] & 0x8) 35581133Stmm printf("IRQ: Low true level sensitive\n"); 35681133Stmm } else { 35781133Stmm printf(" - only one type (true/edge)\n"); 35839211Sgibbs } 35981133Stmm break; 36081133Stmm case PNP_TAG_DMA_FORMAT: 36181133Stmm printf(" DMA: channel(s) "); 36239211Sgibbs for (i = 0; i < 8; i++) 363112293Sphk if (resinfo[0] & (1<<i)) 36439211Sgibbs printf("%d ", i); 36581133Stmm printf ("\n"); 36681133Stmm report_dma_info (resinfo[1]); 36781133Stmm break; 36881133Stmm case PNP_TAG_START_DEPENDANT: 36981133Stmm printf("TAG Start DF\n"); 37081133Stmm if (len == 1) { 37181133Stmm switch (resinfo[0]) { 37281133Stmm case 0: 37381133Stmm printf("Good Configuration\n"); 374229735Sghelmer break; 375229735Sghelmer case 1: 376229735Sghelmer printf("Acceptable Configuration\n"); 377229735Sghelmer break; 378229735Sghelmer case 2: 379229735Sghelmer printf("Sub-optimal Configuration\n"); 38081133Stmm break; 38181133Stmm } 38281133Stmm } 38339211Sgibbs break; 38481133Stmm case PNP_TAG_END_DEPENDANT: 38581133Stmm printf("TAG End DF\n"); 38681133Stmm break; 38781133Stmm case PNP_TAG_IO_RANGE: 38881133Stmm printf(" I/O Range 0x%x .. 0x%x, alignment 0x%x, len 0x%x\n", 38981133Stmm resinfo[1] + (resinfo[2] << 8), 39081133Stmm resinfo[3] + (resinfo[4] << 8), 39181133Stmm resinfo[5], resinfo[6] ); 392112373Sphk if (resinfo[0]) 393112373Sphk printf("\t[16-bit addr]\n"); 394112373Sphk else 395112373Sphk printf("\t[not 16-bit addr]\n"); 396112373Sphk break; 397112373Sphk case PNP_TAG_IO_FIXED: 398112373Sphk printf (" FIXED I/O base address 0x%x length 0x%x\n", 399112373Sphk resinfo[0] + ( (resinfo[1] & 3 ) << 8), /* XXX */ 40081133Stmm resinfo[2]); 40181133Stmm break; 40281133Stmm#ifdef DIAGNOSTIC 40381133Stmm case PNP_TAG_RESERVED: 40481133Stmm printf("Reserved Tag Detected\n"); 40581133Stmm break; 40681133Stmm#endif 40781133Stmm case PNP_TAG_VENDOR: 408112288Sphk printf("*** Small Vendor Tag Detected\n"); 40981133Stmm break; 410112293Sphk case PNP_TAG_END: 41181133Stmm printf("End Tag\n\n"); 41281133Stmm /* XXX Record and Verify Checksum */ 41381133Stmm return 1; 41481133Stmm break; 41581133Stmm } 41681133Stmm return 0; 41781133Stmm} 41881133Stmm 41981133Stmm 42082028Skenvoid 42182028Skenhandle_large_res(u_char *resinfo, int item, int len) 422145553Smux{ 423145553Smux int i; 42481133Stmm 42581133Stmm DEB(printf("*** Large ITEM %d len %d found\n", item, len)); 42681133Stmm switch (item) { 42781133Stmm case PNP_TAG_MEMORY_RANGE: 42882028Sken report_memory_info(resinfo[0]); 429145553Smux printf("Memory range minimum address: 0x%x\n", 43082028Sken (resinfo[1] << 8) + (resinfo[2] << 16)); 43139211Sgibbs printf("Memory range maximum address: 0x%x\n", 43239211Sgibbs (resinfo[3] << 8) + (resinfo[4] << 16)); 43381133Stmm printf("Memory range base alignment: 0x%x\n", 43481133Stmm (i = (resinfo[5] + (resinfo[6] << 8))) ? i : (1 << 16)); 43581133Stmm printf("Memory range length: 0x%x\n", 43681133Stmm (resinfo[7] + (resinfo[8] << 8)) * 256); 43781133Stmm break; 43881133Stmm case PNP_TAG_ID_ANSI: 43981133Stmm printf("Device Description: "); 440112293Sphk 44139211Sgibbs for (i = 0; i < len; i++) { 442145549Smux if (resinfo[i]) /* XXX */ 44381133Stmm printf("%c", resinfo[i]); 44481133Stmm } 44539211Sgibbs printf("\n"); 44639211Sgibbs break; 44739211Sgibbs case PNP_TAG_ID_UNICODE: 44839211Sgibbs printf("ID String Unicode Detected (Undefined)\n"); 44939498Sken break; 45039211Sgibbs case PNP_TAG_LARGE_VENDOR: 45139211Sgibbs printf("Large Vendor Defined Detected\n"); 45239211Sgibbs break; 45339211Sgibbs case PNP_TAG_MEMORY32_RANGE: 45439211Sgibbs printf("32bit Memory Range Desc Unimplemented\n"); 45539211Sgibbs break; 45639211Sgibbs case PNP_TAG_MEMORY32_FIXED: 45739211Sgibbs printf("32bit Fixed Location Desc Unimplemented\n"); 45839211Sgibbs break; 45939211Sgibbs#ifdef DIAGNOSTIC 46039211Sgibbs case PNP_TAG_LARGE_RESERVED: 46139211Sgibbs printf("Large Reserved Tag Detected\n"); 46239211Sgibbs break; 46339211Sgibbs#endif 46439211Sgibbs } 46539211Sgibbs} 46639211Sgibbs 467112293Sphk 468112293Sphk/* 46939211Sgibbs * Dump all the information about configurations. 47039211Sgibbs */ 47139498Skenvoid 47239211Sgibbsdump_resdata(u_char *data, int csn) 47339211Sgibbs{ 47439211Sgibbs int i, large_len; 47539211Sgibbs 47639211Sgibbs u_char tag, *resinfo; 47739211Sgibbs 47839498Sken DDB(printf("\nCard assigned CSN #%d\n", csn)); 47939211Sgibbs printf("Vendor ID %c%c%c%02x%02x (0x%08x), Serial Number 0x%08x\n", 48039211Sgibbs ((data[0] & 0x7c) >> 2) + 64, 48139211Sgibbs (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64, 48239211Sgibbs (data[1] & 0x1f) + 64, data[2], data[3], 48339211Sgibbs *(int *)&(data[0]), 48439211Sgibbs *(int *)&(data[4])); 48539211Sgibbs 48639211Sgibbs pnp_write(PNP_SET_CSN, csn); /* Move this out of this function XXX */ 48739211Sgibbs outb(_PNP_ADDRESS, PNP_STATUS); 48839211Sgibbs 48939211Sgibbs /* Allows up to 1kb of Resource Info, Should be plenty */ 49039211Sgibbs for (i = 0; i < 1024; i++) { 49139211Sgibbs if (!get_resource_info(&tag, 1)) 49239211Sgibbs break; 49339211Sgibbs 49439211Sgibbs if (PNP_RES_TYPE(tag) == 0) { 49539211Sgibbs /* Handle small resouce data types */ 49639211Sgibbs 49739211Sgibbs resinfo = malloc(PNP_SRES_LEN(tag)); 49839211Sgibbs if (!get_resource_info(resinfo, PNP_SRES_LEN(tag))) 49939211Sgibbs break; 50039211Sgibbs 50139211Sgibbs if (handle_small_res(resinfo, PNP_SRES_NUM(tag), PNP_SRES_LEN(tag)) == 1) 50239211Sgibbs break; 50339211Sgibbs free(resinfo); 50439211Sgibbs } else { 50539211Sgibbs /* Handle large resouce data types */ 50639211Sgibbs u_char buf[2]; 50739211Sgibbs if (!get_resource_info((char *)buf, 2)) 50839211Sgibbs break; 50939211Sgibbs large_len = (buf[1] << 8) + buf[0]; 51039211Sgibbs 51139211Sgibbs resinfo = malloc(large_len); 51239211Sgibbs if (!get_resource_info(resinfo, large_len)) 51339211Sgibbs break; 51439211Sgibbs 51539211Sgibbs handle_large_res(resinfo, PNP_LRES_NUM(tag), large_len); 51639211Sgibbs free(resinfo); 51739211Sgibbs } 51839211Sgibbs } 51939211Sgibbs printf("Successfully got %d resources, %d logical fdevs\n", i, 52039211Sgibbs logdevs); 52139211Sgibbs printf("-- card select # 0x%04x\n", pnp_read(PNP_SET_CSN)); 52239211Sgibbs printf("\nCSN %c%c%c%02x%02x (0x%08x), Serial Number 0x%08x\n", 52339211Sgibbs ((data[0] & 0x7c) >> 2) + 64, 52439211Sgibbs (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64, 52539211Sgibbs (data[1] & 0x1f) + 64, data[2], data[3], 52639211Sgibbs *(int *)&(data[0]), 52739211Sgibbs *(int *)&(data[4])); 52839211Sgibbs 52939211Sgibbs for (i=0; i<logdevs; i++) { 53039211Sgibbs int j; 53139211Sgibbs 53239211Sgibbs pnp_write(PNP_SET_LDN, i); 53339211Sgibbs 53439211Sgibbs printf("\nLogical device #%d\n", pnp_read(PNP_SET_LDN) ); 53539211Sgibbs printf("IO: "); 53639211Sgibbs for (j=0; j<8; j++) 53739211Sgibbs printf(" 0x%02x%02x", pnp_read(PNP_IO_BASE_HIGH(j)), 53839211Sgibbs pnp_read(PNP_IO_BASE_LOW(j))); 53939211Sgibbs printf("\nIRQ %d %d\n", 54039211Sgibbs pnp_read(PNP_IRQ_LEVEL(0)), pnp_read(PNP_IRQ_LEVEL(1)) ); 54139211Sgibbs printf("DMA %d %d\n", 54239211Sgibbs pnp_read(PNP_DMA_CHANNEL(0)), pnp_read(PNP_DMA_CHANNEL(1)) ); 54339211Sgibbs printf("IO range check 0x%02x activate 0x%02x\n", 54439211Sgibbs pnp_read(PNP_IO_RANGE_CHECK), pnp_read(PNP_ACTIVATE) ); 54581133Stmm } 54681133Stmm} 54781133Stmm 54881133Stmm 54981133Stmm/* 55081133Stmm * Run the isolation protocol. Use rd_port as the READ_DATA port 55181133Stmm * value (caller should try multiple READ_DATA locations before giving 55239211Sgibbs * up). Upon exiting, all cards are aware that they should use rd_port 55392913Sobrien * as the READ_DATA port; 55439211Sgibbs * 55539211Sgibbs */ 55639211Sgibbsint 55739211Sgibbsisolation_protocol() 55839211Sgibbs{ 55939211Sgibbs int csn; 560119029Sphk u_char data[9]; 56139211Sgibbs 56239211Sgibbs send_Initiation_LFSR(); 56339211Sgibbs 56439211Sgibbs /* Reset CSN for All Cards */ 56539211Sgibbs pnp_write(PNP_CONFIG_CONTROL, 0x04); 56639211Sgibbs 56739211Sgibbs for (csn = 1; (csn < PNP_MAX_CARDS); csn++) { 56839211Sgibbs /* Wake up cards without a CSN */ 56939211Sgibbs logdevs = 0 ; 57039211Sgibbs pnp_write(PNP_WAKE, 0); 57139211Sgibbs pnp_write(PNP_SET_RD_DATA, rd_port); 57239211Sgibbs outb(_PNP_ADDRESS, PNP_SERIAL_ISOLATION); 57339211Sgibbs DELAY(1000); /* Delay 1 msec */ 57439211Sgibbs 57539211Sgibbs if (get_serial(data)) 57639211Sgibbs dump_resdata(data, csn); 57739211Sgibbs else 57839211Sgibbs break; 57939211Sgibbs } 58039211Sgibbs return csn - 1; 58139211Sgibbs} 582229735Sghelmer 58339211Sgibbs 58439211Sgibbsint 58539211Sgibbsmain(int argc, char **argv) 58639211Sgibbs{ 58739211Sgibbs int num_pnp_devs; 58839211Sgibbs 58939211Sgibbs#ifdef __i386__ 59039211Sgibbs /* Hey what about a i386_iopl() call :) */ 59139211Sgibbs if (open("/dev/io", O_RDONLY) < 0) { 59239211Sgibbs fprintf (stderr, "pnpinfo: Can't get I/O privilege.\n"); 59339211Sgibbs exit (1); 59439211Sgibbs } 59539211Sgibbs#endif 596229735Sghelmer#ifdef __alpha__ 597229735Sghelmer ioperm(0x203, 0x400 - 0x203, 1); 598229735Sghelmer#endif 599229735Sghelmer 600229735Sghelmer printf("Checking for Plug-n-Play devices...\n"); 601229735Sghelmer 602229735Sghelmer /* Try various READ_DATA ports from 0x203-0x3ff */ 60339211Sgibbs for (rd_port = 0x80; (rd_port < 0xff); rd_port += 0x10) { 60439211Sgibbs DEB(printf("Trying Read_Port at %x...\n", (rd_port << 2) | 0x3) ); 60539211Sgibbs num_pnp_devs = isolation_protocol(rd_port); 60639211Sgibbs if (num_pnp_devs) 60739211Sgibbs break; 60839211Sgibbs } 60939211Sgibbs if (!num_pnp_devs) { 61039211Sgibbs printf("No Plug-n-Play devices were found\n"); 61139211Sgibbs return 0; 61239211Sgibbs } 61339211Sgibbs} 61439211Sgibbs