setos

拙OS
Log | Files | Refs | LICENSE

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};