main.c (11410B)
1 #include <uefi.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <console.h> 5 #include <pci.h> 6 #include <xhc.h> 7 8 error err; 9 uint8 kernel_main_stack[1024]; 10 RGBA32 m_img[16*16]; // initialized at the bottom of this file. 11 12 void 13 kernel_main(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop) 14 { 15 EFI_GRAPHICS_OUTPUT_PROTOCOL _gop = *gop; 16 gop = &_gop; 17 if (init_root_window( 18 (uint32 *)gop->Mode->FrameBufferBase, 19 gop->Mode->Info->HorizontalResolution, 20 gop->Mode->Info->VerticalResolution, 21 gop->Mode->Info->PixelsPerScanLine, 22 gop->Mode->Info->PixelFormat 23 ) < 0) { 24 // still can't print to console. 25 goto halt; 26 } 27 Window *root_children[MAX_CHILD_WIN]; // TODO: implement malloc. 28 root_window.children = root_children; 29 30 Window win0; 31 make_window(&root_window, &win0, (Point){150, 100}, (Point){400, 700}, 0xff, 0xb9d08bff); 32 Console con0 = { 33 .win = &win0, 34 .font = &asciifont, 35 .w = win0.size.x / 8, 36 .h = win0.size.y / 16, 37 .pos = (Point){0, 0} 38 }; 39 RGBA32 m_hidden[16*16]; 40 Mouse m = { 41 .size = (Point) {16, 16}, 42 .pos = (Point) {143, 150}, 43 .hidden = m_hidden, 44 .img = m_img, 45 }; 46 47 m.pos.x = (m.pos.x + 1) % root_window.size.x; 48 draw_mouse(&root_window, &m); 49 pci_scan_all_bus(); 50 51 cons_printf(&con0, "pci devices:\n"); 52 PCIDev *pci_xhc = NULL; 53 for (int i = 0; i < num_pci_dev; i++) { 54 cons_printf(&con0, "%d:\t%x\t%x\t%x\t%x\t%x\n", i, 55 pci_dev[i].vendor_id, pci_dev[i].device_id, 56 pci_dev[i].base_class, pci_dev[i].sub_class, 57 pci_dev[i].prog); 58 if (pci_dev[i].base_class == 0xc && pci_dev[i].sub_class == 0x3 && 59 pci_dev[i].prog == 0x30) { 60 pci_xhc = &pci_dev[i]; 61 } 62 } 63 if (pci_xhc == NULL) { 64 cons_printf(&con0, "xhci device not found.\n"); 65 goto halt; 66 } 67 68 // populate Xhc struct. 69 // TODO: find the following calculation in some specification. 70 // only article found is osdev's page: 71 // osdev.org/PCI#Address_and_size_of_the_BAR 72 Xhc xhc; 73 xhc.base = ((uintptr) pci_xhc->t0.base_address_register[1]) << 32 | 74 (pci_xhc->t0.base_address_register[0]&0xfffffff0); 75 xhc.cap = (xhc_capability_registers *) xhc.base; 76 xhc.op = (xhc_operational_registers *) (xhc.base + xhc.cap->CAPLENGTH); 77 xhc.runtime = (xhc_runtime_registers *) (xhc.base + xhc.cap->RTSOFF); 78 xhc.doorbell = (xhc_doorbell_registers *) (xhc.base + xhc.cap->DBOFF); 79 80 // reset xhc. 81 if ((xhc.op->USBSTS & 0x1) != 1) { // USBSTS.HCH 82 xhc.op->USBCMD &= ~0x1; // USBCMD.R/S. stop xhc. 83 for (;(xhc.op->USBSTS & 0x1) != 1;) { 84 } 85 } 86 xhc.op->USBCMD |= 1 << 1; // USBCMD.HCRST 87 for (;(xhc.op->USBCMD&(1<<1)) != 0;) { 88 } 89 cons_printf(&con0, "usb reset done\n"); 90 for (;(xhc.op->USBSTS&(1<<11)) != 0;) { // USBSTS.CNR 91 } 92 cons_printf(&con0, "usb controller ready\n"); 93 94 if ((uint8) (xhc.cap->HCSPARAMS1&0xff) < 1) { // HCSPARAMS1.MaxSlots 95 cons_printf(&con0, "Max Device Slot is too small: %d\n", (uint8) (xhc.cap->HCSPARAMS1&0xff)); 96 goto halt; 97 } 98 xhc.op->CONFIG |= 1; // CONFIG.MaxSlotsEn 99 cons_printf(&con0, "CONFIG: %x\n", xhc.op->CONFIG); 100 // TODO: align DCBAAP in 64-byte. 101 // I don't like __attribute__ 102 xhc_device_context *DCBAAP[2] __attribute__((aligned(64))) = {0}; 103 if (((uint64) DCBAAP&~(uint64)0x3f) != (uint64) DCBAAP) { 104 cons_printf(&con0, "DCBAAP not aligned: %x\n", (uint64) DCBAAP); 105 goto halt; 106 } 107 xhc_device_context device_context; 108 DCBAAP[1] = &device_context; 109 xhc.op->DCBAAP = (uint64) DCBAAP; 110 cons_printf(&con0, "DCBAAP: %x\n", xhc.op->DCBAAP); 111 112 // setup the command ring. 113 xhc_trb command_ring[16] __attribute__((aligned(64))) = {0}; 114 int command_ring_pcs = 1; 115 // set link TRB. 116 command_ring[15].parameter = (uint64) command_ring; 117 command_ring[15].control = 6 << 10; // TRB type: link TRB 118 xhc.op->CRCR = (uint64) command_ring; 119 120 // setup an event ring. 121 xhc_trb event_ring_segment_table[1] __attribute__((aligned(64))) = {0}; 122 xhc_trb event_ring_segment[16] __attribute__((aligned(16))) = {0}; 123 int event_ring_ccs = 1; 124 event_ring_segment_table[0].parameter = (uint64) event_ring_segment; 125 event_ring_segment_table[0].status = 16; 126 xhc.runtime->IR[0].ERSTSZ = sizeof(event_ring_segment_table) / sizeof(event_ring_segment_table[0]); 127 xhc.runtime->IR[0].ERDP = (uint64) event_ring_segment; 128 xhc.runtime->IR[0].ERSTBA = (uint64) event_ring_segment_table; 129 130 // setup the primary interrupter 131 xhc.runtime->IR[0].IMOD = 4000; 132 xhc.runtime->IR[0].IMAN |= 3; // IMAN.IP & IMAN.IE 133 xhc.op->USBCMD |= 1 << 2; // USBCMD.INTE 134 135 // setup interrupt 136 uint32 msg __attribute__((aligned(4))) = 0; 137 cons_printf(&con0, "local apic id: %x\n", *(uint32 *) (0xfee00020) >> 24); 138 uintptr pci_config_base = (uintptr) pci_xhc; 139 PCICap *cap = (PCICap *) (pci_config_base + pci_xhc->capabilities_pointer); 140 for (;; cap = (PCICap *) (pci_config_base + cap->next_pointer)) { 141 switch (cap->capability_id) { 142 case 0x5: 143 cons_printf(&con0, "MSI\n"); 144 MSICap *msi_cap = (MSICap *) cap; 145 msi_cap->message_control |= 0x1; // enable MSI 146 cons_printf(&con0, "message_control: %x\n", msi_cap->message_control); 147 msi_cap->message_address = (uint32) (uint64) &msg; 148 msi_cap->message_upper_address = (uint32) ((uint64) &msg >> 32); 149 msi_cap->message_data = 0xcafe; 150 break; 151 case 0x11: 152 cons_printf(&con0, "MSI-X is not supported\n"); 153 /* pending development 154 MSIXCap *msix_cap = (MSIXCap *) cap; 155 // enable msi-x 156 msix_cap->message_control |= 1 << 15; 157 cons_printf(&con0, "message control: %x\n", msix_cap->message_control); 158 int bir = (int) msix_cap->table_offset&0x3; 159 uintptr bar = ((uintptr) pci_xhc->t0.base_address_register[bir+1]) << 32 | 160 (pci_xhc->t0.base_address_register[bir]&0xfffffff0); 161 MSIXTab msixtab = (MSIXTab)(bar + (msix_cap->table_offset&~0x3)); 162 // setup message 163 uint32 msg __attribute__((aligned(4))); 164 cons_printf(&con0, "&msg: %x\n", &msg); 165 msixtab[0].MsgAddr = (uint32) ((uint64)&msg)&0xffffffff; 166 msixtab[0].MsgUpperAddr = (uint32) (((uint64)&msg)>>32)&0xffffffff; 167 msixtab[0].MsgData = 0xdeadbeef; 168 msixtab[0].VectorControl &= ~0x1; 169 cons_printf(&con0, "capability_id: %x\n", msix_cap->capability_id); 170 cons_printf(&con0, "next_pointer: %x\n", msix_cap->next_pointer); 171 cons_printf(&con0, "table_offset: %x\n", msix_cap->table_offset); 172 cons_printf(&con0, "pba_offset: %x\n", msix_cap->pba_offset); 173 cons_printf(&con0, "msgaddr:\t%x\nmsgupperaddr:\t%x\nmsgdata:\t%x\nvectorcontrol:\t%x\n", 174 msixtab[0].MsgAddr, msixtab[0].MsgUpperAddr, 175 msixtab[0].MsgData, msixtab[0].VectorControl); 176 */ 177 break; 178 default: 179 cons_printf(&con0, "unsupported capability: 0x%x\n", 180 cap->capability_id); 181 break; 182 } 183 if (cap->next_pointer == 0) { 184 break; 185 } 186 } 187 // enable xHC. 188 xhc.op->USBCMD |= 0x1; // USBCMD.R/S 189 for (;(xhc.op->USBSTS & 0x1) != 0;) { 190 } 191 cons_printf(&con0, "xHC started\n"); 192 193 // read ERDP 194 xhc_trb *ERDP = (xhc_trb *) (xhc.runtime->IR[0].ERDP&~0xf); 195 cons_printf(&con0, "ERDP: %x\n", ERDP); 196 cons_printf(&con0, "event_ring_segment: %x\n", event_ring_segment); 197 for (; (ERDP->control&0x1) == event_ring_ccs; ERDP += sizeof(xhc_trb)) { 198 if (ERDP >= event_ring_segment + 199 sizeof(xhc_trb)*event_ring_segment_table[0].status) { 200 ERDP = event_ring_segment; 201 event_ring_ccs = !event_ring_ccs; 202 } 203 ERDP->control = (ERDP->control&0xfffffffe) | !event_ring_ccs; 204 cons_printf(&con0, "parameter:\t%x\nstatus:\t%x\ncontrol:\t%x\n", 205 ERDP->parameter, ERDP->status, ERDP->control); 206 } 207 xhc.runtime->IR[0].ERDP = (uint64) ERDP|(xhc.runtime->IR[0].ERDP&0xf); 208 cons_printf(&con0, "processed event ring\n"); 209 210 // reset port. 211 int max_ports = xhc.cap->HCSPARAMS1>>24; 212 struct PRS *port = NULL; 213 cons_printf(&con0, "MaxPorts: %x\n", max_ports); 214 for (int i = 0; i < max_ports; i++) { 215 if ((xhc.op->PRS[i].PORTSC&(1<<17|1)) == (1<<17|1)) { // PORTSC.CSC&PORTSC.CCS 216 cons_printf(&con0, "%d:\tPORTSC: %x\n", 217 i, xhc.op->PRS[i].PORTSC); 218 port = &xhc.op->PRS[i]; 219 } 220 } 221 if (port == NULL) { 222 cons_printf(&con0, "no port enabled.\n"); 223 goto halt; 224 } 225 uint32 st = port->PORTSC; 226 st ^= 1<<31|1<<29|1<<28|1<<23|1<<22|1<<21|1<<20|1<<19|1<<18|1<<2|1<<1; 227 port->PORTSC = st|1<<17|1<<4; // PORTSC.CSC&PORTSC.PR 228 for (;(port->PORTSC&(1<<4)) != 0;) { // wait for PORTSC.PR becomes 0. 229 } 230 cons_printf(&con0, "port:\tPORTSC: %x\n", port->PORTSC); 231 232 // assign a slot. 233 234 cons_printf(&con0, "offset of prs[0]: %x\n", 235 (uintptr) xhc.op->PRS - (uintptr) xhc.op); 236 237 halt: 238 for(;;) { __asm__("hlt"); } 239 } 240 241 RGBA32 m_img[16*16] = { 242 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 243 0x000000ff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 244 0x000000ff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 245 0x000000ff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 246 0x000000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 247 0x000000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 248 0x000000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 249 0x000000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 250 0x000000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 251 0x000000ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 252 0x000000ff, 0xffffffff, 0xffffffff, 0x000000ff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 253 0x000000ff, 0xffffffff, 0x000000ff, 0x00000000, 0x00000000, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 254 0x000000ff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000ff, 0x000000ff, 0x000000ff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 255 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 256 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 257 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};