openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

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