Я разрабатываю свою собственную ОС и пытаюсь реализовать очень простой каркасный драйвер xhci. Я перезагрузил контроллер, выделил DCBAA и настроил кольца команд и событий. В качестве «Hello World» для драйвера я пытаюсь отправить образец TRB через кольцо команд и увидеть TRB завершения события в кольце событий, но TRB в кольце событий не генерируется. Я тестирую это в QEMU с включенными журналами трассировки xhci, поэтому могу подтвердить, что кольцо команд работает успешно, но кольцо событий не создает никаких записей в журнале.
Это мой драйвер код инициализации:
bool XhciDriver::init(PciDeviceInfo& deviceInfo) {
_mapDeviceMmio(deviceInfo.barAddress);
uint64_t opRegBase = (uint64_t)m_capRegisters + m_capRegisters->caplength;
m_opRegisters = (volatile XhciOperationalRegisters*)opRegBase;
m_runtimeRegisterBase = opRegBase + m_capRegisters->rtsoff;
m_rtRegisters = (volatile XhciRuntimeRegisters*)m_runtimeRegisterBase;
m_maxDeviceSlots = XHCI_MAX_DEVICE_SLOTS(m_capRegisters);
m_numPorts = XHCI_NUM_PORTS(m_capRegisters);
printXhciCapabilityRegisters(m_capRegisters);
printXhciOperationalRegisters(m_opRegisters);
_assumeOwnershipFromBios();
if (!_resetController()) {
return false;
}
kuPrint("[XHCI] Reset the controller\n");
// Set the Max Device Slots Enabled field
uint32_t configReg = XHCI_SET_MAX_SLOTS_EN(m_opRegisters->config, m_maxDeviceSlots);
m_opRegisters->config = configReg;
m_opRegisters->dnctrl |= 0b1111111111111111;
if (_checkForHostControllerError()) {
return false;
}
// ============================== Initialize DCBAA ============================== //
kuPrint("[XHCI] device slots: %llu ports: %llu\n", m_maxDeviceSlots, m_numPorts);
kuPrint("[XHCI] 64-byte contexts: %s\n", _is64ByteContextUsed() ? "true" : "false");
size_t contextEntrySize = _is64ByteContextUsed() ? 64 : 32;
void* dcbaaVirtualBase = _allocXhciMemory(contextEntrySize * (m_maxDeviceSlots + 1));
zeromem(dcbaaVirtualBase, contextEntrySize * (m_maxDeviceSlots + 1));
kuPrint("[XHCI] dcbaa va: %llx pa: %llx\n", dcbaaVirtualBase, (uint64_t)__pa(dcbaaVirtualBase));
/*
// xHci Spec Section 6.1 (page 404)
If the Max Scratchpad Buffers field of the HCSPARAMS2 register is > ‘0’, then
the first entry (entry_0) in the DCBAA shall contain a pointer to the Scratchpad
Buffer Array. If the Max Scratchpad Buffers field of the HCSPARAMS2 register is
= ‘0’, then the first entry (entry_0) in the DCBAA is reserved and shall be
cleared to ‘0’ by software.
*/
uint32_t maxScratchpadBuffers = XHCI_MAX_SCRATCHPAD_BUFFERS(m_capRegisters);
kuPrint("[XHCI] Scratchpad buffer: %s\n", maxScratchpadBuffers > 0 ? "required" : "not required");
// Initialize scratchpad buffer array if needed
if (maxScratchpadBuffers > 0) {
void* scratchpadArray = _allocXhciMemory(contextEntrySize * maxScratchpadBuffers);
zeromem(scratchpadArray, contextEntrySize * maxScratchpadBuffers);
((uint64_t*)dcbaaVirtualBase)[0] = (uint64_t)__pa(scratchpadArray);
}
m_opRegisters->dcbaap = (uint64_t)__pa(dcbaaVirtualBase);
// ============================== Initialize command ring ============================== //
size_t cmdRingSize = sizeof(XhciTrb_t) * 256;
XhciTrb_t* commandRing = (XhciTrb_t*)_allocXhciMemory(cmdRingSize);
zeromem(commandRing, cmdRingSize);
// Initialize the command ring TRBs
for (int i = 0; i < 256; i++) {
commandRing[i].control = 1; // Set cycle bit to 1 for each TRB
}
// Set the last TRB as a link TRB to point back to the first TRB
commandRing[255].parameter = (uint64_t)__pa(commandRing);
commandRing[255].control = (XHCI_TRB_TYPE_LINK crcr = cmdRingPhysicalBase | XHCI_CRCR_RING_CYCLE_STATE;
kuPrint("[XHCI] Command ring initialized: %llx\n", (uint64_t)commandRing);
// ============================== Initialize event ring ============================== //
// Define the size of the event ring
const size_t eventRingSize = 256 * sizeof(XhciTrb_t);
// Allocate memory for the event ring
void* eventRingVirtualBase = _allocXhciMemory(eventRingSize);
zeromem(eventRingVirtualBase, eventRingSize);
XhciTrb_t* eventRing = (XhciTrb_t*)eventRingVirtualBase;
// Set up the Link TRB to create a circular buffer
eventRing[255].parameter = (uint64_t)__pa(eventRingVirtualBase); // Link to the start of the ring
eventRing[255].status = 0;
eventRing[255].control = (XHCI_TRB_TYPE_LINK crcr;
// Allocate and clear a test TRB
XhciTrb_t testTrb;
zeromem(&testTrb, sizeof(XhciTrb_t));
// noOpTrb.control = (XHCI_TRB_TYPE_NOOP crcr);
// Poll the event ring for a completion event
kuPrint("[XHCI] Polling Event Ring at address: %llx\n", eventRing);
while (true) {
for (int i = 0; i < 256; ++i) {
if (eventRing[i].control != 0 && (eventRing[i].control >> 10) != XHCI_TRB_TYPE_LINK) {
kuPrint("[XHCI] Event Ring TRB[%i]: parameter = %llx, status = %x, control = %x\n",
i, eventRing[i].parameter, eventRing[i].status, eventRing[i].control);
if ((eventRing[i].control >> 10) == XHCI_TRB_TYPE_ENABLE_SLOT_CMD) {
kuPrint("[XHCI] Enable Slot TRB processed successfully\n");
return true;
}
}
}
kuPrint("[XHCI] No TRBs found in the event ring...\n");
sleep(2);
}
kuPrint("\n");
return true;
}
Я утверждал, что контроллер xhci не сталкивается с какими-либо системными ошибками (мониторинг регистра usbsts), и все адреса выровнены по 64 байтам. Ниже приведен журнал qemu событий xhci:
usb_xhci_oper_read off 0x0004, ret 0x00000001
usb_xhci_cap_read off 0x0010, ret 0x00087001
usb_xhci_cap_read off 0x0010, ret 0x00087001
usb_xhci_cap_read off 0x0008, ret 0x0000000f
usb_xhci_cap_read off 0x0008, ret 0x0000000f
usb_xhci_oper_write off 0x0030, val 0x01512880
usb_xhci_oper_write off 0x0034, val 0x00000000
usb_xhci_oper_write off 0x0018, val 0x01513101
usb_xhci_oper_write off 0x001c, val 0x00000000
usb_xhci_runtime_write off 0x0068, val 0x00000001
usb_xhci_runtime_write off 0x0078, val 0x01514140
usb_xhci_runtime_write off 0x007c, val 0x00000000
usb_xhci_runtime_write off 0x0070, val 0x015122c0
usb_xhci_runtime_write off 0x0074, val 0x00000000
usb_xhci_runtime_read off 0x0070, ret 0x015122c0
usb_xhci_runtime_read off 0x0074, ret 0x00000000
usb_xhci_runtime_read off 0x0068, ret 0x00000001
usb_xhci_runtime_read off 0x0078, ret 0x01514140
usb_xhci_runtime_read off 0x007c, ret 0x00000000
usb_xhci_oper_read off 0x0000, ret 0x00000000
usb_xhci_oper_write off 0x0000, val 0x00000001
usb_xhci_run
usb_xhci_oper_read off 0x0004, ret 0x00000000
usb_xhci_oper_read off 0x0000, ret 0x00000001
usb_xhci_oper_read off 0x0004, ret 0x00000000
usb_xhci_oper_read off 0x0008, ret 0x00000001
usb_xhci_oper_read off 0x0014, ret 0x0000ffff
usb_xhci_oper_read off 0x0018, ret 0x01513101
usb_xhci_oper_read off 0x001c, ret 0x00000000
usb_xhci_oper_read off 0x0030, ret 0x01512880
usb_xhci_oper_read off 0x0034, ret 0x00000000
usb_xhci_oper_read off 0x0038, ret 0x00000040
usb_xhci_oper_read off 0x0004, ret 0x00000000
usb_xhci_oper_read off 0x0018, ret 0x01513101
usb_xhci_oper_read off 0x001c, ret 0x00000000
usb_xhci_cap_read off 0x0014, ret 0x00002000
usb_xhci_doorbell_write off 0x0000, val 0x00000000
usb_xhci_fetch_trb addr 0x0000000001513100, CR_ENABLE_SLOT, p 0x0000000000000000, s 0x00000000, c 0x00002400
usb_xhci_oper_read off 0x0018, ret 0x01513101
usb_xhci_oper_read off 0x001c, ret 0x00000000
Я тестировал это и на реальном оборудовании, и там оно тоже не работает, так что это не просто проблема qemu.
Я разрабатываю свою собственную ОС и пытаюсь реализовать очень простой каркасный драйвер xhci. Я перезагрузил контроллер, выделил DCBAA и настроил кольца команд и событий. В качестве «Hello World» для драйвера я пытаюсь отправить образец TRB через кольцо команд и увидеть TRB завершения события в кольце событий, но TRB в кольце событий не генерируется. Я тестирую это в QEMU с включенными журналами трассировки xhci, поэтому могу подтвердить, что кольцо команд работает успешно, но кольцо событий не создает никаких записей в журнале. Это мой драйвер код инициализации: [code] bool XhciDriver::init(PciDeviceInfo& deviceInfo) { _mapDeviceMmio(deviceInfo.barAddress);
if (!_resetController()) { return false; } kuPrint("[XHCI] Reset the controller\n");
// Set the Max Device Slots Enabled field uint32_t configReg = XHCI_SET_MAX_SLOTS_EN(m_opRegisters->config, m_maxDeviceSlots); m_opRegisters->config = configReg;
m_opRegisters->dnctrl |= 0b1111111111111111;
if (_checkForHostControllerError()) { return false; }
If the Max Scratchpad Buffers field of the HCSPARAMS2 register is > ‘0’, then the first entry (entry_0) in the DCBAA shall contain a pointer to the Scratchpad Buffer Array. If the Max Scratchpad Buffers field of the HCSPARAMS2 register is = ‘0’, then the first entry (entry_0) in the DCBAA is reserved and shall be cleared to ‘0’ by software. */ uint32_t maxScratchpadBuffers = XHCI_MAX_SCRATCHPAD_BUFFERS(m_capRegisters); kuPrint("[XHCI] Scratchpad buffer: %s\n", maxScratchpadBuffers > 0 ? "required" : "not required");
// Initialize the command ring TRBs for (int i = 0; i < 256; i++) { commandRing[i].control = 1; // Set cycle bit to 1 for each TRB }
// Set the last TRB as a link TRB to point back to the first TRB commandRing[255].parameter = (uint64_t)__pa(commandRing); commandRing[255].control = (XHCI_TRB_TYPE_LINK crcr = cmdRingPhysicalBase | XHCI_CRCR_RING_CYCLE_STATE;
kuPrint("[XHCI] Command ring initialized: %llx\n", (uint64_t)commandRing);
// ============================== Initialize event ring ============================== // // Define the size of the event ring const size_t eventRingSize = 256 * sizeof(XhciTrb_t);
// Allocate memory for the event ring void* eventRingVirtualBase = _allocXhciMemory(eventRingSize); zeromem(eventRingVirtualBase, eventRingSize);
// Set up the Link TRB to create a circular buffer eventRing[255].parameter = (uint64_t)__pa(eventRingVirtualBase); // Link to the start of the ring eventRing[255].status = 0; eventRing[255].control = (XHCI_TRB_TYPE_LINK crcr;
// Allocate and clear a test TRB XhciTrb_t testTrb; zeromem(&testTrb, sizeof(XhciTrb_t)); // noOpTrb.control = (XHCI_TRB_TYPE_NOOP crcr);
// Poll the event ring for a completion event kuPrint("[XHCI] Polling Event Ring at address: %llx\n", eventRing);
while (true) { for (int i = 0; i < 256; ++i) { if (eventRing[i].control != 0 && (eventRing[i].control >> 10) != XHCI_TRB_TYPE_LINK) { kuPrint("[XHCI] Event Ring TRB[%i]: parameter = %llx, status = %x, control = %x\n", i, eventRing[i].parameter, eventRing[i].status, eventRing[i].control); if ((eventRing[i].control >> 10) == XHCI_TRB_TYPE_ENABLE_SLOT_CMD) { kuPrint("[XHCI] Enable Slot TRB processed successfully\n"); return true; } } } kuPrint("[XHCI] No TRBs found in the event ring...\n"); sleep(2); }
kuPrint("\n"); return true; } [/code] Я утверждал, что контроллер xhci не сталкивается с какими-либо системными ошибками (мониторинг регистра usbsts), и все адреса выровнены по 64 байтам. Ниже приведен журнал qemu событий xhci: [code]usb_xhci_oper_read off 0x0004, ret 0x00000001 usb_xhci_cap_read off 0x0010, ret 0x00087001 usb_xhci_cap_read off 0x0010, ret 0x00087001 usb_xhci_cap_read off 0x0008, ret 0x0000000f usb_xhci_cap_read off 0x0008, ret 0x0000000f usb_xhci_oper_write off 0x0030, val 0x01512880 usb_xhci_oper_write off 0x0034, val 0x00000000 usb_xhci_oper_write off 0x0018, val 0x01513101 usb_xhci_oper_write off 0x001c, val 0x00000000 usb_xhci_runtime_write off 0x0068, val 0x00000001 usb_xhci_runtime_write off 0x0078, val 0x01514140 usb_xhci_runtime_write off 0x007c, val 0x00000000 usb_xhci_runtime_write off 0x0070, val 0x015122c0 usb_xhci_runtime_write off 0x0074, val 0x00000000 usb_xhci_runtime_read off 0x0070, ret 0x015122c0 usb_xhci_runtime_read off 0x0074, ret 0x00000000 usb_xhci_runtime_read off 0x0068, ret 0x00000001 usb_xhci_runtime_read off 0x0078, ret 0x01514140 usb_xhci_runtime_read off 0x007c, ret 0x00000000 usb_xhci_oper_read off 0x0000, ret 0x00000000 usb_xhci_oper_write off 0x0000, val 0x00000001 usb_xhci_run usb_xhci_oper_read off 0x0004, ret 0x00000000 usb_xhci_oper_read off 0x0000, ret 0x00000001 usb_xhci_oper_read off 0x0004, ret 0x00000000 usb_xhci_oper_read off 0x0008, ret 0x00000001 usb_xhci_oper_read off 0x0014, ret 0x0000ffff usb_xhci_oper_read off 0x0018, ret 0x01513101 usb_xhci_oper_read off 0x001c, ret 0x00000000 usb_xhci_oper_read off 0x0030, ret 0x01512880 usb_xhci_oper_read off 0x0034, ret 0x00000000 usb_xhci_oper_read off 0x0038, ret 0x00000040 usb_xhci_oper_read off 0x0004, ret 0x00000000 usb_xhci_oper_read off 0x0018, ret 0x01513101 usb_xhci_oper_read off 0x001c, ret 0x00000000 usb_xhci_cap_read off 0x0014, ret 0x00002000 usb_xhci_doorbell_write off 0x0000, val 0x00000000 usb_xhci_fetch_trb addr 0x0000000001513100, CR_ENABLE_SLOT, p 0x0000000000000000, s 0x00000000, c 0x00002400 usb_xhci_oper_read off 0x0018, ret 0x01513101 usb_xhci_oper_read off 0x001c, ret 0x00000000 [/code] Я тестировал это и на реальном оборудовании, и там оно тоже не работает, так что это не просто проблема qemu.
Я работаю над расширением ОС Stanford Pintos для поддержки USB 3.0 через xhci (расширяемый интерфейс контроллера хоста) . Существующая система поддерживает только UHCI (USB 1.1) и частично EHCI (USB 2.0), поэтому мы переходим к современному стеку...
Круги имеют заданный радиус CircleRadius. Кольцо имеет максимальный радиус maxRingRadius. Количество кругов может быть любым целым числом,круги, которое необходимо вычислить вместе с фактическим радиусом...
Я хочу поместить кольцо в проект карты. Я хотел бы установить внутренний и внешний радиус и разместить центр где угодно.
Необходимый импорт:
import cartopy
import cartopy.crs as ccrs
from cartopy import geodesic
import numpy as np
import...