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 */ 2629615Sjmg 27124125Scharnier#include <sys/cdefs.h> 28124125Scharnier__FBSDID("$FreeBSD$"); 29124125Scharnier 3029615Sjmg#include <sys/time.h> 3129615Sjmg 32124125Scharnier#include <err.h> 3329615Sjmg#include <stdio.h> 3429615Sjmg#include <stdlib.h> 3529615Sjmg#include <unistd.h> 3629615Sjmg#include <fcntl.h> 3729615Sjmg#include <string.h> 3829615Sjmg 3929615Sjmg#include <machine/cpufunc.h> 4029615Sjmg 4150786Speter#include <isa/pnpreg.h> 4229615Sjmg 4329615Sjmg#ifdef DEBUG 4429615Sjmg#define DEB(x) x 4529615Sjmg#else 4629615Sjmg#define DEB(x) 4729615Sjmg#endif 4829615Sjmg#define DDB(x) x 4929615Sjmg 5029615Sjmgvoid 5129615Sjmgpnp_write(int d, u_char r) 5229615Sjmg{ 5329615Sjmg outb (_PNP_ADDRESS, d); 5429615Sjmg outb (_PNP_WRITE_DATA, r); 5529615Sjmg} 5639144Seivind 5729615Sjmg/* The READ_DATA port that we are using currently */ 5829615Sjmgstatic int rd_port; 5929615Sjmg 6029615Sjmgu_char 6129615Sjmgpnp_read(int d) 6229615Sjmg{ 6329615Sjmg outb(_PNP_ADDRESS, d); 6429615Sjmg return inb( (rd_port << 2) + 3) & 0xff; 6529615Sjmg} 6629615Sjmg 6731135Sjmgu_short 6829615Sjmgpnp_readw(int d) 6929615Sjmg{ 7029615Sjmg int c = pnp_read(d) << 8 ; 7129615Sjmg c |= pnp_read(d+1); 7229615Sjmg return c; 7329615Sjmg} 7429615Sjmg 7529615Sjmgint logdevs=0; 7629615Sjmg 7729615Sjmgvoid DELAY __P((int i)); 7829615Sjmgvoid send_Initiation_LFSR(); 7929615Sjmgint get_serial __P((u_char *data)); 8029615Sjmgint get_resource_info __P((u_char *buffer, int len)); 8129615Sjmgint handle_small_res __P((u_char *resinfo, int item, int len)); 8229615Sjmgvoid handle_large_res __P((u_char *resinfo, int item, int len)); 8329615Sjmgvoid dump_resdata __P((u_char *data, int csn)); 8429615Sjmgint isolation_protocol(); 8529615Sjmg 8629615Sjmg 8729615Sjmg/* 8829615Sjmg * DELAY does accurate delaying in user-space. 8929615Sjmg * This function busy-waits. 9029615Sjmg */ 9129615Sjmgvoid 9229615SjmgDELAY (int i) 9329615Sjmg{ 9429615Sjmg struct timeval t; 9529615Sjmg long start, stop; 9629615Sjmg 9729615Sjmg i *= 4; 9829615Sjmg 9929615Sjmg gettimeofday (&t, NULL); 10029615Sjmg start = t.tv_sec * 1000000 + t.tv_usec; 10129615Sjmg do { 10229615Sjmg gettimeofday (&t, NULL); 10329615Sjmg stop = t.tv_sec * 1000000 + t.tv_usec; 10429615Sjmg } while (start + i > stop); 10529615Sjmg} 10629615Sjmg 10729615Sjmg 10829615Sjmg/* 10929615Sjmg * Send Initiation LFSR as described in "Plug and Play ISA Specification, 11029615Sjmg * Intel May 94." 11129615Sjmg */ 11229615Sjmgvoid 11329615Sjmgsend_Initiation_LFSR() 11429615Sjmg{ 11529615Sjmg int cur, i; 11629615Sjmg 11750786Speter pnp_write(PNP_CONFIG_CONTROL, 0x2); 11829615Sjmg 11929615Sjmg /* Reset the LSFR */ 12029615Sjmg outb(_PNP_ADDRESS, 0); 12129615Sjmg outb(_PNP_ADDRESS, 0); /* yes, we do need it twice! */ 12229615Sjmg 12329615Sjmg cur = 0x6a; 12429615Sjmg 12529615Sjmg for (i = 0; i < 32; i++) { 12629615Sjmg outb(_PNP_ADDRESS, cur); 12729615Sjmg cur = (cur >> 1) | (((cur ^ (cur >> 1)) << 7) & 0xff); 12829615Sjmg } 12929615Sjmg} 13029615Sjmg 13129615Sjmg/* 13229615Sjmg * Get the device's serial number. Returns 1 if the serial is valid. 13329615Sjmg */ 13429615Sjmgint 13529615Sjmgget_serial(u_char *data) 13629615Sjmg{ 13729615Sjmg int i, bit, valid = 0, sum = 0x6a; 13829615Sjmg 13929615Sjmg bzero(data, sizeof(char) * 9); 14029615Sjmg 14129615Sjmg for (i = 0; i < 72; i++) { 14229615Sjmg bit = inb((rd_port << 2) | 0x3) == 0x55; 14329615Sjmg DELAY(250); /* Delay 250 usec */ 14429615Sjmg 14529615Sjmg /* Can't Short Circuit the next evaluation, so 'and' is last */ 14629615Sjmg bit = (inb((rd_port << 2) | 0x3) == 0xaa) && bit; 14729615Sjmg DELAY(250); /* Delay 250 usec */ 14829615Sjmg 14929615Sjmg valid = valid || bit; 15029615Sjmg 15129615Sjmg if (i < 64) 15229615Sjmg sum = (sum >> 1) | 15329615Sjmg (((sum ^ (sum >> 1) ^ bit) << 7) & 0xff); 15429615Sjmg 15529615Sjmg data[i / 8] = (data[i / 8] >> 1) | (bit ? 0x80 : 0); 15629615Sjmg } 15729615Sjmg 15829615Sjmg valid = valid && (data[8] == sum); 15929615Sjmg 16029615Sjmg return valid; 16129615Sjmg} 16229615Sjmg 16329615Sjmg 16429615Sjmg/* 16529615Sjmg * Fill's the buffer with resource info from the device. 16629615Sjmg * Returns 0 if the device fails to report 16729615Sjmg */ 16829615Sjmgint 16929615Sjmgget_resource_info(u_char *buffer, int len) 17029615Sjmg{ 17129615Sjmg int i, j; 17229615Sjmg 17329615Sjmg for (i = 0; i < len; i++) { 17450786Speter outb(_PNP_ADDRESS, PNP_STATUS); 17529615Sjmg for (j = 0; j < 100; j++) { 17629615Sjmg if ((inb((rd_port << 2) | 0x3)) & 0x1) 17729615Sjmg break; 17829615Sjmg DELAY(1); 17929615Sjmg } 18029615Sjmg if (j == 100) { 18129615Sjmg printf("PnP device failed to report resource data\n"); 18229615Sjmg return 0; 18329615Sjmg } 18450786Speter outb(_PNP_ADDRESS, PNP_RESOURCE_DATA); 18529615Sjmg buffer[i] = inb((rd_port << 2) | 0x3); 18629615Sjmg DEB(printf("--- get_resource_info: got 0x%02x\n",(unsigned)buffer[i])); 18729615Sjmg } 18829615Sjmg return 1; 18929615Sjmg} 19029615Sjmg 19129615Sjmgvoid 19229615Sjmgreport_dma_info (x) 19329615Sjmg int x; 19429615Sjmg{ 19529615Sjmg char *s1=NULL, *s2=NULL, *s3=NULL, *s4=NULL, *s5=NULL; 19629615Sjmg 19729615Sjmg switch (x & 0x3) { 19829615Sjmg case 0: 19929615Sjmg s1="8-bit"; 20029615Sjmg break; 20129615Sjmg case 1: 20229615Sjmg s1="8/16-bit"; 20329615Sjmg break; 20429615Sjmg case 2: 20529615Sjmg s1="16-bit"; 20629615Sjmg break; 20729615Sjmg#ifdef DIAGNOSTIC 20829615Sjmg case 3: 20929615Sjmg s1="Reserved"; 21029615Sjmg break; 21129615Sjmg#endif 21229615Sjmg } 21329615Sjmg 21429615Sjmg s2 = (x & 0x4) ? "bus master" : "not a bus master"; 21529615Sjmg 21629615Sjmg s3 = (x & 0x8) ? "count by byte" : ""; 21729615Sjmg 21829615Sjmg s4 = (x & 0x10) ? "count by word" : ""; 21929615Sjmg 22029615Sjmg switch ((x & 0x60) >> 5) { 22129615Sjmg case 0: 22229615Sjmg s5="Compatibility mode"; 22329615Sjmg break; 22429615Sjmg case 1: 22529615Sjmg s5="Type A"; 22629615Sjmg break; 22729615Sjmg case 2: 22829615Sjmg s5="Type B"; 22929615Sjmg break; 23029615Sjmg case 3: 23129615Sjmg s5="Type F"; 23229615Sjmg break; 23329615Sjmg } 23429615Sjmg printf("\t%s, %s, %s, %s, %s\n",s1,s2,s3,s4,s5); 23529615Sjmg} 23629615Sjmg 23729615Sjmg 23829615Sjmgvoid 23929615Sjmgreport_memory_info (int x) 24029615Sjmg{ 24129615Sjmg if (x & 0x1) 24229615Sjmg printf ("Memory Range: Writeable\n"); 24329615Sjmg else 24429615Sjmg printf ("Memory Range: Not writeable (ROM)\n"); 24529615Sjmg 24629615Sjmg if (x & 0x2) 24729615Sjmg printf ("Memory Range: Read-cacheable, write-through\n"); 24829615Sjmg else 24929615Sjmg printf ("Memory Range: Non-cacheable\n"); 25029615Sjmg 25129615Sjmg if (x & 0x4) 25229615Sjmg printf ("Memory Range: Decode supports high address\n"); 25329615Sjmg else 25429615Sjmg printf ("Memory Range: Decode supports range length\n"); 25529615Sjmg 25629615Sjmg switch ((x & 0x18) >> 3) { 25729615Sjmg case 0: 25829615Sjmg printf ("Memory Range: 8-bit memory only\n"); 25929615Sjmg break; 26029615Sjmg case 1: 26129615Sjmg printf ("Memory Range: 16-bit memory only\n"); 26229615Sjmg break; 26329615Sjmg case 2: 26429615Sjmg printf ("Memory Range: 8-bit and 16-bit memory supported\n"); 26529615Sjmg break; 26629615Sjmg#ifdef DIAGNOSTIC 26729615Sjmg case 3: 26829615Sjmg printf ("Memory Range: Reserved\n"); 26929615Sjmg break; 27029615Sjmg#endif 27129615Sjmg } 27229615Sjmg 27329615Sjmg if (x & 0x20) 27429615Sjmg printf ("Memory Range: Memory is shadowable\n"); 27529615Sjmg else 27629615Sjmg printf ("Memory Range: Memory is not shadowable\n"); 27729615Sjmg 27829615Sjmg if (x & 0x40) 27929615Sjmg printf ("Memory Range: Memory is an expansion ROM\n"); 28029615Sjmg else 28129615Sjmg printf ("Memory Range: Memory is not an expansion ROM\n"); 28229615Sjmg 28329615Sjmg#ifdef DIAGNOSTIC 28429615Sjmg if (x & 0x80) 28529615Sjmg printf ("Memory Range: Reserved (Device is brain-damaged)\n"); 28629615Sjmg#endif 28729615Sjmg} 28829615Sjmg 28929615Sjmg 29029615Sjmg/* 29129615Sjmg * Small Resource Tag Handler 29229615Sjmg * 29329615Sjmg * Returns 1 if checksum was valid (and an END_TAG was received). 29429615Sjmg * Returns -1 if checksum was invalid (and an END_TAG was received). 29529615Sjmg * Returns 0 for other tags. 29629615Sjmg */ 29729615Sjmgint 29829615Sjmghandle_small_res(u_char *resinfo, int item, int len) 29929615Sjmg{ 30029615Sjmg int i; 30129615Sjmg 30229615Sjmg DEB(printf("*** ITEM 0x%04x len %d detected\n", item, len)); 30329615Sjmg 30429615Sjmg switch (item) { 30529615Sjmg default: 30629615Sjmg printf("*** ITEM 0x%02x detected\n", item); 30729615Sjmg break; 30850786Speter case PNP_TAG_VERSION: 30929615Sjmg printf("PnP Version %d.%d, Vendor Version %d\n", 31029615Sjmg resinfo[0] >> 4, resinfo[0] & (0xf), resinfo[1]); 31129615Sjmg break; 31250786Speter case PNP_TAG_LOGICAL_DEVICE: 31329615Sjmg printf("\nLogical Device ID: %c%c%c%02x%02x 0x%08x #%d\n", 31429615Sjmg ((resinfo[0] & 0x7c) >> 2) + 64, 31529615Sjmg (((resinfo[0] & 0x03) << 3) | 31629615Sjmg ((resinfo[1] & 0xe0) >> 5)) + 64, 31729615Sjmg (resinfo[1] & 0x1f) + 64, 31829615Sjmg resinfo[2], resinfo[3], *(int *)(resinfo), 31929615Sjmg logdevs++); 32029615Sjmg 32129615Sjmg if (resinfo[4] & 0x1) 32229615Sjmg printf ("\tDevice powers up active\n"); /* XXX */ 32329615Sjmg if (resinfo[4] & 0x2) 32429615Sjmg printf ("\tDevice supports I/O Range Check\n"); 32529615Sjmg if (resinfo[4] > 0x3) 32629615Sjmg printf ("\tReserved register funcs %02x\n", 32729615Sjmg resinfo[4]); 32829615Sjmg 32929615Sjmg if (len == 6) 33029615Sjmg printf("\tVendor register funcs %02x\n", resinfo[5]); 33129615Sjmg break; 33250786Speter case PNP_TAG_COMPAT_DEVICE: 33329615Sjmg printf("Compatible Device ID: %c%c%c%02x%02x (%08x)\n", 33429615Sjmg ((resinfo[0] & 0x7c) >> 2) + 64, 33529615Sjmg (((resinfo[0] & 0x03) << 3) | 33629615Sjmg ((resinfo[1] & 0xe0) >> 5)) + 64, 33729615Sjmg (resinfo[1] & 0x1f) + 64, 33829615Sjmg resinfo[2], resinfo[3], *(int *)resinfo); 33929615Sjmg break; 34050786Speter case PNP_TAG_IRQ_FORMAT: 34129615Sjmg printf(" IRQ: "); 34229615Sjmg 34329615Sjmg for (i = 0; i < 8; i++) 34429615Sjmg if (resinfo[0] & (1<<i)) 34529615Sjmg printf("%d ", i); 34629615Sjmg for (i = 0; i < 8; i++) 34729615Sjmg if (resinfo[1] & (1<<i)) 34829615Sjmg printf("%d ", i + 8); 34929615Sjmg if (len == 3) { 35029615Sjmg if (resinfo[2] & 0x1) 35129615Sjmg printf("IRQ: High true edge sensitive\n"); 35229615Sjmg if (resinfo[2] & 0x2) 35329615Sjmg printf("IRQ: Low true edge sensitive\n"); 35429615Sjmg if (resinfo[2] & 0x4) 35529615Sjmg printf("IRQ: High true level sensitive\n"); 35629615Sjmg if (resinfo[2] & 0x8) 35729615Sjmg printf("IRQ: Low true level sensitive\n"); 35829615Sjmg } else { 35929615Sjmg printf(" - only one type (true/edge)\n"); 36029615Sjmg } 36129615Sjmg break; 36250786Speter case PNP_TAG_DMA_FORMAT: 36329615Sjmg printf(" DMA: channel(s) "); 36429615Sjmg for (i = 0; i < 8; i++) 36529615Sjmg if (resinfo[0] & (1<<i)) 36629615Sjmg printf("%d ", i); 36729615Sjmg printf ("\n"); 36829615Sjmg report_dma_info (resinfo[1]); 36929615Sjmg break; 37050786Speter case PNP_TAG_START_DEPENDANT: 37129615Sjmg printf("TAG Start DF\n"); 37229615Sjmg if (len == 1) { 37329615Sjmg switch (resinfo[0]) { 37429615Sjmg case 0: 37529615Sjmg printf("Good Configuration\n"); 37629615Sjmg break; 37729615Sjmg case 1: 37829615Sjmg printf("Acceptable Configuration\n"); 37929615Sjmg break; 38029615Sjmg case 2: 38129615Sjmg printf("Sub-optimal Configuration\n"); 38229615Sjmg break; 38329615Sjmg } 38429615Sjmg } 38529615Sjmg break; 38650786Speter case PNP_TAG_END_DEPENDANT: 38729615Sjmg printf("TAG End DF\n"); 38829615Sjmg break; 38950786Speter case PNP_TAG_IO_RANGE: 39029615Sjmg printf(" I/O Range 0x%x .. 0x%x, alignment 0x%x, len 0x%x\n", 39129615Sjmg resinfo[1] + (resinfo[2] << 8), 39229615Sjmg resinfo[3] + (resinfo[4] << 8), 39329615Sjmg resinfo[5], resinfo[6] ); 39429615Sjmg if (resinfo[0]) 39529615Sjmg printf("\t[16-bit addr]\n"); 39629615Sjmg else 39729615Sjmg printf("\t[not 16-bit addr]\n"); 39829615Sjmg break; 39950786Speter case PNP_TAG_IO_FIXED: 40029615Sjmg printf (" FIXED I/O base address 0x%x length 0x%x\n", 40129615Sjmg resinfo[0] + ( (resinfo[1] & 3 ) << 8), /* XXX */ 40229615Sjmg resinfo[2]); 40329615Sjmg break; 40429615Sjmg#ifdef DIAGNOSTIC 40550786Speter case PNP_TAG_RESERVED: 40629615Sjmg printf("Reserved Tag Detected\n"); 40729615Sjmg break; 40829615Sjmg#endif 40950786Speter case PNP_TAG_VENDOR: 41029615Sjmg printf("*** Small Vendor Tag Detected\n"); 41129615Sjmg break; 41250786Speter case PNP_TAG_END: 41329615Sjmg printf("End Tag\n\n"); 41429615Sjmg /* XXX Record and Verify Checksum */ 41529615Sjmg return 1; 41629615Sjmg break; 41729615Sjmg } 41829615Sjmg return 0; 41929615Sjmg} 42029615Sjmg 42129615Sjmg 42229615Sjmgvoid 42329615Sjmghandle_large_res(u_char *resinfo, int item, int len) 42429615Sjmg{ 42529615Sjmg int i; 42629615Sjmg 42729615Sjmg DEB(printf("*** Large ITEM %d len %d found\n", item, len)); 42829615Sjmg switch (item) { 42950786Speter case PNP_TAG_MEMORY_RANGE: 43029615Sjmg report_memory_info(resinfo[0]); 43129615Sjmg printf("Memory range minimum address: 0x%x\n", 43229615Sjmg (resinfo[1] << 8) + (resinfo[2] << 16)); 43329615Sjmg printf("Memory range maximum address: 0x%x\n", 43429615Sjmg (resinfo[3] << 8) + (resinfo[4] << 16)); 43529615Sjmg printf("Memory range base alignment: 0x%x\n", 43629615Sjmg (i = (resinfo[5] + (resinfo[6] << 8))) ? i : (1 << 16)); 43729615Sjmg printf("Memory range length: 0x%x\n", 43829615Sjmg (resinfo[7] + (resinfo[8] << 8)) * 256); 43929615Sjmg break; 44050786Speter case PNP_TAG_ID_ANSI: 44129615Sjmg printf("Device Description: "); 44229615Sjmg 44329615Sjmg for (i = 0; i < len; i++) { 44429615Sjmg if (resinfo[i]) /* XXX */ 44529615Sjmg printf("%c", resinfo[i]); 44629615Sjmg } 44729615Sjmg printf("\n"); 44829615Sjmg break; 44950786Speter case PNP_TAG_ID_UNICODE: 45029615Sjmg printf("ID String Unicode Detected (Undefined)\n"); 45129615Sjmg break; 45250786Speter case PNP_TAG_LARGE_VENDOR: 45329615Sjmg printf("Large Vendor Defined Detected\n"); 45429615Sjmg break; 45550786Speter case PNP_TAG_MEMORY32_RANGE: 45629615Sjmg printf("32bit Memory Range Desc Unimplemented\n"); 45729615Sjmg break; 45850786Speter case PNP_TAG_MEMORY32_FIXED: 45929615Sjmg printf("32bit Fixed Location Desc Unimplemented\n"); 46029615Sjmg break; 46150786Speter#ifdef DIAGNOSTIC 46250786Speter case PNP_TAG_LARGE_RESERVED: 46329615Sjmg printf("Large Reserved Tag Detected\n"); 46429615Sjmg break; 46550786Speter#endif 46629615Sjmg } 46729615Sjmg} 46829615Sjmg 46929615Sjmg 47029615Sjmg/* 47129615Sjmg * Dump all the information about configurations. 47229615Sjmg */ 47329615Sjmgvoid 47429615Sjmgdump_resdata(u_char *data, int csn) 47529615Sjmg{ 47629615Sjmg int i, large_len; 47729615Sjmg 47829615Sjmg u_char tag, *resinfo; 47929615Sjmg 48029615Sjmg DDB(printf("\nCard assigned CSN #%d\n", csn)); 48129615Sjmg printf("Vendor ID %c%c%c%02x%02x (0x%08x), Serial Number 0x%08x\n", 48229615Sjmg ((data[0] & 0x7c) >> 2) + 64, 48329615Sjmg (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64, 48429615Sjmg (data[1] & 0x1f) + 64, data[2], data[3], 48529615Sjmg *(int *)&(data[0]), 48629615Sjmg *(int *)&(data[4])); 48729615Sjmg 48850786Speter pnp_write(PNP_SET_CSN, csn); /* Move this out of this function XXX */ 48950786Speter outb(_PNP_ADDRESS, PNP_STATUS); 49029615Sjmg 49129615Sjmg /* Allows up to 1kb of Resource Info, Should be plenty */ 49229615Sjmg for (i = 0; i < 1024; i++) { 49329615Sjmg if (!get_resource_info(&tag, 1)) 49429615Sjmg break; 49529615Sjmg 49639144Seivind if (PNP_RES_TYPE(tag) == 0) { 49729615Sjmg /* Handle small resouce data types */ 49829615Sjmg 49939144Seivind resinfo = malloc(PNP_SRES_LEN(tag)); 50039144Seivind if (!get_resource_info(resinfo, PNP_SRES_LEN(tag))) 50129615Sjmg break; 50229615Sjmg 50339144Seivind if (handle_small_res(resinfo, PNP_SRES_NUM(tag), PNP_SRES_LEN(tag)) == 1) 50429615Sjmg break; 50529615Sjmg free(resinfo); 50629615Sjmg } else { 50729615Sjmg /* Handle large resouce data types */ 50846422Sluoqi u_char buf[2]; 50946422Sluoqi if (!get_resource_info((char *)buf, 2)) 51029615Sjmg break; 51146422Sluoqi large_len = (buf[1] << 8) + buf[0]; 51229615Sjmg 51329615Sjmg resinfo = malloc(large_len); 51429615Sjmg if (!get_resource_info(resinfo, large_len)) 51529615Sjmg break; 51629615Sjmg 51739144Seivind handle_large_res(resinfo, PNP_LRES_NUM(tag), large_len); 51829615Sjmg free(resinfo); 51929615Sjmg } 52029615Sjmg } 52129615Sjmg printf("Successfully got %d resources, %d logical fdevs\n", i, 52229615Sjmg logdevs); 52350786Speter printf("-- card select # 0x%04x\n", pnp_read(PNP_SET_CSN)); 52429615Sjmg printf("\nCSN %c%c%c%02x%02x (0x%08x), Serial Number 0x%08x\n", 52529615Sjmg ((data[0] & 0x7c) >> 2) + 64, 52629615Sjmg (((data[0] & 0x03) << 3) | ((data[1] & 0xe0) >> 5)) + 64, 52729615Sjmg (data[1] & 0x1f) + 64, data[2], data[3], 52829615Sjmg *(int *)&(data[0]), 52929615Sjmg *(int *)&(data[4])); 53029615Sjmg 53129615Sjmg for (i=0; i<logdevs; i++) { 53229615Sjmg int j; 53329615Sjmg 53450786Speter pnp_write(PNP_SET_LDN, i); 53529615Sjmg 53650786Speter printf("\nLogical device #%d\n", pnp_read(PNP_SET_LDN) ); 53729615Sjmg printf("IO: "); 53829615Sjmg for (j=0; j<8; j++) 539101611Siedowse printf(" 0x%02x%02x", pnp_read(PNP_IO_BASE_HIGH(j)), 540101611Siedowse pnp_read(PNP_IO_BASE_LOW(j))); 54129615Sjmg printf("\nIRQ %d %d\n", 54250786Speter pnp_read(PNP_IRQ_LEVEL(0)), pnp_read(PNP_IRQ_LEVEL(1)) ); 54329615Sjmg printf("DMA %d %d\n", 54450786Speter pnp_read(PNP_DMA_CHANNEL(0)), pnp_read(PNP_DMA_CHANNEL(1)) ); 54529615Sjmg printf("IO range check 0x%02x activate 0x%02x\n", 54650786Speter pnp_read(PNP_IO_RANGE_CHECK), pnp_read(PNP_ACTIVATE) ); 54729615Sjmg } 54829615Sjmg} 54929615Sjmg 55029615Sjmg 55129615Sjmg/* 55229615Sjmg * Run the isolation protocol. Use rd_port as the READ_DATA port 55329615Sjmg * value (caller should try multiple READ_DATA locations before giving 55429615Sjmg * up). Upon exiting, all cards are aware that they should use rd_port 55529615Sjmg * as the READ_DATA port; 55629615Sjmg * 55729615Sjmg */ 55829615Sjmgint 55929615Sjmgisolation_protocol() 56029615Sjmg{ 56129615Sjmg int csn; 56229615Sjmg u_char data[9]; 56329615Sjmg 56429615Sjmg send_Initiation_LFSR(); 56529615Sjmg 56629615Sjmg /* Reset CSN for All Cards */ 56750786Speter pnp_write(PNP_CONFIG_CONTROL, 0x04); 56829615Sjmg 56950786Speter for (csn = 1; (csn < PNP_MAX_CARDS); csn++) { 57029615Sjmg /* Wake up cards without a CSN */ 57129615Sjmg logdevs = 0 ; 57250786Speter pnp_write(PNP_WAKE, 0); 57350786Speter pnp_write(PNP_SET_RD_DATA, rd_port); 57450786Speter outb(_PNP_ADDRESS, PNP_SERIAL_ISOLATION); 57529615Sjmg DELAY(1000); /* Delay 1 msec */ 57629615Sjmg 57729615Sjmg if (get_serial(data)) 57829615Sjmg dump_resdata(data, csn); 57929615Sjmg else 58029615Sjmg break; 58129615Sjmg } 58229615Sjmg return csn - 1; 58329615Sjmg} 58429615Sjmg 58529615Sjmg 58647405Sdfrint 58747405Sdfrmain(int argc, char **argv) 58829615Sjmg{ 58929615Sjmg int num_pnp_devs; 59029615Sjmg 59147405Sdfr#ifdef __i386__ 59229615Sjmg /* Hey what about a i386_iopl() call :) */ 593124125Scharnier if (open("/dev/io", O_RDONLY) < 0) 594124125Scharnier errx(1, "can't get I/O privilege"); 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) ); 602228672Sdim num_pnp_devs = isolation_protocol(); 60329615Sjmg if (num_pnp_devs) 60429615Sjmg break; 60529615Sjmg } 60629615Sjmg if (!num_pnp_devs) { 60729615Sjmg printf("No Plug-n-Play devices were found\n"); 608124125Scharnier return (0); 60929615Sjmg } 610124125Scharnier return (0); 61129615Sjmg} 612