pci.c (4037B)
1 /* $Id$ 2 ** 3 ** Copyright 1999 Brian J. Swetland 4 ** All rights reserved. 5 ** 6 ** Redistribution and use in source and binary forms, with or without 7 ** modification, are permitted provided that the following conditions 8 ** are met: 9 ** 1. Redistributions of source code must retain the above copyright 10 ** notice, this list of conditions, and the following disclaimer. 11 ** 2. Redistributions in binary form must reproduce the above copyright 12 ** notice, this list of conditions, and the following disclaimer in the 13 ** documentation and/or other materials provided with the distribution. 14 ** 3. The name of the author may not be used to endorse or promote products 15 ** derived from this software without specific prior written permission. 16 ** 17 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <fcntl.h> 32 33 #include <i386/io.h> 34 35 #include "pci.h" 36 37 uint32 read_pci(int bus, int dev, int func, int reg, int bytes) 38 { 39 uint32 base; 40 41 union { 42 confadd c; 43 uint32 n; 44 } u; 45 46 u.c.enable = 1; 47 u.c.rsvd = 0; 48 u.c.bus = bus; 49 u.c.dev = dev; 50 u.c.func = func; 51 u.c.reg = reg & 0xFC; 52 53 outl(u.n,0xCF8); 54 55 base = 0xCFC + (reg & 0x03); 56 57 switch(bytes){ 58 case 1: return inb(base); 59 case 2: return inw(base); 60 case 4: return inl(base); 61 default: return 0; 62 } 63 } 64 65 void write_pci(int bus, int dev, int func, int reg, uint32 v, int bytes) 66 { 67 uint32 base; 68 69 union { 70 confadd c; 71 uint32 n; 72 } u; 73 74 u.c.enable = 1; 75 u.c.rsvd = 0; 76 u.c.bus = bus; 77 u.c.dev = dev; 78 u.c.func = func; 79 u.c.reg = reg & 0xFC; 80 81 base = 0xCFC + (reg & 0x03); 82 outl(u.n,0xCF8); 83 switch(bytes){ 84 case 1: outb(v,base); break; 85 case 2: outw(v,base); break; 86 case 4: outl(v,base); break; 87 } 88 89 } 90 91 void probe(int bus, int dev, int func) 92 { 93 union { 94 pci_cfg cfg; 95 uint32 word[4]; 96 } x; 97 pci_cfg *cfg = &x.cfg; 98 uint32 v; 99 int i; 100 for(i=0;i<4;i++){ 101 x.word[i] = read_pci(bus,dev,func,4*i,4); 102 } 103 if(cfg->vendor_id == 0xffff) return; 104 105 printf("Device Info: /bus/pci/%d/%d/%d\n",bus,dev,func); 106 printf(" * Vendor: %S Device: %S Class/SubClass/Interface %X/%X/%X\n", 107 cfg->vendor_id,cfg->device_id,cfg->base_class,cfg->sub_class,cfg->interface); 108 printf(" * Status: %S Command: %S BIST/Type/Lat/CLS: %X/%X/%X/%X\n", 109 cfg->status, cfg->command, cfg->bist, cfg->header_type, 110 cfg->latency_timer, cfg->cache_line_size); 111 112 switch(cfg->header_type & 0x7F){ 113 case 0: /* normal device */ 114 for(i=0;i<6;i++){ 115 v = read_pci(bus,dev,func,i*4 + 0x10, 4); 116 if(v) { 117 int v2; 118 write_pci(bus,dev,func,i*4 + 0x10, 0xffffffff, 4); 119 v2 = read_pci(bus,dev,func,i*4+0x10, 4) & 0xfffffff0; 120 v2 = 1 + ~v2; 121 if(v & 1) { 122 printf(" * Base Register %d IO: %x (%x)\n",i,v&0xfff0,v2&0xffff); 123 } else { 124 printf(" * Base Register %d MM: %x (%x)\n",i,v&0xfffffff0,v2); 125 } 126 } 127 } 128 v = read_pci(bus,dev,func,0x3c,1); 129 if((v != 0xff) && (v != 0)) printf(" * Interrupt Line: %X\n",v); 130 break; 131 case 1: 132 printf(" * PCI <-> PCI Bridge\n"); 133 break; 134 default: 135 printf(" * Unknown Header Type\n"); 136 } 137 138 if(cfg->header_type & 0x80){ 139 for(i=1;i<8;i++){ 140 probe(bus,dev,i); 141 } 142 } 143 144 // v = read_pci(bus,dev,func,0x3C); 145 // printf(" * Lat/Gnt/IntPin/IntLine: %x\n",v); 146 } 147 148 int main (int argc, char **argv) 149 { 150 int bus,dev; 151 152 for(bus=0;bus<255;bus++){ 153 for(dev=0;dev<32;dev++) { 154 probe(bus,dev,0); 155 } 156 } 157 158 return 0; 159 } 160