Commit Diff


commit - 5baff2808906de6d7d3ed0b3b370e5e15d3b00c7
commit + eabbd81c2041c1d54cb02608d9c375fe9c2dddfb
blob - 9f7cca2cfb0beb306bec088eec4730a5351ef79c
blob + 2f949657ef99bc433c7f48b6254a4452c483ad88
--- servers/xhci/main.c
+++ servers/xhci/main.c
@@ -1,13 +1,32 @@
-// The xHCI driver possess a number of slots for each devices
-// it can handle. The slot maximum can be changed at compile
-// time by the end user.
+// The xHCI driver is for one controller. Everytime a new
+// device is added, a new instance is launched.
 
-// There is 1 command ring per xhci controller
-
 #include "types.h"
 #include "libc.h"
 #include "xhci.h"
 
+#define TRB_COUNT	16
+
+struct trb {
+	u32 Parameter_Lo;
+	u32 Parameter_Hi;
+	u32 Status;
+	u32 Control; // Includes TRB Type, ENT and C Flags
+};
+
+struct opt_reg {
+	u32 USBCMD;
+	u32 USBSTS;
+	u32 PAGESIZE;
+	u32 RsvdZ1[2];
+	u32 DNCTRL;
+	u64 CRCR;
+	u32 RsvdZ2[4];
+	u64 DCBAAP;
+	u32 CONFIG;
+	u32 RsvdZ3[241]; // 0x3C to 0x3FF 964 bytes
+};
+
 struct xhci_ctl {
 	u8 CAPLENGTH;
 	u16 HCIVERSION;
@@ -57,6 +76,11 @@ struct xhci_ctl {
 		u8 GSC;
 		u8 VTC;
 	} HCCPARAMS2;
+
+	struct opt_reg *OPTREG;
+	u64 *DeviceContexes; // Limit defined by HCSPARAMS1.MaxSlots
+
+	struct trb *CommandRing;
 };
 
 void setup_ctl(struct xhci_ctl *, u64);
@@ -64,6 +88,7 @@ void setup_ctl(struct xhci_ctl *, u64);
 void
 xhci_main(struct contract *con)
 {
+	u8 *memptr = con->memBlock; // This is used as starting point for allocation
 	struct shared_buffer *sbuf;
 	struct xhci_ctl ctl;
 	struct xhcip *xhcip;
@@ -83,6 +108,25 @@ xhci_main(struct contract *con)
 	output("xhci: bar address is "); outputh(xhcip->address); output("\n");
 	setup_ctl(&ctl, xhcip->address);
 
+	// Initialize controller
+	while ((ctl.OPTREG->USBSTS >> 11) & 0x1);
+
+	// You can't do that while controller is running R/S = 1 or
+	// if the MaxSlots is 0 which is rare
+	ctl.OPTREG->CONFIG &= ~(0xff);
+	ctl.OPTREG->CONFIG |= ctl.HCSPARAMS1.MaxSlots;
+
+	// are we allocating?
+	ctl.DeviceContexes = (u64 *)(memptr);
+	memptr += ((ctl.HCSPARAMS1.MaxSlots + 1) * 8);
+	ctl.OPTREG->DCBAAP = (u64)ctl.DeviceContexes; // The lower 6 bits are zero'd since alligned
+
+	// again
+	memptr = (u8 *)(((u64)memptr + 63) & ~63); // 64 bytes alligned
+	ctl.CommandRing = (struct trb *)memptr;
+	memptr += (sizeof(struct trb) * TRB_COUNT);
+	ctl.OPTREG->CRCR = ((u64)ctl.CommandRing) | 1;
+
 	for (;;);
 }
 
@@ -136,6 +180,8 @@ setup_ctl(struct xhci_ctl *ctl, u64 bar)
 	ctl->HCCPARAMS2.GSC = (base[7] >> 8) & 0x1;
 	ctl->HCCPARAMS2.VTC = (base[7] >> 9) & 0x1;
 
+	ctl->OPTREG = (struct opt_reg *)(bar + ctl->CAPLENGTH);
+
 	output("xhci setup: version ");
 	outputh(ctl->HCIVERSION);
 	output("\n");