📄 z228_usb_msc.cpp
字号:
PhysicalIoBase.HighPart = 0;
PhysicalIoBase.LowPart = Z228_RESET;
reset = (DWORD *)MmMapIoSpace( PhysicalIoBase, 0x1000 ,FALSE );
if( !reset ) {
RETAILMSG(USB_ERROR, (TEXT("MAP Z228_RESET register failed \r\n")));
}
else{
*reset &= ~(Z228_RESET_nUSBRES |Z228_RESET_nUSB48RES|Z228_RESET_nUSBPLLRES |Z228_RESET_nUSB12RES);
Sleep(10);
*reset |=Z228_RESET_nUSB48RES;
Sleep(10);
*reset |=Z228_RESET_nUSBPLLRES;
Sleep(10);
*reset |=Z228_RESET_nUSB12RES;
Sleep(10);
*reset |=Z228_RESET_nUSBRES;
Sleep(40);
MmUnmapIoSpace( reset, 0x1000 );
}
/* Disable interrupts */
usb_write(0, UDC_ENDP_INTR_ENABLE);
usb_write(~0, UDC_ENDP_INTR);
usb_write(0, UDC_INTR_ENABLE);
usb_write(~0, UDC_INTR);
// Reset all endpoints
for (DWORD dwEpIdx = 0; dwEpIdx < ENDPOINT_COUNT; ++dwEpIdx) {
PEP_STATUS peps = GetEpStatus(pContext, dwEpIdx);
ResetEndpoint(pContext, peps);
}
}
// Check the device release number.
static
VOID
CheckDeviceRelease(
PZ228_CONTEXT pContext
)
{
RETAILMSG(USB_DEBUG, (_T("==> CheckDeviceRelease ()\r\n")));
}
inline
static
VOID
SetClearTransferInterrupts(
PZ228_CONTEXT pContext,
PEP_STATUS peps,
PSTransfer pTransfer,
BOOL bSet
)
{
// Enable transfer interrupts.
if(bSet)
usb_set(peps->dwFlags, UDC_ENDP_INTR_ENABLE);
else
usb_clear(peps->dwFlags, UDC_ENDP_INTR_ENABLE);
RETAILMSG(USB_DEBUG, (_T("SetClearTransferInterrupts: 0x%x \r\n"), usb_read(UDC_ENDP_INTR_ENABLE)));
}
/*
* Z228 Bus Suspend Interrupt Handler
*/
inline static void z228_suspend_intr(PZ228_CONTEXT pContext)
{
DWORD dwID_Change;
RETAILMSG(USB_DEBUG, (_T("+z228_suspend_intr\r\n")));
if(pContext->fAttached == TRUE) {
pContext->pfnNotify(pContext->pvMddContext,UFN_MSG_BUS_EVENTS, UFN_DETACH);
pContext->fAttached = FALSE;
usb_set(UDC_BUSRESET_INTR, UDC_INTR_ENABLE);
usb_clear(UDC_SUSPEND_INTR, UDC_INTR_ENABLE);
}
dwID_Change = usb_read(UHC_OTG_CSR)& UHC_CONN_ID_CHANGE;
if(dwID_Change) {
usb_write(UHC_CONN_ID_CHANGE, UHC_OTG_CSR);
// clear the ID Change intr
DWORD dwMode = (usb_read(UHC_OTG_CSR)&OTG_MODE_DEVICE)? DEV_MODE : HOST_MODE;
if(dwMode == HOST_MODE) {
RETAILMSG(1, (_T("Device: ID change Done, Mode = %d! set event\r\n"),dwMode));
pContext->fExitIST = TRUE;
SetEvent(pContext->hevDevEvent);
Sleep(100);
}
else {
usb_set(UDC_BUSRESET_INTR |UDC_SUSPEND_INTR, UDC_INTR);
}
}
//delay for a while waiting upper level DETACH
Sleep(200);
}
/*
* Z228 Bus Reset Interrupt Handler
*/
inline static void z228_reset_intr(PZ228_CONTEXT pContext)
{
RETAILMSG(USB_DEBUG, (_T("+z228_reset_intr\r\n")));
if (!pContext->fAttached) {
// Upon attach sometimes we do not get a VBUS interrupt,
// just the reset interrupt.
usb_set(UDC_SUSPEND_INTR, UDC_INTR_ENABLE);
pContext->pfnNotify(pContext->pvMddContext,UFN_MSG_BUS_EVENTS, UFN_ATTACH);
pContext->fAttached = TRUE;
}
pContext->fSpeedReported = FALSE;
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS,UFN_RESET);
usb_write(0x0, UDC_RX_CONTROL(0));
usb_write(UDC_RX_FLUSHFIFO, UDC_RX_CONTROL(0));
usb_write(0x0, UDC_TX_CONTROL(0));
usb_write(UDC_TX_FLUSHFIFO, UDC_TX_CONTROL(0));
usb_write(UDC_FIFOREADY, UDC_RX_CONTROL(0));
}
static
VOID
HandleTx(
PZ228_CONTEXT pContext,
PEP_STATUS peps
)
{
PREFAST_DEBUGCHK(pContext);
PREFAST_DEBUGCHK(peps);
DEBUGCHK(peps->fInitialized);
PSTransfer pTransfer = peps->pTransfer;
BOOL fCompleted = FALSE;
DWORD dwStatus;
DWORD cdwToWrite, iTimes, remains;
unsigned char *tsrc,*tdst;
DWORD* pdwBuffer;
volatile DWORD * const pdwReg = (DWORD *)(udc_base+(UDC_TX_FIFO(peps->dwEndpoint)>>2)) ;
//RETAILMSG(1, (_T("==> HandleTx ()\r\n")));
ValidateTransferDirection(pContext, peps, pTransfer);
DEBUGCHK(TRANSFER_IS_IN(pTransfer));
DEBUGCHK(pTransfer->dwUsbError == UFN_NOT_COMPLETE_ERROR);
DEBUGMSG(USB_DEBUG, (_T(" UDC_TX_STATUS = 0x%x\r\n"),usb_read(UDC_TX_STATUS(peps->dwEndpoint))));
RETAILMSG(USB_DATA_OUT, (_T(" pTransfer->dwEndpoint = 0x%x\r\n"),peps->dwEndpoint));
DEBUGMSG(USB_DEBUG, (_T(" pTransfer->cbTransferred = 0x%x\r\n"),pTransfer->cbTransferred));
//RETAILMSG(USB_DATA_IN, (_T(" len = 0x%x\r\n"),pTransfer->cbBuffer));
DWORD dwCurrentPermissions = GetCurrentPermissions();
SetProcPermissions(pTransfer->dwCallerPermissions);
Tx_Again:
__try {
const BYTE *c_pbBuffer = (const BYTE*) pTransfer->pvBuffer + pTransfer->cbTransferred;
const DWORD c_cbBuffer = pTransfer->cbBuffer - pTransfer->cbTransferred;
// Min of input byte count and supported size
cdwToWrite =min(c_cbBuffer,peps->dwPacketSizeAssigned);
if(cdwToWrite){
iTimes = cdwToWrite>>2;
remains = cdwToWrite & 0x3;
usb_write(cdwToWrite, UDC_TX_TRANSFER_SIZE(peps->dwEndpoint));
// Write to FIFO through register.
pdwBuffer = (DWORD*) c_pbBuffer;
// memcpy((BYTE*)pdwReg, (BYTE*)pdwReg, cdwToWrite);
for(DWORD a=0; a<iTimes; a++)
*pdwReg=*(pdwBuffer+a);
// Now handle the leftovers
if (remains) {
tdst = (unsigned char *)(pdwReg + a);
tsrc = (unsigned char *)(pdwBuffer + a);
while (remains--)
*tdst++ = *tsrc++;
}
pTransfer->cbTransferred += cdwToWrite;
}
// Set FIFO Ready Bit to send data
usb_set(UDC_TX_FIFOREADY, UDC_TX_CONTROL(peps->dwEndpoint));
// clear status bit
usb_set(UDC_TX_NAKSENT,UDC_TX_STATUS(peps->dwEndpoint));
if(pTransfer->cbTransferred == pTransfer->cbBuffer) {
DWORD TxStatus = usb_read(UDC_TX_STATUS(peps->dwEndpoint));
if(TxStatus & UDC_TX_DATASENT) {
usb_set(UDC_TX_DATASENT,UDC_TX_STATUS(peps->dwEndpoint));
usb_set(UDC_TX_NAKSENT,UDC_TX_STATUS(peps->dwEndpoint));
dwStatus = UFN_NO_ERROR;
fCompleted = TRUE;
}
}
else{
fCompleted = FALSE;
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
RETAILMSG(USB_ERROR, (_T("%s TX Exception!\r\n"), pszFname));
fCompleted = TRUE;
dwStatus = UFN_CLIENT_BUFFER_ERROR;
}
if(fCompleted == FALSE){
for(DWORD i=0; i<20; i++)
if(usb_read(UDC_TX_STATUS(peps->dwEndpoint))&(UDC_TX_DATASENT))
{
usb_set(UDC_TX_DATASENT,UDC_TX_STATUS(peps->dwEndpoint));
usb_set(UDC_TX_NAKSENT,UDC_TX_STATUS(peps->dwEndpoint));
goto Tx_Again;
break;
}
}
else
CompleteTransfer(pContext, peps, dwStatus);
SetProcPermissions(dwCurrentPermissions);
}
static
VOID
HandleRx(
PZ228_CONTEXT pContext,
PEP_STATUS peps
)
{
DEBUGCHK(pContext);
DEBUGCHK(peps);
DEBUGCHK(peps->fInitialized);
PSTransfer pTransfer = peps->pTransfer;
BOOL fCompleted = FALSE;
DWORD dwStatus = UFN_NO_ERROR, dwRxStatus;
DWORD iTimes, remains, size;
unsigned char *tsrc,*tdst;
DWORD *fifo = (DWORD*)((DWORD) udc_base + (UDC_RX_FIFO>>2)), *pdwBuffer ;
DEBUGCHK(TRANSFER_IS_OUT(pTransfer));
DEBUGCHK(pTransfer->dwUsbError == UFN_NOT_COMPLETE_ERROR);
RETAILMSG(0, (_T("+Rx\r\n")));
ValidateTransferDirection(pContext, peps, pTransfer);
DWORD dwCurrentPermissions = GetCurrentPermissions();
SetProcPermissions(pTransfer->dwCallerPermissions);
Rx_Again:
__try {
PBYTE pbBuffer = (PBYTE) pTransfer->pvBuffer + pTransfer->cbTransferred;
DWORD cbBuffer = pTransfer->cbBuffer - pTransfer->cbTransferred;
dwRxStatus = usb_read(UDC_RX_STATUS);
size = (dwRxStatus >> UDC_RX_SIZE_SHIFT) & UDC_RX_SIZE_MASK;
size = min(cbBuffer, size);
RETAILMSG(USB_DATA_OUT, (_T("cbBuffer=0x%x ,size=0x%x\r\n"),cbBuffer,size));
if (dwRxStatus & UDC_RX_STATUS_COMPLETE) {
//if(dwRxStatus & UDC_RX_GOOD_STATUS) {
if(size != 0 ) {
/* Need to read out some data from FIFO */
iTimes = size>>2;
remains = size & 0x3;
pdwBuffer= (DWORD *) pbBuffer;
//memcpy((char *)pdwBuffer, (char *)fifo, size);
for(DWORD a=0; a<iTimes; a++)
{
*(pdwBuffer+a)=*fifo;
//RETAILMSG(USB_DATA_IN, (TEXT(" 0x%08x "),*(pdwBuffer+a)));
}
/* Now handle the leftovers */
if (remains) {
tsrc = (unsigned char *)(fifo + a);
tdst = (unsigned char *)(pdwBuffer + a);
while (remains--)
*tdst++ = *tsrc++;
//RETAILMSG(USB_DATA_IN, (TEXT(" 0x%06x "),*(pdwBuffer+a)));
}
//RETAILMSG(USB_DATA_IN,(TEXT("\r\n")));
pTransfer->cbTransferred += size;
if(pTransfer->cbTransferred == pTransfer->cbBuffer)
fCompleted = TRUE;
else
fCompleted = FALSE;
}
usb_set(UDC_RX_STATUS_COMPLETE, UDC_RX_STATUS);
}
usb_write(UDC_RX_FIFOREADY, UDC_RX_CONTROL(peps->dwEndpoint));
}
__except(EXCEPTION_EXECUTE_HANDLER) {
RETAILMSG(USB_ERROR, (_T("%s RX Exception!\r\n"), pszFname));
fCompleted = TRUE;
dwStatus = UFN_CLIENT_BUFFER_ERROR;
}
if (fCompleted) {
CompleteTransfer(pContext, peps, dwStatus);
}
else {
for(DWORD i=0; i<10; i++) {
dwRxStatus = usb_read(UDC_RX_STATUS);
if (dwRxStatus & UDC_RX_STATUS_COMPLETE) {
goto Rx_Again;
break;
}
}
}
SetProcPermissions(dwCurrentPermissions);
}
// Calls must be protected by the pTransfer->cs.
static
VOID
StartTransfer(
PZ228_CONTEXT pContext,
PEP_STATUS peps,
PSTransfer pTransfer
)
{
DWORD dwRxStatus;
DEBUGCHK(pContext);
PREFAST_DEBUGCHK(peps);
DEBUGCHK(!peps->pTransfer);
DEBUGCHK(pTransfer->dwUsbError == UFN_NOT_COMPLETE_ERROR);
ValidateTransferDirection(pContext, peps, pTransfer);
//RETAILMSG(1, (_T("+ StartTransfer \r\n")));
DEBUGMSG(USB_DEBUG, (_T(" Setting up %s %s transfer on ep %c for %u bytes\r\n"),
peps->pszType, TRANSFER_IS_IN(pTransfer) ? _T("IN") : _T("OUT"),
GET_ENDPOINT_LETTER(peps->dwEndpoint), pTransfer->cbBuffer));
peps->pTransfer = pTransfer;
// Enable transfer interrupts.
SetClearTransferInterrupts(pContext, peps, pTransfer, SET);
if (TRANSFER_IS_IN(pTransfer) ) {
// Fill FIFO
HandleTx(pContext, peps);
}
else if(TRANSFER_IS_OUT(pTransfer) && peps->dwEndpoint){
dwRxStatus = usb_read(UDC_RX_STATUS);
// start to Rx
if (dwRxStatus & UDC_RX_STATUS_COMPLETE)
HandleRx(pContext, peps);
}
RETAILMSG(USB_DEBUG, (_T("-StartTransfer \r\n")));
}
DWORD
WINAPI
UfnPdd_IssueTransfer(
PVOID pvPddContext,
DWORD dwEndpoint,
PSTransfer pTransfer
)
{
DWORD dwRet;
DEBUGCHK(EP_VALID(dwEndpoint));
DEBUGCHK(pTransfer->dwUsbError == UFN_NOT_COMPLETE_ERROR);
DEBUGCHK(pTransfer->cbTransferred == 0);
//RETAILMSG(1, (_T("+UfnPdd_IssueTransfer %d\r\n"),dwEndpoint));
PZ228_CONTEXT pContext = (PZ228_CONTEXT) pvPddContext;
ValidateContext(pContext);
PEP_STATUS peps = GetEpStatus(pContext, dwEndpoint);
LOCK_ENDPOINT1(peps);
DEBUGCHK(peps->fInitialized);
if ( (peps->dwPacketSizeAssigned & 0x3) != 0 &&
(pTransfer->cbBuffer > peps->dwPacketSizeAssigned) ) {
// We do not support transfer greater than the max packet
// size if the max packet size is not DWORD aligned due to
// alignment problems in HandleTx().
// The solution is to issue transfers of max packet size or
// less.
RETAILMSG(USB_ERROR, (_T("%s Transfer size too large for non-DWORD aligned max packet size\r\n"),
pszFname));
dwRet = ERROR_INVALID_PARAMETER;
goto EXIT;
}
DEBUGCHK(peps->pTransfer == NULL);
StartTransfer(pContext, peps, pTransfer);
dwRet = ERROR_SUCCESS;
EXIT:
UNLOCK_ENDPOINT1(peps);
return dwRet;
}
// Surround calls with cs on both the endpoint and the transfer.
static
VOID
CompleteTransfer(
PZ228_CONTEXT pContext,
PEP_STATUS peps,
DWORD dwUsbError
)
{
//RETAILMSG(1, (_T("+CompleteTransfer %d \r\n"),peps->dwEndpoint));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -