diff options
author | Mole Shang <[email protected]> | 2024-02-17 11:55:33 +0800 |
---|---|---|
committer | Mole Shang <[email protected]> | 2024-02-17 12:22:07 +0800 |
commit | e8e0a7b4c97064eb5e9415726d7e38aaceccd3fd (patch) | |
tree | fb42ba5be7a8ae608b968266f62fd71fa889a89d /kernel/pci.c | |
parent | a6af72924b115c1177d18d9b1eaba56623e4248b (diff) | |
parent | d85aec2689c4250d0384904bdc11aa618c726bec (diff) | |
download | xv6-labs-e8e0a7b4c97064eb5e9415726d7e38aaceccd3fd.tar.gz xv6-labs-e8e0a7b4c97064eb5e9415726d7e38aaceccd3fd.tar.bz2 xv6-labs-e8e0a7b4c97064eb5e9415726d7e38aaceccd3fd.zip |
Merge branch 'thread' into fs
Conflicts:
.gitignore
Makefile
conf/lab.mk
kernel/param.h
Diffstat (limited to 'kernel/pci.c')
-rw-r--r-- | kernel/pci.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/kernel/pci.c b/kernel/pci.c new file mode 100644 index 0000000..3e361c5 --- /dev/null +++ b/kernel/pci.c @@ -0,0 +1,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] = 0b111; + __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); + } + } +} |