diff --git a/src/common/util/CxbxUtil.cpp b/src/common/util/CxbxUtil.cpp index 70122a3c4..d77d50685 100644 --- a/src/common/util/CxbxUtil.cpp +++ b/src/common/util/CxbxUtil.cpp @@ -140,34 +140,90 @@ size_t IoVecFromBuffer(const IoVec* iov, unsigned int iov_cnt, size_t offset, vo } // Read an array of DWORDs in memory -void GetDwords(xbaddr Paddr, uint32_t* Buffer, int Number) +bool GetDwords(xbaddr Paddr, uint32_t* Buffer, int Number) { - for (int i = 0; i < Number; i++, Buffer++, Paddr += sizeof(*Buffer)) { - std::memcpy(Buffer, reinterpret_cast(Paddr), 4); // dropped little -> big endian conversion from XQEMU - } + for (int i = 0; i < Number; i++, Buffer++, Paddr += sizeof(*Buffer)) { + // dropped little -> big endian conversion from XQEMU + if (Memory_R(reinterpret_cast(Paddr), Buffer, 4)) { + return true; + } + } + return false; } // Write an array of DWORDs in memory -void WriteDwords(xbaddr Paddr, uint32_t* Buffer, int Number) +bool WriteDwords(xbaddr Paddr, uint32_t* Buffer, int Number) { - for (int i = 0; i < Number; i++, Buffer++, Paddr += sizeof(*Buffer)) { - std::memcpy(reinterpret_cast(Paddr), Buffer, 4); // dropped big -> little endian conversion from XQEMU - } + for (int i = 0; i < Number; i++, Buffer++, Paddr += sizeof(*Buffer)) { + // dropped big -> little endian conversion from XQEMU + if (Memory_W(reinterpret_cast(Paddr), Buffer, 4)) { + return true; + } + } + return false; } // Read an array of WORDs in memory -void GetWords(xbaddr Paddr, uint16_t* Buffer, int Number) +bool GetWords(xbaddr Paddr, uint16_t* Buffer, int Number) { - for (int i = 0; i < Number; i++, Buffer++, Paddr += sizeof(*Buffer)) { - std::memcpy(Buffer, reinterpret_cast(Paddr), 2); // dropped little -> big endian conversion from XQEMU - } + for (int i = 0; i < Number; i++, Buffer++, Paddr += sizeof(*Buffer)) { + // dropped little -> big endian conversion from XQEMU + if (Memory_R(reinterpret_cast(Paddr), Buffer, 2)) { + return true; + } + } + return false; } // Write an array of WORDs in memory -void WriteWords(xbaddr Paddr, uint16_t* Buffer, int Number) +bool WriteWords(xbaddr Paddr, uint16_t* Buffer, int Number) { - for (int i = 0; i < Number; i++, Buffer++, Paddr += sizeof(*Buffer)) { - std::memcpy(reinterpret_cast(Paddr), Buffer, 2); // dropped big -> little endian conversion from XQEMU + for (int i = 0; i < Number; i++, Buffer++, Paddr += sizeof(*Buffer)) { + // dropped big -> little endian conversion from XQEMU + if (Memory_W(reinterpret_cast(Paddr), Buffer, 2)) { + return true; + } + } + return false; +} + +bool Memory_R(void* Addr, void* Buf, size_t Num) +{ + bool Error = false; + + if (Num != 0) { + if (Addr == nullptr) { + Error = true; + } + else { + std::memcpy(Buf, Addr, Num); + } + } + return Error; +} + +bool Memory_W(void* Addr, void* Buf, size_t Num) +{ + bool Error = false; + + if (Num != 0) { + if (Addr == nullptr) { + Error = true; + } + else { + std::memcpy(Addr, Buf, Num); + } + } + return Error; +} + +bool Memory_RW(void* Addr, void* Buf, size_t Num, bool bIsWrite) +{ + if (bIsWrite) { + return Memory_W(Addr, Buf, Num); + } + else { + return Memory_R(Addr, Buf, Num); } } diff --git a/src/common/util/CxbxUtil.h b/src/common/util/CxbxUtil.h index 29ce47d32..225b56a5a 100644 --- a/src/common/util/CxbxUtil.h +++ b/src/common/util/CxbxUtil.h @@ -63,10 +63,13 @@ void IoVecAdd(IOVector* qiov, void* base, size_t len); size_t IoVecTobuffer(const IoVec* iov, const unsigned int iov_cnt, size_t offset, void *buf, size_t bytes); size_t IoVecFromBuffer(const IoVec* iov, unsigned int iov_cnt, size_t offset, void* buf, size_t bytes); -void WriteDwords(xbaddr Paddr, uint32_t* Buffer, int Number); -void GetDwords(xbaddr Paddr, uint32_t* Buffer, int Number); -void GetWords(xbaddr Paddr, uint16_t* Buffer, int Number); -void WriteWords(xbaddr Paddr, uint16_t* Buffer, int Number); +bool WriteDwords(xbaddr Paddr, uint32_t* Buffer, int Number); +bool GetDwords(xbaddr Paddr, uint32_t* Buffer, int Number); +bool GetWords(xbaddr Paddr, uint16_t* Buffer, int Number); +bool WriteWords(xbaddr Paddr, uint16_t* Buffer, int Number); +bool Memory_R(void* Addr, void* Buf, size_t Num); +bool Memory_W(void* Addr, void* Buf, size_t Num); +bool Memory_RW(void* Addr, void* Buf, size_t Num, bool bIsWrite); void unix2dos(std::string& string); diff --git a/src/devices/usb/OHCI.cpp b/src/devices/usb/OHCI.cpp index 183571840..63ef68a2d 100644 --- a/src/devices/usb/OHCI.cpp +++ b/src/devices/usb/OHCI.cpp @@ -83,7 +83,7 @@ static const char* OHCI_RegNames[] = { /* Define these two if you want to dump usb packets and OHCI registers */ //#define DEBUG_ISOCH //#define DEBUG_PACKET -#define DEBUG_OHCI_REG +//#define DEBUG_OHCI_REG #ifdef DEBUG_OHCI_REG #define DUMP_REG_R(reg_val) DBG_PRINTF("%s, R, reg_val: 0x%X\n", OHCI_RegNames[Addr >> 2], reg_val) @@ -386,87 +386,49 @@ bool OHCI::OHCI_ReadHCCA(xbaddr Paddr, OHCI_HCCA* Hcca) // NOTE: this shared memory contains the HCCA + EDs and TDs - if (Paddr != xbnull) { - std::memcpy(Hcca, reinterpret_cast(Paddr), sizeof(OHCI_HCCA)); - return false; - } - - return true; // error + return Memory_R(reinterpret_cast(Paddr), Hcca, sizeof(OHCI_HCCA)); } bool OHCI::OHCI_WriteHCCA(xbaddr Paddr, OHCI_HCCA* Hcca) { - if (Paddr != xbnull) { - // We need to calculate the offset of the HccaFrameNumber member to avoid overwriting HccaInterrruptTable - size_t OffsetOfFrameNumber = offsetof(OHCI_HCCA, HccaFrameNumber); - - std::memcpy(reinterpret_cast(Paddr + OffsetOfFrameNumber), - reinterpret_cast(Hcca) + OffsetOfFrameNumber, 8); - return false; - } - - return true; // error + // We need to calculate the offset of the HccaFrameNumber member to avoid overwriting HccaInterrruptTable + size_t OffsetOfFrameNumber = offsetof(OHCI_HCCA, HccaFrameNumber); + return Memory_W(reinterpret_cast(Paddr + OffsetOfFrameNumber), reinterpret_cast(Hcca) + OffsetOfFrameNumber, 8); } bool OHCI::OHCI_ReadED(xbaddr Paddr, OHCI_ED* Ed) { - if (Paddr != xbnull) { - GetDwords(Paddr, reinterpret_cast(Ed), sizeof(*Ed) >> 2); // ED is 16 bytes large - return false; - } - return true; // error + return GetDwords(Paddr, reinterpret_cast(Ed), sizeof(*Ed) >> 2); // ED is 16 bytes large } bool OHCI::OHCI_WriteED(xbaddr Paddr, OHCI_ED* Ed) { - if (Paddr != xbnull) { - // According to the standard, only the HeadP field is writable by the HC, so we'll write just that - size_t OffsetOfHeadP = offsetof(OHCI_ED, HeadP); - WriteDwords(Paddr + OffsetOfHeadP, reinterpret_cast(reinterpret_cast(Ed) + OffsetOfHeadP), 1); - return false; - } - return true; // error + // According to the standard, only the HeadP field is writable by the HC, so we'll write just that + size_t OffsetOfHeadP = offsetof(OHCI_ED, HeadP); + return WriteDwords(Paddr + OffsetOfHeadP, reinterpret_cast(reinterpret_cast(Ed) + OffsetOfHeadP), 1); } bool OHCI::OHCI_ReadTD(xbaddr Paddr, OHCI_TD* Td) { - if (Paddr != xbnull) { - GetDwords(Paddr, reinterpret_cast(Td), sizeof(*Td) >> 2); // TD is 16 bytes large - return false; - } - return true; // error + return GetDwords(Paddr, reinterpret_cast(Td), sizeof(*Td) >> 2); // TD is 16 bytes large } bool OHCI::OHCI_WriteTD(xbaddr Paddr, OHCI_TD* Td) { - if (Paddr != xbnull) { - WriteDwords(Paddr, reinterpret_cast(Td), sizeof(*Td) >> 2); - return false; - } - return true; // error + return WriteDwords(Paddr, reinterpret_cast(Td), sizeof(*Td) >> 2); } bool OHCI::OHCI_ReadIsoTD(xbaddr Paddr, OHCI_ISO_TD* td) { - if (Paddr != xbnull) { - GetDwords(Paddr, reinterpret_cast(td), 4); - GetWords(Paddr + 16, td->Offset, 8); - return false; - } - return true; // error + return GetDwords(Paddr, reinterpret_cast(td), 4) || GetWords(Paddr + 16, td->Offset, 8); } bool OHCI::OHCI_WriteIsoTD(xbaddr Paddr, OHCI_ISO_TD* td) { - if (Paddr != xbnull) { - WriteDwords(Paddr, reinterpret_cast(td), 4); - WriteWords(Paddr + 16, td->Offset, 8); - return false; - } - return true; // error + return WriteDwords(Paddr, reinterpret_cast(td), 4) || WriteWords(Paddr + 16, td->Offset, 8); } -bool OHCI::OHCI_CopyTD(OHCI_TD* Td, uint8_t* Buffer, int Length, bool bIsWrite) +bool OHCI::OHCI_CopyTDBuffer(OHCI_TD* Td, uint8_t* Buffer, int Length, bool bIsWrite) { uint32_t ptr, n; @@ -477,7 +439,7 @@ bool OHCI::OHCI_CopyTD(OHCI_TD* Td, uint8_t* Buffer, int Length, bool bIsWrite) n = Length; } - if (OHCI_FindAndCopyTD(ptr, Buffer, n, bIsWrite)) { + if (Memory_RW(reinterpret_cast(ptr), Buffer, n, bIsWrite)) { return true; // error } if (n == Length) { @@ -490,13 +452,13 @@ bool OHCI::OHCI_CopyTD(OHCI_TD* Td, uint8_t* Buffer, int Length, bool bIsWrite) // same 4K page that contains the last byte of the buffer." ptr = Td->BufferEnd & ~0xFFFu; Buffer += n; - if (OHCI_FindAndCopyTD(ptr, Buffer, Length - n, bIsWrite)) { + if (Memory_RW(reinterpret_cast(ptr), Buffer, Length - n, bIsWrite)) { return true; // error } return false; } -bool OHCI::OHCI_CopyIsoTD(uint32_t start_addr, uint32_t end_addr, uint8_t* Buffer, int Length, bool bIsWrite) +bool OHCI::OHCI_CopyIsoTDBuffer(uint32_t start_addr, uint32_t end_addr, uint8_t* Buffer, int Length, bool bIsWrite) { uint32_t ptr, n; @@ -506,7 +468,7 @@ bool OHCI::OHCI_CopyIsoTD(uint32_t start_addr, uint32_t end_addr, uint8_t* Buffe n = Length; } - if (OHCI_FindAndCopyTD(ptr, Buffer, n, bIsWrite)) { + if (Memory_RW(reinterpret_cast(ptr), Buffer, n, bIsWrite)) { return true; // error } if (n == Length) { @@ -514,28 +476,12 @@ bool OHCI::OHCI_CopyIsoTD(uint32_t start_addr, uint32_t end_addr, uint8_t* Buffe } ptr = end_addr & ~0xFFFu; Buffer += n; - if (OHCI_FindAndCopyTD(ptr, Buffer, Length - n, bIsWrite)) { + if (Memory_RW(reinterpret_cast(ptr), Buffer, Length - n, bIsWrite)) { return true; // error } return false; } -bool OHCI::OHCI_FindAndCopyTD(xbaddr Paddr, uint8_t* Buffer, int Length, bool bIsWrite) -{ - if (Paddr == xbnull) { - return true; // error - } - - if (bIsWrite) { - std::memcpy(reinterpret_cast(Paddr), Buffer, Length); - } - else { - std::memcpy(Buffer, reinterpret_cast(Paddr), Length); - } - - return false; -} - int OHCI::OHCI_ServiceEDlist(xbaddr Head, int Completion) { OHCI_ED ed; @@ -705,7 +651,7 @@ int OHCI::OHCI_ServiceTD(OHCI_ED* Ed) packetlen = length; } if (!completion) { - if (OHCI_CopyTD(&td, m_UsbBuffer, packetlen, false)) { + if (OHCI_CopyTDBuffer(&td, m_UsbBuffer, packetlen, false)) { OHCI_FatalError(); } } @@ -760,7 +706,7 @@ int OHCI::OHCI_ServiceTD(OHCI_ED* Ed) if (ret >= 0) { if (direction == OHCI_TD_DIR_IN) { - if (OHCI_CopyTD(&td, m_UsbBuffer, ret, true)) { + if (OHCI_CopyTDBuffer(&td, m_UsbBuffer, ret, true)) { OHCI_FatalError(); } #ifdef DEBUG_PACKET @@ -1790,7 +1736,7 @@ int OHCI::OHCI_ServiceIsoTD(OHCI_ED* ed, int completion) } if (len && dir != OHCI_TD_DIR_IN) { - if (OHCI_CopyIsoTD(start_addr, end_addr, m_UsbBuffer, len, false)) { + if (OHCI_CopyIsoTDBuffer(start_addr, end_addr, m_UsbBuffer, len, false)) { OHCI_FatalError(); return 1; } @@ -1827,7 +1773,7 @@ int OHCI::OHCI_ServiceIsoTD(OHCI_ED* ed, int completion) // Writeback if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) { // IN transfer succeeded - if (OHCI_CopyIsoTD(start_addr, end_addr, m_UsbBuffer, ret, true)) { + if (OHCI_CopyIsoTDBuffer(start_addr, end_addr, m_UsbBuffer, ret, true)) { OHCI_FatalError(); return 1; } diff --git a/src/devices/usb/OHCI.h b/src/devices/usb/OHCI.h index fdd8da4f3..dbcb74034 100644 --- a/src/devices/usb/OHCI.h +++ b/src/devices/usb/OHCI.h @@ -234,11 +234,9 @@ class OHCI // write an iso TD in memory bool OHCI_WriteIsoTD(xbaddr Paddr, OHCI_ISO_TD* td); // read/write the user buffer pointed to by a TD from/to main memory - bool OHCI_CopyTD(OHCI_TD* Td, uint8_t* Buffer, int Length, bool bIsWrite); + bool OHCI_CopyTDBuffer(OHCI_TD* Td, uint8_t* Buffer, int Length, bool bIsWrite); // read/write the user buffer pointed to by a ISO TD from/to main memory - bool OHCI_CopyIsoTD(uint32_t start_addr, uint32_t end_addr, uint8_t* Buffer, int Length, bool bIsWrite); - // find a TD buffer in memory and copy it - bool OHCI_FindAndCopyTD(xbaddr Paddr, uint8_t* Buffer, int Length, bool bIsWrite); + bool OHCI_CopyIsoTDBuffer(uint32_t start_addr, uint32_t end_addr, uint8_t* Buffer, int Length, bool bIsWrite); // process an ED list. Returns nonzero if active TD was found int OHCI_ServiceEDlist(xbaddr Head, int Completion); // process a TD. Returns nonzero to terminate processing of this endpoint