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/processor/IoBase.h" 33 #include "pedigree/kernel/processor/MemoryRegion.h" 34 #include "pedigree/kernel/processor/PhysicalMemoryManager.h" 35 #include "pedigree/kernel/processor/Processor.h" 36 #include "pedigree/kernel/processor/ProcessorInformation.h" 37 #include "pedigree/kernel/processor/VirtualAddressSpace.h" 38 #include "pedigree/kernel/processor/state_forward.h" 39 #include "pedigree/kernel/processor/types.h" 40 #include "pedigree/kernel/time/Time.h" 41 #include "pedigree/kernel/utilities/ExtensibleBitmap.h" 42 #include "pedigree/kernel/utilities/Iterator.h" 43 #include "pedigree/kernel/utilities/List.h" 44 #include "pedigree/kernel/utilities/RequestQueue.h" 45 #include "pedigree/kernel/utilities/String.h" 46 #include "pedigree/kernel/utilities/Vector.h" 47 #include "pedigree/kernel/utilities/utility.h" 49 #define INDEX_FROM_TD(ptr) \ 50 (((reinterpret_cast<uintptr_t>((ptr)) & 0xFFF) / sizeof(TD))) 51 #define PHYS_TD(idx) (m_pTDListPhys + ((idx) * sizeof(TD))) 55 m_ScheduleChangeLock(), m_PeriodicListChangeLock(),
56 m_ControlListChangeLock(), m_BulkListChangeLock(), m_PeriodicEDBitmap(),
57 m_ControlEDBitmap(), m_BulkEDBitmap(), m_pBulkQueueHead(0),
58 m_pControlQueueHead(0), m_pBulkQueueTail(0), m_pControlQueueTail(0),
59 m_pPeriodicQueueTail(0), m_DequeueListLock(), m_DequeueList(),
60 m_DequeueCount(0), m_OhciMR(
"Ohci-MR")
62 setSpecificType(
String(
"OHCI"));
69 ERROR(
"USB: OHCI: Couldn't allocate memory region!");
73 uintptr_t virtualBase =
74 reinterpret_cast<uintptr_t
>(m_OhciMR.virtualAddress());
75 uintptr_t physicalBase = m_OhciMR.physicalAddress();
77 m_pHcca =
reinterpret_cast<Hcca *
>(virtualBase);
78 m_pBulkEDList =
reinterpret_cast<ED *
>(virtualBase + 0x1000);
79 m_pControlEDList =
reinterpret_cast<ED *
>(virtualBase + 0x2000);
80 m_pPeriodicEDList =
reinterpret_cast<ED *
>(virtualBase + 0x3000);
81 m_pTDList =
reinterpret_cast<TD *
>(virtualBase + 0x4000);
83 m_pHccaPhys = physicalBase;
84 m_pBulkEDListPhys = physicalBase + 0x1000;
85 m_pControlEDListPhys = physicalBase + 0x2000;
86 m_pPeriodicEDListPhys = physicalBase + 0x3000;
87 m_pTDListPhys = physicalBase + 0x4000;
90 ByteSet(m_pHcca, 0, 0x800);
93 m_PeriodicEDBitmap.set(0);
94 ED *pPeriodicED = m_pPeriodicEDList;
95 ByteSet(pPeriodicED, 0,
sizeof(ED));
96 pPeriodicED->bSkip =
true;
97 pPeriodicED->pMetaData =
new ED::MetaData;
98 pPeriodicED->pMetaData->id = 0x2000;
99 pPeriodicED->pMetaData->pPrev = pPeriodicED->pMetaData->pNext = pPeriodicED;
102 DoubleWordSet(m_pHcca->pInterruptEDList, m_pPeriodicEDListPhys, 3);
105 m_pPeriodicQueueTail = pPeriodicED;
107 m_pBulkQueueTail = m_pBulkQueueHead = 0;
108 m_pControlQueueTail = m_pControlQueueHead = 0;
117 m_pBase = m_Addresses[0]->m_Io;
118 m_Addresses[0]->map();
121 uint8_t version = m_pBase->read32(OhciVersion) & 0xFF;
123 "USB: OHCI: starting up - controller is version " 124 <<
Dec << ((version & 0xF0) >> 4) <<
"." << (version & 0xF) <<
Hex 128 uint32_t control = m_pBase->read32(OhciControl);
129 if (control & OhciControlInterruptRoute)
132 DEBUG_LOG(
"USB: OHCI: currently in SMM!");
133 uint32_t status = m_pBase->read32(OhciCommandStatus);
135 status | OhciCommandRequestOwnership, OhciCommandStatus);
136 while ((control = m_pBase->read32(OhciControl)) &
137 OhciControlInterruptRoute)
138 Time::delay(1 * Time::Multiplier::Millisecond);
143 if (control & OhciControlStateFunctionalMask)
144 DEBUG_LOG(
"USB: OHCI: BIOS is currently in charge.");
146 DEBUG_LOG(
"USB: OHCI: not yet operational.");
149 if (!(control & OhciControlStateRunning))
150 m_pBase->write32(OhciControlStateRunning, OhciControl);
154 m_pBase->write32(control & ~OhciControlStateFunctionalMask, OhciControl);
155 Time::delay(200 * Time::Multiplier::Millisecond);
158 uint32_t interval = m_pBase->read32(OhciFmInterval);
161 m_pBase->write32(OhciCommandHcReset, OhciCommandStatus);
162 while (m_pBase->read32(OhciCommandStatus) & OhciCommandHcReset)
163 Time::delay(5 * Time::Multiplier::Millisecond);
169 m_pBase->write32(m_pHccaPhys, OhciHcca);
172 m_pBase->write32(m_pControlEDListPhys, OhciControlHeadED);
173 m_pBase->write32(m_pBulkEDListPhys, OhciBulkHeadED);
176 m_pBase->write32(0x4000007F, OhciInterruptDisable);
178 OhciInterruptMIE | OhciInterruptWbDoneHead | 0x1 | 0x10 | 0x20,
179 OhciInterruptEnable);
182 control = m_pBase->read32(OhciControl);
184 ~(0x3 | 0x3C | OhciControlStateFunctionalMask |
185 OhciControlInterruptRoute);
186 control |= OhciControlListsEnable | OhciControlStateRunning |
188 m_pBase->write32(control, OhciControl);
193 m_pBase->write32(interval | (1U << 31U), OhciFmInterval);
196 "USB: OHCI: maximum packet size is " << ((interval >> 16) & 0xEFFF));
199 m_pBase->write32(0x10000, OhciRhStatus);
211 Machine::instance().getIrqManager()->
control(
212 getInterruptNumber(), IrqManager::MitigationThreshold,
221 uint32_t rhDescA = m_pBase->read32(OhciRhDescriptorA);
222 uint8_t powerWait = ((rhDescA >> 24) & 0xFF) * 2;
223 m_nPorts = rhDescA & 0xFF;
226 "USB: OHCI: Reset complete, " <<
Dec << m_nPorts <<
Hex 227 <<
" ports available");
229 for (
size_t i = 0; i < m_nPorts; i++)
231 if (!(m_pBase->read32(OhciRhPortStatus + (i * 4)) & OhciRhPortStsPower))
233 DEBUG_LOG(
"USB: OHCI: applying power to port " << i);
236 m_pBase->write32(OhciRhPortStsPower, OhciRhPortStatus + (i * 4));
239 Time::delay(powerWait * Time::Multiplier::Millisecond);
242 DEBUG_LOG(
"OHCI: Determining if there's a device on this port");
245 if (m_pBase->read32(OhciRhPortStatus + (i * 4)) &
246 OhciRhPortStsConnected)
251 m_pBase->write32(OhciInterruptRhStsChange, OhciInterruptStatus);
253 OhciInterruptMIE | OhciInterruptRhStsChange | OhciInterruptWbDoneHead,
254 OhciInterruptEnable);
265 if (!pED || !pED->pMetaData)
268 #ifdef USB_VERBOSE_DEBUG 270 "OHCI: removing ED #" 271 << pED->pMetaData->id
272 <<
" from the schedule to prepare for reclamation");
279 ED *pPrev = pED->pMetaData->pPrev;
280 ED *pNext = pED->pMetaData->pNext;
285 if (pED->pMetaData->edType == ControlList)
287 pQueueHead = &m_pControlQueueHead;
288 pQueueTail = &m_pControlQueueTail;
290 else if (pED->pMetaData->edType == BulkList)
292 pQueueHead = &m_pBulkQueueHead;
293 pQueueTail = &m_pBulkQueueTail;
297 ERROR(
"OHCI: ED #" << pED->pMetaData->id <<
" has an invalid type!");
301 bool bControl = pED->pMetaData->edType == ControlList;
304 if (pED == *pQueueHead)
306 #ifdef USB_VERBOSE_DEBUG 307 DEBUG_LOG(
"OHCI: ED was a queue head, adjusting controller state " 314 m_pBase->write32(vtp_ed(pNext), OhciControlHeadED);
316 m_pBase->write32(vtp_ed(pNext), OhciBulkHeadED);
320 pPrev->pNext = pED->pNext;
324 if (pED == *pQueueTail)
331 pPrev->pMetaData->pNext = pNext;
333 pNext->pMetaData->pPrev = pPrev;
336 if (pED->pMetaData->completedTdList.
count())
339 it != pED->pMetaData->completedTdList.
end(); it++)
341 size_t idx = (*it)->id;
342 ByteSet((*it), 0,
sizeof(
TD));
343 m_TDBitmap.clear(idx);
349 if (pED->pMetaData->tdList.
count())
352 it != pED->pMetaData->completedTdList.
end(); it++)
354 size_t idx = (*it)->id;
355 ByteSet((*it), 0,
sizeof(
TD));
356 m_TDBitmap.clear(idx);
361 stop(pED->pMetaData->edType);
366 m_DequeueList.pushBack(pED);
371 m_pBase->write32(OhciInterruptStartOfFrame, OhciInterruptStatus);
372 m_pBase->write32(OhciInterruptStartOfFrame, OhciInterruptEnable);
378 void Ohci::interrupt(
size_t number, InterruptState &state)
391 uint32_t nStatus = 0;
394 if (m_pHcca->pDoneHead)
397 nStatus = OhciInterruptWbDoneHead;
398 if (m_pHcca->pDoneHead & 0x1)
399 nStatus |= m_pBase->read32(OhciInterruptStatus) &
400 m_pBase->read32(OhciInterruptEnable);
404 nStatus = m_pBase->read32(OhciInterruptStatus) &
405 m_pBase->read32(OhciInterruptEnable);
411 DEBUG_LOG(
"USB: OHCI: irq is not for us");
420 m_pBase->write32(OhciInterruptMIE, OhciInterruptDisable);
423 nStatus &= ~OhciInterruptMIE;
425 #ifdef USB_VERBOSE_DEBUG 429 if (nStatus & OhciInterruptUnrecoverableError)
434 ERROR(
"OHCI: controller is hung!");
442 if (nStatus & OhciInterruptStartOfFrame)
446 #ifdef USB_VERBOSE_DEBUG 447 DEBUG_LOG(
"OHCI: SOF, preparing to reclaim EDs...");
451 m_pBase->write32(OhciInterruptStartOfFrame, OhciInterruptDisable);
457 if (!m_DequeueList.count())
460 pED = m_DequeueList.popFront();
463 size_t id = pED->pMetaData->id & 0xFFF;
464 Lists type = pED->pMetaData->edType;
466 #ifdef USB_VERBOSE_DEBUG 467 DEBUG_LOG(
"OHCI: freeing ED #" << pED->pMetaData->id <<
".");
471 delete pED->pMetaData;
472 ByteSet(pED, 0,
sizeof(
ED));
477 m_ControlEDBitmap.clear(
id);
480 m_BulkEDBitmap.clear(
id);
483 WARNING(
"periodic: not actually clearing bit");
486 case IsochronousList:
487 DEBUG_LOG(
"USB: OHCI: dequeue on an isochronous ED, " 488 "but we don't support them yet.");
500 if (nStatus & OhciInterruptRhStsChange)
501 for (
size_t i = 0; i < m_nPorts; i++)
502 if (m_pBase->read32(OhciRhPortStatus + (i * 4)) &
503 OhciRhPortStsConnStsCh)
504 addAsyncRequest(0, i);
510 if (nStatus & OhciInterruptWbDoneHead)
517 if (m_FullSchedule.count())
518 pED = m_FullSchedule.popFront();
524 if (pED->pMetaData->bIgnore)
530 bool bPeriodic = pED->pMetaData->bPeriodic;
534 while (pED->pMetaData->tdList.
count())
536 pTD = pED->pMetaData->tdList.
popFront();
540 if (pTD->nStatus == 0xF)
549 #ifdef USB_VERBOSE_DEBUG 551 ERROR_NOLOCK(
"TD Error " <<
Dec << pTD->nStatus <<
Hex);
553 nResult = -pTD->getError();
557 if (pTD->pBufferStart)
561 pTD->pBufferEnd - pTD->pBufferStart + 1;
562 nResult = pTD->nBufferSize - nBytesLeft;
565 nResult = pTD->nBufferSize;
566 pED->pMetaData->nTotalBytes += nResult;
568 #ifdef USB_VERBOSE_DEBUG 570 "TD #" <<
Dec << pTD->id <<
Hex <<
" [from ED #" <<
Dec 571 << pED->pMetaData->id <<
Hex <<
"] DONE: " <<
Dec 572 << pED->nAddress <<
":" << pED->nEndpoint <<
" " 577 (pTD->nPid == 0 ?
"SETUP" :
"")))
578 <<
" " << nResult <<
Hex);
582 bool bEndOfTransfer =
584 ((nResult < 0) || (pTD == pED->pMetaData->pLastTD))) ||
585 (bPeriodic && (nResult >= 0));
588 pED->pMetaData->completedTdList.
pushBack(pTD);
595 if (pED->pMetaData->pCallback)
597 pED->pMetaData->pCallback(
598 pED->pMetaData->pParam,
599 nResult < 0 ? nResult :
600 pED->pMetaData->nTotalBytes);
611 pTD->bDataToggle = !pTD->bDataToggle;
615 pED->pMetaData->nTotalBytes = 0;
623 pTD->pBufferStart = pTD->pBufferEnd - pTD->nBufferSize + 1;
624 pED->pHeadTD = PHYS_TD(pTD->id) >> 4;
626 pED->pMetaData->tdList.
pushBack(pTD);
633 if (!pED->pMetaData->bIgnore)
639 if (persistList.
count())
643 it != persistList.
end();)
645 m_FullSchedule.pushBack(*it);
646 it = persistList.
erase(it);
651 m_pBase->write32(nStatus, OhciInterruptStatus);
654 m_pBase->write32(OhciInterruptMIE, OhciInterruptEnable);
662 uintptr_t pTransaction,
bool bToggle, UsbPid pid, uintptr_t pBuffer,
669 nIndex = m_TDBitmap.getFirstClear();
670 if (nIndex >= (0x1000 /
sizeof(
TD)))
672 ERROR(
"USB: OHCI: TD space full");
675 m_TDBitmap.set(nIndex);
679 TD *pTD = &m_pTDList[nIndex];
680 ByteSet(pTD, 0,
sizeof(
TD));
684 pTD->bBuffRounding = 1;
710 if (va.
isMapped(reinterpret_cast<void *>(pBuffer)))
712 physical_uintptr_t phys = 0;
714 va.
getMapping(reinterpret_cast<void *>(pBuffer), phys, flags);
715 pTD->pBufferStart = phys + (pBuffer & 0xFFF);
716 pTD->pBufferEnd = pTD->pBufferStart + nBytes - 1;
721 "OHCI: addTransferToTransaction: Buffer (page " 722 <<
Dec << pBuffer <<
Hex <<
") isn't mapped!");
723 m_TDBitmap.clear(nIndex);
727 pTD->nBufferSize = nBytes;
735 size_t transactionType = (pTransaction & 0x3000) >> 12;
736 uintptr_t edOffset = pTransaction & 0xFFF;
739 switch (transactionType)
742 pED = &m_pControlEDList[edOffset];
745 pED = &m_pBulkEDList[edOffset];
748 pED = &m_pPeriodicEDList[edOffset];
757 ERROR(
"USB: OHCI: transaction " << pTransaction <<
" is invalid.");
762 if (pED->pMetaData->pLastTD)
764 pED->pMetaData->pLastTD->pNext = PHYS_TD(nIndex) >> 4;
765 pED->pMetaData->pLastTD->nNextTDIndex = nIndex;
766 pED->pMetaData->pLastTD->bLast =
false;
770 pED->pMetaData->pFirstTD = pTD;
771 pED->pHeadTD = PHYS_TD(nIndex) >> 4;
773 pED->pMetaData->pLastTD = pTD;
775 pED->pMetaData->tdList.
pushBack(pTD);
781 bool bIsBulk = endpointInfo.nEndpoint > 0;
790 nIndex = m_BulkEDBitmap.getFirstClear();
792 nIndex = m_ControlEDBitmap.getFirstClear();
794 if (nIndex >= (0x1000 /
sizeof(
ED)))
796 ERROR(
"USB: OHCI: ED space full");
797 return static_cast<uintptr_t
>(-1);
802 m_BulkEDBitmap.set(nIndex);
803 pED = &m_pBulkEDList[nIndex];
808 m_ControlEDBitmap.set(nIndex);
809 pED = &m_pControlEDList[nIndex];
813 ByteSet(pED, 0,
sizeof(
ED));
816 pED->nAddress = endpointInfo.nAddress;
817 pED->nEndpoint = endpointInfo.nEndpoint;
818 pED->bLoSpeed = endpointInfo.speed == LowSpeed;
821 pED->nMaxPacketSize = endpointInfo.nMaxPacketSize;
828 pED->pMetaData->endpointInfo = endpointInfo;
829 pED->pMetaData->id = nIndex;
830 pED->pMetaData->bIgnore =
true;
831 pED->pMetaData->edType = bIsBulk ? BulkList : ControlList;
832 pED->pMetaData->bPeriodic =
false;
833 pED->pMetaData->pFirstTD = pED->pMetaData->pLastTD = 0;
834 pED->pMetaData->nTotalBytes = 0;
835 pED->pMetaData->pPrev = pED->pMetaData->pNext = 0;
836 pED->pMetaData->bLinked =
false;
843 uintptr_t pTransaction,
void (*pCallback)(uintptr_t, ssize_t),
848 size_t transactionType = (pTransaction & 0x3000) >> 12;
849 uintptr_t edOffset = pTransaction & 0xFFF;
858 if (transactionType == 0)
859 bValid = m_ControlEDBitmap.test(edOffset);
860 else if (transactionType == 1)
861 bValid = m_BulkEDBitmap.test(edOffset);
863 if ((pTransaction == static_cast<uintptr_t>(-1)) || !bValid)
866 "OHCI: doAsync: didn't get a valid transaction id [" 867 << pTransaction <<
", " << edOffset <<
"].");
871 if (transactionType == 0)
873 pED = &m_pControlEDList[edOffset];
874 pLock = &m_ControlListChangeLock;
876 else if (transactionType == 1)
878 pED = &m_pBulkEDList[edOffset];
879 pLock = &m_BulkListChangeLock;
884 "OHCI: doAsync: only control and bulk transactions supported");
890 pED->pMetaData->pCallback = pCallback;
891 pED->pMetaData->pParam = pParam;
893 bool bControl = !pED->pMetaData->endpointInfo.nEndpoint;
907 if (!m_pControlQueueHead)
909 #ifdef USB_VERBOSE_DEBUG 910 DEBUG_LOG(
"OHCI: ED is now the control queue head.");
912 m_pControlQueueHead = pED;
917 if (!m_pBulkQueueHead)
919 #ifdef USB_VERBOSE_DEBUG 920 DEBUG_LOG(
"OHCI: ED is now the control queue head.");
922 m_pBulkQueueHead = pED;
928 physical_uintptr_t queueHeadPhys = 0;
931 pQueueHead = m_pControlQueueHead;
932 queueHeadPhys = vtp_ed(pQueueHead);
936 pQueueHead = m_pBulkQueueHead;
937 queueHeadPhys = vtp_ed(pQueueHead);
941 if (queueHeadPhys == vtp_ed(pED))
945 #ifdef USB_VERBOSE_DEBUG 947 "OHCI: new control queue head is " 948 << queueHeadPhys <<
" compared to " 949 << m_pBase->read32(OhciControlHeadED));
951 "OHCI: current control queue ED is " 952 << m_pBase->read32(OhciControlCurrentED));
954 m_pBase->write32(queueHeadPhys, OhciControlHeadED);
958 #ifdef USB_VERBOSE_DEBUG 959 DEBUG_LOG(
"OHCI: new bulk queue head is " << queueHeadPhys);
961 m_pBase->write32(queueHeadPhys, OhciBulkHeadED);
969 pTail = m_pControlQueueTail;
970 m_pControlQueueTail = pED;
974 pTail = m_pBulkQueueTail;
975 m_pBulkQueueTail = pED;
981 pTail->pNext = vtp_ed(pED) >> 4;
982 pTail->pMetaData->pNext = pED;
986 pED->pMetaData->pNext = 0;
987 pED->pMetaData->pPrev = pTail;
988 pQueueHead->pMetaData->pPrev = 0;
991 pED->bSkip = pED->pMetaData->bIgnore =
false;
992 pED->pMetaData->bLinked =
true;
998 m_ScheduleChangeLock.acquire();
999 m_FullSchedule.pushBack(pED);
1000 m_ScheduleChangeLock.release();
1003 start(pED->pMetaData->edType);
1008 uint32_t status = m_pBase->read32(OhciCommandStatus);
1010 bControl ? OhciCommandControlListFilled : OhciCommandBulkListFilled;
1011 m_pBase->write32(status, OhciCommandStatus);
1015 UsbEndpoint endpointInfo, uintptr_t pBuffer, uint16_t nBytes,
1016 void (*pCallback)(uintptr_t, ssize_t), uintptr_t pParam)
1024 nIndex = m_PeriodicEDBitmap.getFirstClear();
1025 if (nIndex >= (0x1000 /
sizeof(
ED)))
1027 ERROR(
"USB: OHCI: ED space full");
1031 m_PeriodicEDBitmap.set(nIndex);
1032 pED = &m_pPeriodicEDList[nIndex];
1038 ByteSet(pED, 0,
sizeof(
ED));
1041 pED->nAddress = endpointInfo.nAddress;
1042 pED->nEndpoint = endpointInfo.nEndpoint;
1043 pED->bLoSpeed = endpointInfo.speed == LowSpeed;
1046 pED->nMaxPacketSize = endpointInfo.nMaxPacketSize;
1053 pED->pMetaData->endpointInfo = endpointInfo;
1054 pED->pMetaData->id = nIndex;
1055 pED->pMetaData->bIgnore =
true;
1056 pED->pMetaData->edType = PeriodicList;
1057 pED->pMetaData->pFirstTD = pED->pMetaData->pLastTD = 0;
1058 pED->pMetaData->nTotalBytes = 0;
1059 pED->pMetaData->pPrev = pED->pMetaData->pNext = 0;
1060 pED->pMetaData->bLinked =
false;
1062 pED->pMetaData->bPeriodic =
true;
1065 pED->pMetaData->pCallback = pCallback;
1066 pED->pMetaData->pParam = pParam;
1069 m_ScheduleChangeLock.acquire();
1070 m_FullSchedule.pushBack(pED);
1071 m_ScheduleChangeLock.release();
1076 pED->pMetaData->pPrev = m_pPeriodicQueueTail;
1078 m_pPeriodicQueueTail->pNext = vtp_ed(pED) >> 4;
1079 m_pPeriodicQueueTail = pED;
1082 pED->bSkip = pED->pMetaData->bIgnore =
false;
1083 pED->pMetaData->bLinked =
true;
1086 start(pED->pMetaData->edType);
1095 OhciRhPortStsReset | OhciRhPortStsConnStsCh,
1096 OhciRhPortStatus + (nPort * 4));
1098 !(m_pBase->read32(OhciRhPortStatus + (nPort * 4)) & OhciRhPortStsResCh))
1099 Time::delay(5 * Time::Multiplier::Millisecond);
1100 m_pBase->write32(OhciRhPortStsResCh, OhciRhPortStatus + (nPort * 4));
1103 if (!(m_pBase->read32(OhciRhPortStatus + (nPort * 4)) &
1104 OhciRhPortStsEnable))
1105 m_pBase->write32(OhciRhPortStsEnable, OhciRhPortStatus + (nPort * 4));
1111 uint64_t p1, uint64_t p2, uint64_t p3, uint64_t p4, uint64_t p5,
1112 uint64_t p6, uint64_t p7, uint64_t p8)
1115 if (m_pBase->read32(OhciRhPortStatus + (p1 * 4)) & OhciRhPortStsConnected)
1121 if (m_pBase->read32(OhciRhPortStatus + (p1 * 4)) & OhciRhPortStsLoSpeed)
1126 <<
" has a low-speed device connected to it");
1127 deviceConnected(p1, LowSpeed);
1134 <<
" has a full-speed device connected to it");
1135 deviceConnected(p1, FullSpeed);
1139 deviceDisconnected(p1);
1148 uint32_t control = m_pBase->read32(OhciControl);
1149 control &= ~static_cast<
int>(list);
1150 m_pBase->write32(control, OhciControl);
1158 uint32_t control = m_pBase->read32(OhciControl);
1159 control |=
static_cast<int>(list);
1160 m_pBase->write32(control, OhciControl);
virtual bool registerInterruptHandler(size_t nInterruptNumber, InterruptHandler *pHandler)=0
void pushBack(const T &value)
virtual bool portReset(uint8_t nPort, bool bErrorResponse=false)
Gets a UsbDevice from a given vendor:product pair.
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 PhysicalMemoryManager & instance()
void stop(Lists list)
Stops the controller from processing the given list.
Iterator erase(Iterator &Iter)
static const size_t continuous
virtual void getMapping(void *virtualAddress, physical_uintptr_t &physicalAddress, size_t &flags)=0
virtual void doAsync(uintptr_t pTransaction, void(*pCallback)(uintptr_t, ssize_t)=0, uintptr_t pParam=0)
void pushFront(const T &value)
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.
virtual bool isMapped(void *virtualAddress)=0
bool acquire(bool recurse=false, bool safe=true)
static ProcessorInformation & information()
virtual uintptr_t getInterruptNumber()
static const size_t Write
static const size_t KernelMode
uint32_t readConfigSpace(Device *pDev, uint8_t offset)
::Iterator< T, node_t > Iterator
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)
virtual irq_id_t registerPciIrqHandler(IrqHandler *handler, Device *pDevice)=0
void removeED(ED *pED)
Prepares an ED to be reclaimed.
virtual uintptr_t createTransaction(UsbEndpoint endpointInfo)
Creates a new transaction with the given endpoint data.
void start(Lists list)
Starts processing of the given list.
virtual bool control(uint8_t irq, ControlCode code, size_t argument)
virtual bool irq(irq_id_t number, InterruptState &state)
IRQ handler.
static InterruptManager & instance()
Lists
Enumeration of lists that can be stopped or started.
void writeConfigSpace(Device *pDev, uint8_t offset, uint32_t data)