summaryrefslogtreecommitdiff
path: root/kernel/pci.c
diff options
context:
space:
mode:
authorSanjit Bhat <[email protected]>2023-10-26 06:44:48 -0400
committerSanjit Bhat <[email protected]>2023-10-26 06:44:48 -0400
commitcfae93475dfb4cb5cfe264f4c029136e1447c262 (patch)
tree699903e093e3a23caf7ce3899e7c80e48511f900 /kernel/pci.c
parent1ed40716eb54e371df9d1814b9129666b3fe4f09 (diff)
downloadxv6-labs-cfae93475dfb4cb5cfe264f4c029136e1447c262.tar.gz
xv6-labs-cfae93475dfb4cb5cfe264f4c029136e1447c262.tar.bz2
xv6-labs-cfae93475dfb4cb5cfe264f4c029136e1447c262.zip
net add missing files
Diffstat (limited to 'kernel/pci.c')
-rw-r--r--kernel/pci.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/kernel/pci.c b/kernel/pci.c
new file mode 100644
index 0000000..5cd2102
--- /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] = 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);
+ }
+ }
+}