1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <freeldr.h>
#include "prep.h"

typedef struct _pci_cfg {
    unsigned long addr;
    unsigned long data;
} pci_cfg;

typedef struct _pci_desc {
    pci_cfg *cfg;
} pci_desc;

pci_desc pci1_desc = { (void *)0x80000cf8 };
#define rev16(x) ((((x)>>8)&0xff)|(((x)&0xff)<<8))
#define rev32(x) ((((x)>>24)&0xff)|(((x)>>8)&0xff00)|(((x)&0xff00)<<8)|(((x)&0xff)<<24))
#define pci_addr(bus,dev,fn,reg) \
         (0x80000000 | \
          ((bus & 0xff) << 16) | \
          ((dev & 0x1f) << 11) | \
          ((fn & 7) << 8) | \
          (reg & 0xfc))
#if 0
#define pci_cfg_addr(bus,dev,fn,reg) \
        ((bus == 0) ? \
         ((1 << (dev + 16)) | \
          (dev << 11) | \
          (fn << 8) | \
          ((reg & 0xfc) | 1)) : pci_addr(bus,dev,fn,reg))
#else
#define pci_cfg_addr(bus,dev,fn,reg) pci_addr(bus,dev,fn,reg)
#endif
    unsigned long pci_read( pci_desc *desc, int bus, int dev, int fn, int reg, int len ) {
    sync();
    unsigned long save_state = desc->cfg->addr, ret = 0;
    unsigned long addr = pci_cfg_addr(bus,dev,fn,reg);
    unsigned long offset = reg & 3;
    desc->cfg->addr = rev32(addr);
    sync();
    switch( len ) {
    case 4:
        ret = desc->cfg->data;
        break;
    case 2:
        ret = desc->cfg->data;
        ret = (ret >> (offset << 3)) & 0xffff;
        break;
    case 1:
        ret = desc->cfg->data;
        ret = (ret >> (offset << 3)) & 0xff;
        break;
    }
    desc->cfg->addr = save_state;
    sync();
    return ret;
    }

void pci_read_bar( pci_desc *desc, int bus, int dev, int fn, int bar,
           struct _pci_bar *bar_data ) {
    bar_data->data = pci_read( desc, bus, dev, fn, 0x10 + (bar * 4), 4 );
}

/*
 * Imagine: offset 3, len 1
 * let oldval = 0x12345678 and val = 0xabcd1234;
 * mask = ((1 << 8) - 1) << 24; // 0xff000000
 * oldval = (0x12345678 & 0x00ffffff) | (0xabcd1234 & 0xff000000) = 0xab345678;
 */
void pci_write( pci_desc *desc, int bus, int dev, int fn, int reg, int len, int val ) {
    unsigned long save_state = desc->cfg->addr;
    unsigned long addr = pci_cfg_addr(bus,dev,fn,reg);
    unsigned long offset = reg & 3;
    unsigned long oldval = pci_read( desc, bus, dev, fn, reg & ~3, 4 );
    unsigned long mask = ((1 << (len * 8)) - 1) << (offset << 3);<--- Integer overflow<--- Integer overflow
    oldval = (oldval & ~mask) | ((val << (offset << 3)) & mask);
    desc->cfg->addr = rev32(addr);
    sync();
    desc->cfg->data = rev32(oldval);
    sync();
    desc->cfg->addr = save_state;
    sync();
}

void pci_write_bar( pci_desc *desc, int bus, int dev, int fn, int bar, struct _pci_bar *bar_data ) {
    pci_write( desc, bus, dev, fn, 0x10 + (bar * 4), 4, bar_data->data );<--- Calling function 'pci_write', 6th argument '4' value is 4<--- Calling function 'pci_write', 6th argument '4' value is 4
}

void print_bar( struct _pci_bar *bar ) {
    printf("BAR: %x\n", bar->data);
}

#define PCI_VENDORID 0
#define PCI_DEVICEID 2
#define PCI_HEADER_TYPE 0xe
#define PCI_BASECLASS   0xb

void pci_setup( PCONFIGURATION_COMPONENT_DATA pcibus, pci_desc *desc ) {
    unsigned char type;
    unsigned short vendor, device, devclass;
    int funcs, bus, dev, fn;

    pci1_desc.cfg = (pci_cfg *)0x80000cf8;

    printf("PCI Bus:\n");
    for( bus = 0; bus < 1; bus++ ) {
        for( dev = 0; dev < 32; dev++ ) {
            type = pci_read(desc,bus,dev,0,PCI_HEADER_TYPE,1);
            vendor = pci_read(desc,bus,dev,0,PCI_VENDORID,2);
            device = pci_read(desc,bus,dev,0,PCI_DEVICEID,2);

            if(vendor == 0 || vendor == 0xffff) continue;
            if(type & 0x80) funcs = 8; else funcs = 1;

            for( fn = 0; fn < funcs; fn++ ) {
                devclass = pci_read(desc,bus,dev,fn,PCI_BASECLASS,1);
        printf(" %d:%d -> vendor:device:class %x:%x:%x\n",
               bus, dev, vendor, device, devclass);

                if( devclass == 3 ) {
            printf("Setting up vga...\n");
                    vga_setup(pcibus,desc,&vga1_desc,bus,dev,fn);
            printf("Done with vga\n");
                }
            }
        }
    }
    printf("^-- end PCI\n");
}