📄 z228_usb_msc.cpp
字号:
/*++
* The content of this file or document is CONFIDENTIAL and PROPRIETARY
* to Jade Technologies Co., Ltd. It is subject to the terms of a
* License Agreement between Licensee and Jade Technologies Co., Ltd.
* restricting among other things, the use, reproduction, distribution
* and transfer. Each of the embodiments, including this information
* and any derivative work shall retain this copyright notice.
*
* Copyright (c) 2006 Jade Technologies Co., Ltd.
* All rights reserved.
Module Name:
z228_usb_msc.CPP
Abstract:
OTG USB Function (Mass Storage) Platform -Dependent Driver.
--*/
//#define CHN
//#define DEBUG_TEXT
#ifdef CHN
#define MESSAGE_TITLE TEXT("选择'是'为U盘模式,选择'否'为充电模式(请确保选择U盘模式前,将当前运行的应用程序关闭!!)")
#else
#define MESSAGE_TITLE TEXT("Press 'YES' to Storage Mass or 'NO' to charge?(Please quit the running programs before you press 'YES'!!)")
#endif
#include "z228_usb_msc.h"
#include <ceddk.h>
#include <devload.h>
#include <ddkreg.h>
#include <nkintr.h>
#include <netui.h>
#include <pkfuncs.h>
#include <oalfuncs.h>
#include "dma.h"
//****************************************************
//the macro indicates if mass storage is independent
// USB_MULTIFUN - Mass storage has to work with the host driver
// others - Mass storage works by itself
//****************************************************
//#define USB_MULTIFUN
#define USB_DATA_OUT 0
#define USB_DATA_IN 0
#define USB_INIT 0
#define USB_DEBUG 0
#define USB_ERROR 1
//yz_add_070627
#define GPIO_num 8
#define GPIO_pin 2
//yz_end
#define UDC_REG_PRIORITY_VAL _T("Priority256")
#define DEFAULT_PRIORITY 108
const char pszFname[2]=" ";
#ifdef DEBUG_TEXT
FILE * fp=NULL;
#endif
//#define LOCK_ENDPOINT(peps) EnterCriticalSection(&peps->cs)
//#define UNLOCK_ENDPOINT(peps) LeaveCriticalSection(&peps->cs)
#define LOCK_ENDPOINT(peps) 0
#define UNLOCK_ENDPOINT(peps) 0
#define LOCK_ENDPOINT1(peps) EnterCriticalSection(&peps->cs)
#define UNLOCK_ENDPOINT1(peps) LeaveCriticalSection(&peps->cs)
#define EP_0_PACKET_SIZE 0x40
#define EP_EF_MAX_PACKET_SIZE 0x40
#define EP_0EF_FIFO_CAPACITY 0x40
#define EP_ABCD_FIFO_CAPACITY 1024
#define EP_FIFO_DIVISION (0x10000>>2)
#define EP_CFG_0_OFFSET 0x300
#define EP_CFG_A_OFFSET 0x320
#define EP_CFG_B_OFFSET 0x340
#define EP_CFG_C_OFFSET 0x360
#define EP_CFG_D_OFFSET 0x380
#define EP_CFG_E_OFFSET 0x3A0
#define EP_CFG_F_OFFSET 0x3C0
#define EP_A_HS_MAXPKT_INDEX 0x020
#define EP_A_FS_MAXPKT_INDEX 0x021
#define EP_B_HS_MAXPKT_INDEX 0x030
#define EP_B_FS_MAXPKT_INDEX 0x031
#define EP_C_HS_MAXPKT_INDEX 0x040
#define EP_C_FS_MAXPKT_INDEX 0x041
#define EP_D_HS_MAXPKT_INDEX 0x050
#define EP_D_FS_MAXPKT_INDEX 0x051
#define EP_E_HS_MAXPKT_INDEX 0x060
#define EP_E_FS_MAXPKT_INDEX 0x061
#define EP_F_HS_MAXPKT_INDEX 0x070
#define EP_F_FS_MAXPKT_INDEX 0x071
typedef struct _EP_STATUS {
DWORD dwEndpoint;
DWORD dwBaseOffset;
DWORD cbFifo;
DWORD dwFifoOffset;
DWORD dwFlags;
BOOL fInitialized;
DWORD dwPacketSizeAssigned;
PSTransfer pTransfer;
CRITICAL_SECTION cs;
#ifdef DEBUG
LPCTSTR pszType;
#endif
} EP_STATUS, *PEP_STATUS;
static const EP_STATUS g_rgEpStatus[] = {
{ 0, EP_CFG_0_OFFSET, EP_0EF_FIFO_CAPACITY ,EP_FIFO_DIVISION, 0x1},
{ 1, EP_CFG_A_OFFSET, EP_ABCD_FIFO_CAPACITY ,EP_FIFO_DIVISION * 2, 0x20000 },
{ 2, EP_CFG_B_OFFSET, EP_ABCD_FIFO_CAPACITY ,EP_FIFO_DIVISION * 3 , 0x4},
{ 3, EP_CFG_C_OFFSET, EP_ABCD_FIFO_CAPACITY, },
{ 4, EP_CFG_D_OFFSET, EP_ABCD_FIFO_CAPACITY, },
{ 5, EP_CFG_E_OFFSET, EP_0EF_FIFO_CAPACITY },
{ 6, EP_CFG_F_OFFSET, EP_0EF_FIFO_CAPACITY }
};
#define ENDPOINT_COUNT dim(g_rgEpStatus)
typedef struct _Z228_CONTEXT {
DWORD dwSig;
PBYTE pbFifoAddr;
PVOID pvMddContext;
HANDLE hIST;
HANDLE hevIntrEvent;
HANDLE hMainThread;
HANDLE hTestThread;
HANDLE hevDevEvent;
HANDLE hevDevDoneEvent;
HANDLE hevHostEvent;
HANDLE hevHostDoneEvent;
DWORD dwISTPriority;
BOOL fRunning;
CRITICAL_SECTION csSharedRegisterAccess;
DWORD dwSysIntr;
BOOL fSpeedReported;
BOOL fExitIST;
BOOL fRestartIST;
BOOL fForceFullSpeed;
BOOL fAttached;
BOOL fFunction;
PFN_UFN_MDD_NOTIFY pfnNotify;
HANDLE hBusAccess;
CEDEVICE_POWER_STATE cpsCurrent;
EP_STATUS rgEpStatus[ENDPOINT_COUNT];
}Z228_CONTEXT, *PZ228_CONTEXT;
#define EP_VALID(x) ((x) < ENDPOINT_COUNT)
#define Z228_SIG '822Z' // "Z228" signature
#define IS_VALID_Z228_CONTEXT(ptr) \
( (ptr != NULL) && (ptr->dwSig == Z228_SIG) )
#define IN_TRANSFER_INTERRUPTS DATA_PKT_TX_INT_MASK
#define OUT_TRANSFER_INTERRUPTS DATA_PKT_RX_INT_MASK
#define SET 1
#define CLEAR 0
#define GET_ENDPOINT_LETTER(dw) ((dw) ? (dw) + 'A' - 1 : '0')
// Forward declarations
static
VOID
CompleteTransfer(
PZ228_CONTEXT pContext,
PEP_STATUS peps,
DWORD dwUsbError
);
inline
static
int
z228_Hw_Init(
);
DWORD
WINAPI
UfnPdd_SendControlStatusHandshake(
PVOID pvPddContext,
DWORD dwEndpoint
);
#ifdef DEBUG
extern DBGPARAM dpCurSettings;
#define ZONE_INTERRUPTS DEBUGZONE(8)
#define ZONE_POWER DEBUGZONE(9)
UFN_GENERATE_DPCURSETTINGS(UFN_DEFAULT_DPCURSETTINGS_NAME,
_T("Interrupts"), _T("Power"), _T(""), _T(""),
DBG_ERROR | DBG_INIT);
// Validate the Z228 context.
static
VOID
ValidateContext(
PZ228_CONTEXT pContext
)
{
PREFAST_DEBUGCHK(pContext);
DEBUGCHK(pContext->dwSig == Z228_SIG);
DEBUGCHK(!pContext->hevIntrEvent|| pContext->hIST);
DEBUGCHK(VALID_DX(pContext->cpsCurrent));
DEBUGCHK(pContext->pfnNotify);
}
static const LPCTSTR g_rgpszEndpointTypes[4] = {
_T("CONTROL"),
_T("ISOCHRONOUS"),
_T("BULK"),
_T("INTERRUPT")
};
#else
#define ValidateContext(ptr)
#endif
DWORD bCharge;
DWORD *udc_base = NULL;
/******************************************************************
* z228 usb register's operation
******************************************************************/
inline unsigned long usb_read(DWORD port)
{
return *(volatile unsigned long *)(udc_base+(port>>2));
}
inline void usb_write(DWORD val, DWORD port)
{
*(volatile DWORD *)(udc_base+(port>>2)) = val;
}
inline void usb_set(ULONG val, DWORD port)
{
*(volatile DWORD *)(udc_base+(port>>2))|= val;
}
inline void usb_clear(DWORD val, DWORD port)
{
*(volatile DWORD *)(udc_base+(port>>2)) &=~val;
}
/******************************************************************
* Low level FIFO operation
******************************************************************/
inline static void copy_fifo (DWORD *dst, DWORD *src, DWORD count)
{
DWORD i;
unsigned char *tsrc, *tdst;
if (count > 0) {
DWORD times = count >>2;
DWORD remains = count & 0x3;
for (i = 0; i<times; i++)
*(dst+i) = *(src+i);
/* Now handle the leftovers */
if (remains) {
tsrc = (unsigned char *)(src + times);
tdst = (unsigned char *)(dst + times);
while (remains--)
*tdst++ = *tsrc++;
}
}
}
#ifdef DEBUG
static
VOID
ValidateTransferDirection(
PZ228_CONTEXT pContext,
PEP_STATUS peps,
PSTransfer pTransfer
)
{
DEBUGCHK(pContext);
PREFAST_DEBUGCHK(peps);
PREFAST_DEBUGCHK(pTransfer);
}
#else
#define ValidateTransferDirection(ptr1, ptr2, ptr3)
#endif
/*
* Flush EP
*/
static
void
flush(
DWORD ENP
)
{
usb_write(0, UDC_RX_CONTROL(ENP));
usb_read(UDC_RX_CONTROL(ENP));
usb_write(UDC_FLUSHFIFO, UDC_RX_CONTROL(ENP));
}
// Get the index to the max packet register for this endpoint and speed.
static
DWORD
GetMaxPktIdx(
DWORD dwEndpoint,
UFN_BUS_SPEED speed
)
{
DEBUGCHK(dwEndpoint < ENDPOINT_COUNT);
DEBUGCHK(dwEndpoint); // Do not call for endpoint 0.
DWORD dwDelta = (EP_B_HS_MAXPKT_INDEX - EP_A_HS_MAXPKT_INDEX);
DWORD dwIdx = (dwDelta * (dwEndpoint - 1)) + EP_A_HS_MAXPKT_INDEX;
RETAILMSG(USB_DEBUG, (_T("==> GetMaxPktIdx ()\r\n")));
if (speed == BS_FULL_SPEED) {
++dwIdx;
}
DEBUGCHK(dwIdx >= EP_A_HS_MAXPKT_INDEX);
DEBUGCHK(dwIdx <= EP_F_FS_MAXPKT_INDEX);
return dwIdx;
}
// Retrieve the endpoint status structure.
inline
static
PEP_STATUS
GetEpStatus(
PZ228_CONTEXT pContext,
DWORD dwEndpoint
)
{
ValidateContext(pContext);
DEBUGCHK(EP_VALID(dwEndpoint));
// RETAILMSG(USB_DEBUG, (_T("==> GetEpStatus ()\r\n")));
PEP_STATUS peps = &pContext->rgEpStatus[dwEndpoint];
DEBUGCHK(peps->dwEndpoint == dwEndpoint);
return peps;
}
// Clear the transfer status bits.
static
inline
VOID
ClearTransferStatus(
PZ228_CONTEXT pContext,
const EP_STATUS *peps
)
{
DEBUGCHK(pContext);
PREFAST_DEBUGCHK(peps);
RETAILMSG(USB_DEBUG, (_T("==> ClearTransferStatus ()\r\n")));
}
// Return the irq bit for this endpoint.
inline
static
DWORD
EpToIrqStatBit(
DWORD dwEndpoint
)
{
DEBUGCHK(EP_VALID(dwEndpoint));
RETAILMSG(USB_DEBUG, (_T("==> EpToIrqStatBit ()\r\n")));
return (1 << dwEndpoint);
}
// Reset an endpoint
static
VOID
ResetEndpoint(
PZ228_CONTEXT pContext,
PEP_STATUS peps
)
{
RETAILMSG(USB_DEBUG, (_T("+ ResetEndpoint\r\n")));
ValidateContext(pContext);
PREFAST_DEBUGCHK(peps);
}
// Reset the z228 (device and EP0).
static
VOID
ResetDevice(
PZ228_CONTEXT pContext
)
{
PHYSICAL_ADDRESS PhysicalIoBase;
DWORD *reset=NULL;
DWORD tcount =10;
RETAILMSG(USB_DEBUG, (_T("+ResetDevice\r\n")));
/* Disable interrupts */
usb_write(0, UDC_INTR_ENABLE);
usb_write(0, UDC_ENDP_INTR_ENABLE);
usb_write(0, UHC_INTR_ENABLE);
//system control register
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -