blob: 5cd2102fc82ceda57efb1ca41e2f8cf1727543b3 (
plain)
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
|
//
// simple PCI-Express initialization, only
// works for qemu and its e1000 card.
//
#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "riscv.h"
#include "spinlock.h"
#include "proc.h"
#include "defs.h"
void
pci_init()
{
// we'll place the e1000 registers at this address.
// vm.c maps this range.
uint64 e1000_regs = 0x40000000L;
// qemu -machine virt puts PCIe config space here.
// vm.c maps this range.
uint32 *ecam = (uint32 *) 0x30000000L;
// look at each possible PCI device on bus 0.
for(int dev = 0; dev < 32; dev++){
int bus = 0;
int func = 0;
int offset = 0;
uint32 off = (bus << 16) | (dev << 11) | (func << 8) | (offset);
volatile uint32 *base = ecam + off;
uint32 id = base[0];
// 100e:8086 is an e1000
if(id == 0x100e8086){
// command and status register.
// bit 0 : I/O access enable
// bit 1 : memory access enable
// bit 2 : enable mastering
base[1] = 7;
__sync_synchronize();
for(int i = 0; i < 6; i++){
uint32 old = base[4+i];
// writing all 1's to the BAR causes it to be
// replaced with its size.
base[4+i] = 0xffffffff;
__sync_synchronize();
base[4+i] = old;
}
// tell the e1000 to reveal its registers at
// physical address 0x40000000.
base[4+0] = e1000_regs;
e1000_init((uint32*)e1000_regs);
}
}
}
|