21 #include "modules/system/usb/Usb.h" 22 #include "modules/system/usb/UsbHub.h" 23 #include "pedigree/kernel/LockGuard.h" 24 #include "pedigree/kernel/Log.h" 25 #include "pedigree/kernel/Spinlock.h" 26 #include "pedigree/kernel/machine/Device.h" 27 #include "pedigree/kernel/machine/IrqManager.h" 28 #include "pedigree/kernel/machine/Machine.h" 29 #include "pedigree/kernel/machine/Pci.h" 30 #include "pedigree/kernel/machine/types.h" 31 #include "pedigree/kernel/process/Mutex.h" 32 #include "pedigree/kernel/process/Thread.h" 33 #include "pedigree/kernel/processor/IoBase.h" 34 #include "pedigree/kernel/processor/MemoryRegion.h" 35 #include "pedigree/kernel/processor/PhysicalMemoryManager.h" 36 #include "pedigree/kernel/processor/Processor.h" 37 #include "pedigree/kernel/processor/ProcessorInformation.h" 38 #include "pedigree/kernel/processor/VirtualAddressSpace.h" 39 #include "pedigree/kernel/processor/state_forward.h" 40 #include "pedigree/kernel/processor/types.h" 41 #include "pedigree/kernel/time/Time.h" 42 #include "pedigree/kernel/utilities/ExtensibleBitmap.h" 43 #include "pedigree/kernel/utilities/RequestQueue.h" 44 #include "pedigree/kernel/utilities/String.h" 45 #include "pedigree/kernel/utilities/Vector.h" 46 #include "pedigree/kernel/utilities/utility.h" 48 #define INDEX_FROM_QTD(ptr) \ 49 (((reinterpret_cast<uintptr_t>((ptr)) & 0xFFF) / sizeof(qTD))) 50 #define PHYS_QTD(idx) (m_pqTDListPhys + ((idx) * sizeof(qTD))) 52 #define GET_PAGE(param, page, qhIndex) \ 55 if ((nBufferPageOffset + nBytes) > ((page) *0x1000)) \ 57 if (va.isMapped(reinterpret_cast<void *>( \ 58 pBufferPageStart + (page) *0x1000))) \ 60 physical_uintptr_t phys = 0; \ 63 reinterpret_cast<void *>( \ 64 pBufferPageStart + (page) *0x1000), \ 66 (param) = phys >> 12; \ 71 "EHCI: addTransferToTransaction: Buffer (page " \ 72 << Dec << (page) << Hex << ") isn't mapped!"); \ 73 m_QHBitmap.clear((qhIndex)); \ 81 m_pCurrentQueueHead(0), m_EhciMR(
"Ehci-MR")
83 setSpecificType(
String(
"EHCI"));
93 ERROR(
"USB: EHCI: Couldn't allocate Memory Region!");
97 uintptr_t virtualBase =
98 reinterpret_cast<uintptr_t
>(m_EhciMR.virtualAddress());
99 uintptr_t physicalBase = m_EhciMR.physicalAddress();
100 m_pQHList =
reinterpret_cast<QH *
>(virtualBase);
101 m_pFrameList =
reinterpret_cast<uint32_t *
>(virtualBase + 0x2000);
102 m_pqTDList =
reinterpret_cast<qTD *
>(virtualBase + 0x3000);
103 m_pQHListPhys = physicalBase;
104 m_pFrameListPhys = physicalBase + 0x2000;
105 m_pqTDListPhys = physicalBase + 0x3000;
107 DoubleWordSet(m_pFrameList, 1, 0x400);
111 #ifdef USB_VERBOSE_DEBUG 112 DEBUG_LOG(
"USB: EHCI: PCI command register: " << (nPciCmdSts & 0xffff));
114 "USB: EHCI: PCI status register: " 115 << ((nPciCmdSts & 0xffff0000) >> 16));
121 m_pBase = m_Addresses[0]->m_Io;
123 "EHCI: Working off: " << (m_Addresses[0]->m_IsIoSpace ?
"P" :
"MM")
125 m_Addresses[0]->map();
127 uint32_t hccapbase = m_pBase->read32(EHCI_CAPLENGTH);
128 uint16_t version = hccapbase >> 16;
130 m_nOpRegsOffset = hccapbase & 0xF;
131 #ifdef USB_VERBOSE_DEBUG 132 NOTICE(
"EHCI operation registers are at offset " << m_nOpRegsOffset);
134 if (m_nOpRegsOffset == 0)
142 "EHCI controller version " << ((version & 0xFF) >> 8) <<
"." 143 << (version & 0xFF));
147 uint32_t hcsparams = m_pBase->read32(EHCI_HCSPARAMS);
148 m_nPorts = hcsparams & 0xF;
149 #ifdef USB_VERBOSE_DEBUG 151 "EHCI controller has " <<
Dec << m_nPorts <<
Hex <<
" physical ports.");
154 uint32_t hccparams = m_pBase->read32(EHCI_HCCPARAMS);
155 uint8_t eecp = (hccparams >> 8) & 0xFF;
156 if (eecp && (eecp < 0x40))
158 ERROR(
"EHCI: EECP pointer is invalid");
162 #ifdef USB_VERBOSE_DEBUG 164 "EHCI: Host controller " << (hccparams & 1 ?
"does" :
"does not")
165 <<
" require 64-bit data structures.");
167 " Host controller " << (hccparams & 2 ?
"does" :
"does not")
168 <<
" allow us to use frame lists with " 169 "anything other than 1024 items in them.");
172 << (hccparams & 4 ?
"does" :
"does not")
173 <<
" support the asynchronous schedule park capability.");
174 DEBUG_LOG(
" HCCAPBASE is " << hccapbase);
175 DEBUG_LOG(
" HCCPARAMS is " << hccparams);
176 DEBUG_LOG(
" HCSPARAMS is " << hcsparams);
184 #ifdef USB_VERBOSE_DEBUG 186 "EHCI: Reading LEGSUP register and checking for BIOS ownership.");
190 uint32_t dwordOffset = eecp /
sizeof(uint32_t);
196 bool bBiosOwned = legsup & (1 << 16);
199 #ifdef USB_VERBOSE_DEBUG 200 DEBUG_LOG(
"EHCI: Performing handoff from BIOS to the OS...");
208 while (legsup & (1 << 16))
212 Time::delay(5 * Time::Multiplier::Millisecond);
216 eecp = (legsup >> 8) & 0xFF;
223 #ifdef USB_VERBOSE_DEBUG 224 DEBUG_LOG(
"USB: EHCI: disabling running schedules");
228 m_pBase->read32(m_nOpRegsOffset + EHCI_CMD) &
229 ~(EHCI_CMD_ASYNCLE | EHCI_CMD_PERIODICLE),
230 m_nOpRegsOffset + EHCI_CMD);
231 while (m_pBase->read32(m_nOpRegsOffset + EHCI_STS) & 0xC000)
232 Time::delay(5 * Time::Multiplier::Millisecond);
234 uint32_t status = m_pBase->read32(m_nOpRegsOffset + EHCI_STS);
235 if (!(status & EHCI_STS_HALTED))
237 #ifdef USB_VERBOSE_DEBUG 238 DEBUG_LOG(
"USB: EHCI: pausing controller");
242 m_pBase->read32(m_nOpRegsOffset + EHCI_CMD) & ~EHCI_CMD_RUN,
243 m_nOpRegsOffset + EHCI_CMD);
244 while (!(m_pBase->read32(m_nOpRegsOffset + EHCI_STS) & EHCI_STS_HALTED))
245 Time::delay(5 * Time::Multiplier::Millisecond);
248 #ifdef USB_VERBOSE_DEBUG 249 DEBUG_LOG(
"USB: EHCI: resetting controller");
252 m_pBase->write32(EHCI_CMD_HCRES, m_nOpRegsOffset + EHCI_CMD);
253 while (m_pBase->read32(m_nOpRegsOffset + EHCI_CMD) & EHCI_CMD_HCRES)
254 Time::delay(5 * Time::Multiplier::Millisecond);
255 #ifdef USB_VERBOSE_DEBUG 257 "USB: EHCI: Reset complete, status: " 258 << m_pBase->read32(m_nOpRegsOffset + EHCI_STS) <<
".");
266 getInterruptNumber(),
this);
268 Machine::instance().getIrqManager()->
control(
269 getInterruptNumber(), IrqManager::MitigationThreshold,
274 m_pBase->write32(0, m_nOpRegsOffset + EHCI_CTRLDSEG);
277 m_pBase->write32(0x3b, m_nOpRegsOffset + EHCI_INTR);
281 m_pBase->write32(m_pFrameListPhys, m_nOpRegsOffset + EHCI_PERIODICLP);
283 Time::delay(5 * Time::Multiplier::Millisecond);
288 QH *pDummyQH = &m_pQHList[0];
289 qTD *pDummyTD = &m_pqTDList[0];
290 ByteSet(pDummyQH, 0,
sizeof(
QH));
291 ByteSet(pDummyTD, 0,
sizeof(
qTD));
294 pDummyTD->bNextInvalid = pDummyTD->bAltNextInvalid = 1;
297 pDummyQH->pNext = m_pQHListPhys >> 5;
298 pDummyQH->nNextType = 1;
300 pDummyQH->pQTD = m_pqTDListPhys >> 5;
306 pDummyQH->pMetaData->pFirstQTD = 0;
307 pDummyQH->pMetaData->pLastQTD = pDummyTD;
308 pDummyQH->pMetaData->pNext = pDummyQH;
309 pDummyQH->pMetaData->pPrev = pDummyQH;
311 MemoryCopy(&pDummyQH->overlay, pDummyTD,
sizeof(
qTD));
313 m_pCurrentQueueHead = m_pCurrentQueueTail = pDummyQH;
317 m_pBase->read32(m_nOpRegsOffset + EHCI_CMD) & ~EHCI_CMD_ASYNCLE,
318 m_nOpRegsOffset + EHCI_CMD);
319 while (m_pBase->read32(m_nOpRegsOffset + EHCI_STS) & 0x8000)
323 m_pBase->write32(m_pQHListPhys, m_nOpRegsOffset + EHCI_ASYNCLP);
327 (m_pBase->read32(m_nOpRegsOffset + EHCI_CMD) & ~0xFF0000) | 0x80000,
328 m_nOpRegsOffset + EHCI_CMD);
332 m_pBase->read32(m_nOpRegsOffset + EHCI_CMD) | EHCI_CMD_RUN,
333 m_nOpRegsOffset + EHCI_CMD);
334 while (m_pBase->read32(m_nOpRegsOffset + EHCI_STS) & EHCI_STS_HALTED)
335 Time::delay(5 * Time::Multiplier::Millisecond);
341 m_pBase->write32(1, m_nOpRegsOffset + EHCI_CFGFLAG);
348 m_pBase->read32(m_nOpRegsOffset + EHCI_CMD) | 0x900,
349 m_nOpRegsOffset + EHCI_CMD);
354 m_pBase->read32(m_nOpRegsOffset + EHCI_CMD) | EHCI_CMD_ASYNCLE,
355 m_nOpRegsOffset + EHCI_CMD);
356 while (!(m_pBase->read32(m_nOpRegsOffset + EHCI_STS) & 0x8000))
357 Time::delay(5 * Time::Multiplier::Millisecond);
360 for (
size_t i = 0; i < m_nPorts; i++)
362 #ifdef USB_VERBOSE_DEBUG 365 <<
Dec << i <<
Hex <<
" - status initially: " 366 << m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + i * 4));
369 if (!(m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + i * 4) &
373 EHCI_PORTSC_PPOW, m_nOpRegsOffset + EHCI_PORTSC + i * 4);
374 Time::delay(20 * Time::Multiplier::Millisecond);
375 #ifdef USB_VERBOSE_DEBUG 378 <<
Dec << i <<
Hex <<
" - status after power-up: " 379 << m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + i * 4));
385 m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + (i * 4)) &
387 m_nOpRegsOffset + EHCI_PORTSC + (i * 4));
388 while (m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + (i * 4)) &
390 Time::delay(5 * Time::Multiplier::Millisecond);
396 m_pBase->write32(EHCI_STS_PORTCH, m_nOpRegsOffset + EHCI_STS);
397 m_pBase->write32(0x3f, m_nOpRegsOffset + EHCI_INTR);
406 static int threadStub(
void *p)
408 Ehci *pEhci =
reinterpret_cast<Ehci *
>(p);
413 void Ehci::doDequeue()
418 for (
size_t i = 1; i < 0x2000 /
sizeof(
QH); i++)
420 if (!m_QHBitmap.test(i))
423 QH *pQH = &m_pQHList[i];
428 #ifdef USB_VERBOSE_DEBUG 430 "Not performing dequeue on QH #" 431 <<
Dec << i <<
Hex <<
" as it's not even initialised.");
437 if (!pQH->pMetaData->bIgnore)
439 #ifdef USB_VERBOSE_DEBUG 441 "Not performing dequeue on QH #" <<
Dec << i <<
Hex 442 <<
" as it's still active.");
448 size_t nQTDIndex = INDEX_FROM_QTD(pQH->pMetaData->pFirstQTD);
451 m_qTDBitmap.clear(nQTDIndex);
453 qTD *pqTD = &m_pqTDList[nQTDIndex];
454 bool shouldBreak = pqTD->bNextInvalid;
456 nQTDIndex = ((pqTD->pNext << 5) & 0xFFF) /
sizeof(
qTD);
458 ByteSet(pqTD, 0,
sizeof(
qTD));
465 delete pQH->pMetaData;
466 ByteSet(pQH, 0,
sizeof(
QH));
468 #ifdef USB_VERBOSE_DEBUG 480 void Ehci::interrupt(
size_t number, InterruptState &state)
496 uint32_t nStatus = m_pBase->read32(m_nOpRegsOffset + EHCI_STS) &
497 m_pBase->read32(m_nOpRegsOffset + EHCI_INTR);
501 WARNING_NOLOCK(
"EHCI: unwanted IRQ?");
510 m_pBase->write32(nStatus, m_nOpRegsOffset + EHCI_STS);
514 NOTICE_NOLOCK(
"EHCI: Unusual IRQ, status is " << nStatus);
517 #ifdef USB_VERBOSE_DEBUG 518 DEBUG_LOG_NOLOCK(
"EHCI IRQ " << nStatus);
520 if (nStatus & EHCI_STS_PORTCH)
522 for (
size_t i = 0; i < m_nPorts; i++)
524 if (m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + i * 4) &
528 m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + i * 4),
529 m_nOpRegsOffset + EHCI_PORTSC + i * 4);
531 if (!m_IgnoredPorts.test(i))
532 addAsyncRequest(0, i);
540 if (nStatus & (EHCI_STS_INT | EHCI_STS_ERR))
542 for (
size_t i = 1; i < 128; i++)
544 if (!m_QHBitmap.test(i))
547 QH *pQH = &m_pQHList[i];
551 if (!(pQH->pMetaData->pPrev &&
552 pQH->pMetaData->pNext))
554 if (pQH->pMetaData->bIgnore)
556 if (!(pQH->pMetaData->pFirstQTD && pQH->pMetaData->pLastQTD))
559 bool bPeriodic = pQH->pMetaData->bPeriodic;
561 size_t nQTDIndex = INDEX_FROM_QTD(pQH->pMetaData->pFirstQTD);
564 qTD *pqTD = &m_pqTDList[nQTDIndex];
566 if (pqTD->nStatus != 0x80)
569 if ((pqTD->nStatus & 0x7c) || (nStatus & EHCI_STS_ERR))
571 #ifdef USB_VERBOSE_DEBUG 573 ((nStatus & EHCI_STS_ERR) ?
"USB" :
"qTD")
576 "qTD Status: " << pqTD->nStatus
577 <<
" [overlay status=" 578 << pQH->overlay.nStatus <<
"]");
580 "qTD Error Counter: " << pqTD->nErr
581 <<
" [overlay counter=" 582 << pQH->overlay.nErr <<
"]");
584 "QH NAK counter: " << pqTD->res1
585 <<
" [overlay count=" 586 << pQH->overlay.res1 <<
"]");
587 ERROR_NOLOCK(
"qTD PID: " << pqTD->nPid <<
".");
589 nResult = -pqTD->getError();
593 nResult = pqTD->nBufferSize - pqTD->nBytes;
594 pQH->pMetaData->nTotalBytes += nResult;
596 #ifdef USB_VERBOSE_DEBUG 598 "qTD #" <<
Dec << nQTDIndex <<
Hex <<
" [from QH #" 600 << pQH->nAddress <<
":" << pQH->nEndpoint <<
" " 601 << (pqTD->nPid == 0 ?
605 (pqTD->nPid == 2 ?
"SETUP" :
"")))
606 <<
" " << nResult <<
Hex);
610 if ((nResult < 0) || (pqTD == pQH->pMetaData->pLastQTD))
613 if (pQH->pMetaData->pCallback)
614 pQH->pMetaData->pCallback(
615 pQH->pMetaData->pParam,
616 nResult < 0 ? nResult :
617 pQH->pMetaData->nTotalBytes);
622 m_QueueListChangeLock
627 pQH->pMetaData->pNext->hrcl =
632 QH *pPrev = pQH->pMetaData->pPrev;
633 QH *pNext = pQH->pMetaData->pNext;
636 pPrev->pMetaData->pNext = pNext;
637 pNext->pMetaData->pPrev = pPrev;
640 pPrev->pNext = pQH->pNext;
643 if (pQH == m_pCurrentQueueTail)
645 m_pCurrentQueueTail = pPrev;
652 m_pBase->read32(m_nOpRegsOffset + EHCI_CMD);
654 cmdReg | (1 << 6), m_nOpRegsOffset + EHCI_CMD);
657 pQH->pMetaData->bIgnore =
true;
659 m_QueueListChangeLock.release();
665 pqTD->nStatus = 0x80;
666 pqTD->nBytes = pqTD->nBufferSize;
675 MemoryCopy(&pQH->overlay, pqTD,
sizeof(
qTD));
679 size_t oldIndex = nQTDIndex;
681 if (pqTD->bNextInvalid)
684 nQTDIndex = ((pqTD->pNext << 5) & 0xFFF) /
sizeof(
qTD);
686 if (nQTDIndex == oldIndex)
691 <<
"'s qTD list is invalid - circular reference!");
694 else if (pqTD->pNext == 0)
697 "EHCI: QH #" <<
Dec << i <<
Hex 698 <<
"'s qTD list is invalid - null pNext " 699 "pointer (and T bit not set)!");
706 if (nStatus & EHCI_STS_ASYNCADVANCE)
710 threadStub, reinterpret_cast<void *>(
this));
720 uintptr_t nTransaction,
bool bToggle, UsbPid pid, uintptr_t pBuffer,
727 nIndex = m_qTDBitmap.getFirstClear();
728 if (nIndex >= (0x1000 /
sizeof(
qTD)))
730 ERROR(
"USB: EHCI: qTD space full");
733 m_qTDBitmap.set(nIndex);
737 qTD *pqTD = &m_pqTDList[nIndex];
738 ByteSet(pqTD, 0,
sizeof(
qTD));
741 pqTD->bNextInvalid = 1;
742 pqTD->bAltNextInvalid = 1;
761 pqTD->nStatus = 0x80;
766 pqTD->nBytes = nBytes;
767 pqTD->nBufferSize = nBytes;
768 pqTD->bDataToggle = bToggle;
773 uintptr_t nBufferPageOffset = pBuffer & 0xFFF,
774 pBufferPageStart = pBuffer & ~0xFFF;
775 pqTD->nOffset = nBufferPageOffset;
777 if (nBufferPageOffset + nBytes >= 0x5000)
779 ERROR(
"EHCI: addTransferToTransaction: Too many bytes for a single " 786 GET_PAGE(pqTD->pPage0, 0, nIndex);
787 GET_PAGE(pqTD->pPage1, 1, nIndex);
788 GET_PAGE(pqTD->pPage2, 2, nIndex);
789 GET_PAGE(pqTD->pPage3, 3, nIndex);
790 GET_PAGE(pqTD->pPage4, 4, nIndex);
794 QH *pQH = &m_pQHList[nTransaction];
795 if (pQH->pMetaData->pLastQTD)
797 pQH->pMetaData->pLastQTD->pNext = PHYS_QTD(nIndex) >> 5;
798 pQH->pMetaData->pLastQTD->bNextInvalid = 0;
800 if (pQH->pMetaData->pLastQTD == pQH->pMetaData->pFirstQTD)
802 pQH->overlay.pNext = pQH->pMetaData->pLastQTD->pNext;
803 pQH->overlay.bNextInvalid = pQH->pMetaData->pLastQTD->bNextInvalid;
808 pQH->pMetaData->pFirstQTD = pqTD;
809 pQH->pQTD = PHYS_QTD(nIndex) >> 5;
810 MemoryCopy(&pQH->overlay, pqTD,
sizeof(
qTD));
812 pQH->pMetaData->pLastQTD = pqTD;
821 nIndex = m_QHBitmap.getFirstClear();
822 if (nIndex >= (0x2000 /
sizeof(
QH)))
824 ERROR(
"USB: EHCI: QH space full");
825 return static_cast<uintptr_t
>(-1);
827 m_QHBitmap.set(nIndex);
830 QH *pQH = &m_pQHList[nIndex];
831 ByteSet(pQH, 0,
sizeof(
QH));
837 pQH->nNakReload = 15;
844 endpointInfo.speed != HighSpeed ? endpointInfo.nHubAddress : 0;
845 pQH->nHubPort = endpointInfo.speed != HighSpeed ? endpointInfo.nHubPort : 0;
846 pQH->bControlEndpoint =
847 (endpointInfo.speed != HighSpeed) && !endpointInfo.nEndpoint;
850 pQH->bDataToggleSrc = 1;
853 pQH->nAddress = endpointInfo.nAddress;
854 pQH->nSpeed = endpointInfo.speed;
857 pQH->nEndpoint = endpointInfo.nEndpoint;
858 pQH->nMaxPacketSize = endpointInfo.nMaxPacketSize;
866 pMetaData->bPeriodic =
false;
867 pMetaData->pFirstQTD = 0;
868 pMetaData->pLastQTD = 0;
869 pMetaData->pNext = 0;
870 pMetaData->pPrev = 0;
871 pMetaData->bIgnore =
false;
872 pMetaData->nTotalBytes = 0;
874 pQH->pMetaData = pMetaData;
881 uintptr_t nTransaction,
void (*pCallback)(uintptr_t, ssize_t),
885 if ((nTransaction == static_cast<uintptr_t>(-1)) ||
886 !m_QHBitmap.test(nTransaction))
889 "EHCI: doAsync: didn't get a valid transaction id [" << nTransaction
894 QH *pQH = &m_pQHList[nTransaction];
895 pQH->pMetaData->pCallback = pCallback;
896 pQH->pMetaData->pParam = pParam;
897 pQH->pMetaData->pLastQTD->bIoc = 1;
900 if (pQH->pMetaData->pFirstQTD == pQH->pMetaData->pLastQTD)
903 pQH->overlay.bIoc = 1;
906 #ifdef USB_VERBOSE_DEBUG 908 "START #" <<
Dec << nTransaction <<
Hex <<
" " <<
Dec << pQH->nAddress
909 <<
":" << pQH->nEndpoint <<
Hex);
913 if (m_pCurrentQueueTail)
921 size_t queueHeadIndex =
922 (
reinterpret_cast<uintptr_t
>(m_pCurrentQueueHead) & 0xFFF) /
924 pQH->pNext = (m_pQHListPhys + (queueHeadIndex *
sizeof(
QH))) >> 5;
927 pQH->pMetaData->pNext = m_pCurrentQueueHead;
928 pQH->pMetaData->pPrev = m_pCurrentQueueTail;
930 QH *pOldTail = m_pCurrentQueueTail;
938 m_pCurrentQueueTail = pQH;
942 (m_pQHListPhys + (nTransaction *
sizeof(
QH))) >> 5;
943 pOldTail->nNextType = 1;
946 pOldTail->pMetaData->pNext = pQH;
950 m_pCurrentQueueHead->hrcl = 1;
954 ERROR(
"EHCI: Queue tail is null!");
959 UsbEndpoint endpointInfo, uintptr_t pBuffer, uint16_t nBytes,
960 void (*pCallback)(uintptr_t, ssize_t), uintptr_t pParam)
965 size_t nFrameIndex = m_FrameBitmap.getFirstClear();
966 if (nFrameIndex >= 1024)
968 ERROR(
"USB: EHCI: Frame list full");
971 m_FrameBitmap.set(nFrameIndex);
974 uintptr_t nTransaction = createTransaction(endpointInfo);
977 QH *pQH = &m_pQHList[nTransaction];
978 pQH->pMetaData->bPeriodic =
true;
981 addTransferToTransaction(nTransaction,
false, UsbPidIn, pBuffer, nBytes);
982 if (!pQH->pMetaData->pLastQTD)
984 ERROR(
"USB: EHCI: Couldn't add transfer to transaction!");
989 qTD *pqTD = pQH->pMetaData->pLastQTD;
993 m_pFrameList[nFrameIndex] = (m_pQHListPhys + nTransaction *
sizeof(
QH)) | 2;
999 for (retry = 0; retry < 3; retry++)
1001 #ifdef USB_VERBOSE_DEBUG 1004 <<
Dec << nPort <<
Hex <<
" - status before reset: " 1005 << m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + (nPort * 4)));
1010 m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + (nPort * 4)) |
1012 m_nOpRegsOffset + EHCI_PORTSC + (nPort * 4));
1014 Time::delay(50 * Time::Multiplier::Millisecond);
1018 m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + (nPort * 4)) &
1020 m_nOpRegsOffset + EHCI_PORTSC + (nPort * 4));
1023 while (m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + (nPort * 4)) &
1025 Time::delay(5 * Time::Multiplier::Millisecond);
1027 #ifdef USB_VERBOSE_DEBUG 1030 <<
Dec << nPort <<
Hex <<
" - status after reset: " 1031 << m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + (nPort * 4)));
1034 if ((m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + (nPort * 4)) &
1036 (m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + (nPort * 4)) &
1040 "USB: EHCI: Port " <<
Dec << nPort <<
Hex <<
" is connected");
1046 "USB: EHCI: Port " <<
Dec << nPort <<
Hex 1047 <<
" seems to be not HighSpeed. Returning " 1048 "to companion controllers.");
1050 m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + (nPort * 4)) |
1052 m_nOpRegsOffset + EHCI_PORTSC + (nPort * 4));
1056 WARNING(
"EHCI: Port " <<
Dec << nPort <<
Hex <<
" could not be connected");
1062 uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t p5,
1063 uint64_t p6, uint64_t p7, uint64_t p8)
1066 if (m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + p1 * 4) &
1070 if (!deviceConnected(p1, HighSpeed))
1074 <<
" appeared to be connected but could not be set up");
1078 DEBUG_LOG(
"USB: EHCI: Port " <<
Dec << p1 <<
Hex <<
" is disconnected");
1080 deviceDisconnected(p1);
1084 m_pBase->read32(m_nOpRegsOffset + EHCI_PORTSC + p1 * 4),
1085 m_nOpRegsOffset + EHCI_PORTSC + p1 * 4);
virtual bool registerInterruptHandler(size_t nInterruptNumber, InterruptHandler *pHandler)=0
virtual void doAsync(uintptr_t pTransaction, void(*pCallback)(uintptr_t, ssize_t)=0, uintptr_t pParam=0)
static PhysicalMemoryManager & instance()
static const size_t continuous
virtual void addTransferToTransaction(uintptr_t pTransaction, bool bToggle, UsbPid pid, uintptr_t pBuffer, size_t nBytes)
Adds a new transfer to an existent transaction.
static ProcessorInformation & information()
virtual bool portReset(uint8_t nPort, bool bErrorResponse=false)
Gets a UsbDevice from a given vendor:product pair.
static const size_t Write
virtual void addInterruptInHandler(UsbEndpoint endpointInfo, uintptr_t pBuffer, uint16_t nBytes, void(*pCallback)(uintptr_t, ssize_t), uintptr_t pParam=0)
Adds a new handler for an interrupt IN transaction.
static const size_t KernelMode
uint32_t readConfigSpace(Device *pDev, uint8_t offset)
virtual uintptr_t createTransaction(UsbEndpoint endpointInfo)
Creates a new transaction with the given endpoint data.
bool initialiseController()
virtual irq_id_t registerPciIrqHandler(IrqHandler *handler, Device *pDevice)=0
virtual bool control(uint8_t irq, ControlCode code, size_t argument)
static InterruptManager & instance()
virtual bool irq(irq_id_t number, InterruptState &state)
IRQ handler.
virtual uint64_t executeRequest(uint64_t p1=0, uint64_t p2=0, uint64_t p3=0, uint64_t p4=0, uint64_t p5=0, uint64_t p6=0, uint64_t p7=0, uint64_t p8=0)
void writeConfigSpace(Device *pDev, uint8_t offset, uint32_t data)