📄 isp1581.cpp
字号:
//**********************************************************************
//
// Filename: ISP1581.CPP
//
// Description: ISP1581 USB Function Platform-Dependent Driver.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Use of this source code is subject to the terms of the Cirrus end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to
// use this source code. For a copy of the EULA, please see the
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2005, All Rights Reserved
//
//**********************************************************************
#include "isp1581.h"
#include <ceddk.h>
#include <devload.h>
#include <ddkreg.h>
#include <nkintr.h>
#include <hwdefs.h>
#include <oalintr.h>
#define ACTIVE_HIGH
#ifdef ACTIVE_HIGH
#define DMA_PIN_CONFIG M2M_CTRL_ETDP_AHIGH_OUTPUT | \
M2M_CTRL_DACKP_ACTIVEHIGH | \
M2M_CTRL_DREQP_HIGHLEVEL
#define USB_PIN_CONFIG USB_DMAHW_EOT_ACTIVE_HIGH | \
USB_DMAHW_ACK_ACTIVE_HIGH | \
USB_DMAHW_DREQ_ACTIVE_HIGH
#else
#define DMA_PIN_CONFIG M2M_CTRL_ETDP_ALOW_OUTPUT | \
M2M_CTRL_DREQP_LOWLEVEL
#define USB_PIN_CONFIG USB_DMAHW_EOT_ACTIVE_LOW | \
USB_DMAHW_ACK_ACTIVE_LOW | \
USB_DMAHW_DREQ_ACTIVE_LOW
#endif
UFN_GENERATE_DPCURSETTINGS(UFN_DEFAULT_DPCURSETTINGS_NAME,
_T("Interrupts"), _T("Power"), _T(""), _T(""),
DBG_ERROR | DBG_INIT);
#define REG_ALIGN_OFFSET 1
#define UDC_REG_PRIORITY_VAL _T("Priority256")
#define UDC_DMA_ENABLE_VAL _T("DMAEnable")
typedef struct _EP_STATUS {
DWORD dwEndpoint;
BOOL fInitialized;
unsigned short wMaxPacketSize;
unsigned short bmAttributes;
PSTransfer pTransfer;
CRITICAL_SECTION cs;
#ifdef DEBUG
LPCTSTR pszType;
#endif
} EP_STATUS, *PEP_STATUS;
#define LOCK_ENDPOINT(peps) EnterCriticalSection(&peps->cs)
#define UNLOCK_ENDPOINT(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 / 4)
static int g_dma_enabled = 0;
static const EP_STATUS g_rgEpStatus[] = {
{ (0<<1) , },
{ (1<<1) , },
{ (2<<1) , },
{ (3<<1) , },
{ (4<<1) , },
{ (5<<1) , },
{ (6<<1) , },
{ (7<<1) , }
};
#define ENDPOINT_COUNT dim(g_rgEpStatus)
#define EP_VALID(x) ((x) < ENDPOINT_COUNT)
#define DEFAULT_PRIORITY 108
//#define DUMP_BUFFER
#ifdef DUMP_BUFFER
void DumpHexBuf(PUCHAR pBuf, DWORD Count)
{
#define ENTRIES_PER_LINE 16
DWORD i,j;
for (i = 0; i < Count; i += ENTRIES_PER_LINE)
{
RETAILMSG(1,(TEXT("\n0x%08X "),i));
for (j = 0; j < ENTRIES_PER_LINE; j++)
{
if ((i+j) >= Count)
RETAILMSG(1,(TEXT(" ")));
else
RETAILMSG(1,(TEXT("%02X "), pBuf[i+j]));
}
for (j = 0; j < ENTRIES_PER_LINE; j++)
{
if ((i+j) >= Count)
{
break;
}
else
{
if ( ((pBuf[i+j] & 0xff)<0x20) || ((pBuf[i+j] & 0xff)> 0x7f) )
RETAILMSG(1, (TEXT(".")));
else
RETAILMSG(1, (TEXT("%c"), pBuf[i+j]));
}
}
}
RETAILMSG(1, (TEXT("\n")));
}
#else
#define DumpHexBuf(x,y)
#endif
enum DEVICE_STATUS {
DS_DETACHED = 0,
DS_ATTACHED,
DS_POWERED,
DS_DEFAULT,
DS_ADDRESSED,
DS_CONFIGURED,
DS_SUSPENDED,
};
typedef struct _USBSLAVE_PDD_CONTEXT
{
DWORD dwSig;
PBYTE pbConfigAddr;
PBYTE pbFifoAddr;
PVOID pvMddContext;
HANDLE hIST;
HANDLE hevInterrupt;
DWORD dwISTPriority;
BOOL fRunning;
CRITICAL_SECTION csSharedRegisterAccess;
DWORD dwSysIntr;
HANDLE hISRHandler;
BOOL fSpeedReported;
volatile BOOL fExitIST;
BOOL fRestartIST;
BOOL fForceFullSpeed;
BOOL fAttached;
PFN_UFN_MDD_NOTIFY pfnNotify;
HANDLE hBusAccess;
CEDEVICE_POWER_STATE cpsCurrent;
DEVICE_STATUS DeviceStatus;
EP_STATUS rgEpStatus[ENDPOINT_COUNT];
//
unsigned long pusTemIOBASE;
unsigned char ucSetupFlags;
unsigned long pusDMAVirtualBASE;
unsigned long pusDMAPhysicalBASE;
} USBSLAVE_PDD_CONTEXT, *PUSBSLAVE_PDD_CONTEXT;
//
//
//
//*****************************************************************************
//
//DelayuS delay some us time
//
//******************************************************************************
void DelayuS(ULONG ulMicroSec)
{
LARGE_INTEGER liStart, liCurrent;
BOOL b;
b = QueryPerformanceCounter(&liStart);
ASSERT(b);
do
{
Sleep(0);
b = QueryPerformanceCounter(&liCurrent);
ASSERT(b);
} while((liStart.QuadPart + (LONGLONG)ulMicroSec) >=liCurrent.QuadPart);
}
//****************************************************************************
//
// USBStallEndpoint stalls or un-stalls the specified endpoint.
//
//****************************************************************************
void
USBStallEndpoint( PUSBSLAVE_PDD_CONTEXT pContext,unsigned long ulEndpoint, unsigned long bStall)
{
volatile unsigned short *pIOBASE = (unsigned short *)pContext->pusTemIOBASE;
if(bStall)
{
pIOBASE[HwUSBEndpointIndex >> REG_ALIGN_OFFSET] = (unsigned short)(ulEndpoint) ;
pIOBASE[HwUSBEndpointControl >> REG_ALIGN_OFFSET] |= USB_EPCONTROL_STALL;
pIOBASE[HwUSBEndpointType >> REG_ALIGN_OFFSET] &= ~USB_EPTYPE_ENABLE;
pIOBASE[HwUSBEndpointType >> REG_ALIGN_OFFSET] |= USB_EPTYPE_ENABLE;
}
else
{
if(0 == ulEndpoint)
{
pIOBASE[HwUSBEndpointIndex >> REG_ALIGN_OFFSET] = (unsigned short)(ulEndpoint) ;
pIOBASE[HwUSBEndpointControl >> REG_ALIGN_OFFSET] &= ~USB_EPCONTROL_STALL;
}
else
{
pIOBASE[HwUSBEndpointIndex >> REG_ALIGN_OFFSET] = (unsigned short)(ulEndpoint) ;
pIOBASE[HwUSBEndpointControl >> REG_ALIGN_OFFSET] &= ~USB_EPCONTROL_STALL;
pIOBASE[HwUSBEndpointType >> REG_ALIGN_OFFSET] &= ~USB_EPTYPE_ENABLE;
pIOBASE[HwUSBEndpointType >> REG_ALIGN_OFFSET] |= USB_EPTYPE_ENABLE;
}
}
}
#define SET TRUE
#define CLEAR FALSE
// Retrieve the endpoint status structure.
inline
static
PEP_STATUS
GetEpStatus(
PUSBSLAVE_PDD_CONTEXT pContext,
DWORD dwEndpoint
)
{
PEP_STATUS peps = &pContext->rgEpStatus[dwEndpoint];
return peps;
}
static inline VOID
EnableEndpointInterrupt(
PUSBSLAVE_PDD_CONTEXT pContext,
DWORD dwEndpoint
)
{
volatile unsigned short *pIOBASE = (unsigned short *)pContext->pusTemIOBASE;
unsigned long ulIntMask;
DelayuS(500);
ulIntMask = (0xC00<< (dwEndpoint & (~1)) );
pIOBASE[HwUSBIntEnable >> REG_ALIGN_OFFSET] |= (unsigned short)ulIntMask;
pIOBASE[(HwUSBIntEnable >> REG_ALIGN_OFFSET) + 1] |= (unsigned short)(ulIntMask>>16);
}
static inline VOID
DisableEndpointInterrupt(
PUSBSLAVE_PDD_CONTEXT pContext,
DWORD dwEndpoint
)
{
volatile unsigned short *pIOBASE = (unsigned short *)pContext->pusTemIOBASE;
unsigned long ulIntMask;
DelayuS(500);
ulIntMask = (0xC00<< (dwEndpoint & (~1)) );
pIOBASE[HwUSBIntEnable >> REG_ALIGN_OFFSET] &= (unsigned short)(~ulIntMask);
pIOBASE[(HwUSBIntEnable >> REG_ALIGN_OFFSET) + 1] &= (unsigned short)((~ulIntMask)>>16);
}
//****************************************************************************
//
// InitEndpoint.
//
//****************************************************************************
void InitEndpoint(
PVOID pvPddContext,
PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc,
DWORD dwEndpoint
)
{
PUSBSLAVE_PDD_CONTEXT pContext = (PUSBSLAVE_PDD_CONTEXT) pvPddContext;
volatile unsigned short *pIOBASE = (unsigned short *)pContext->pusTemIOBASE;
PEP_STATUS peps = GetEpStatus(pContext, dwEndpoint);
if(!peps->fInitialized) return;
LOCK_ENDPOINT(peps);
if(USB_DIRECTION_IN(pEndpointDesc->bEndpointAddress))
{
peps->dwEndpoint |= USB_ENDPOINT_DIR_IN;
}
else
{
peps->dwEndpoint |= USB_ENDPOINT_DIR_OUT;
}
// Write the packet size and count of transactions / microframe
pIOBASE[HwUSBEndpointIndex >> REG_ALIGN_OFFSET] = (unsigned short) (peps->dwEndpoint);
pIOBASE[HwUSBEndpointType >> REG_ALIGN_OFFSET] = 0xff00;
pIOBASE[HwUSBEndpointMaxPacketSize >> REG_ALIGN_OFFSET] = (unsigned short) peps->wMaxPacketSize;
// Configure and enable the endpoint
pIOBASE[HwUSBEndpointIndex >> REG_ALIGN_OFFSET] = (unsigned short) (peps->dwEndpoint);
pIOBASE[HwUSBEndpointType >> REG_ALIGN_OFFSET] = (
USB_EPTYPE_NO_EMPTY |
USB_EPTYPE_DOUBLE_BUFFER |
peps->bmAttributes |
USB_EPTYPE_ENABLE
);
// Clear FIFO
pIOBASE[HwUSBEndpointIndex >> REG_ALIGN_OFFSET] = (unsigned short) (peps->dwEndpoint);
pIOBASE[HwUSBEndpointControl >> REG_ALIGN_OFFSET] |= USB_EPCONTROL_CLEAR;
UNLOCK_ENDPOINT(peps);
}
//****************************************************************************
//
// USBEnable configures the ISP1581 device.
//
//****************************************************************************
void
USBChipEnable(PUSBSLAVE_PDD_CONTEXT pContext, BOOL bSoftReset)
{
unsigned long dwIntMask;
volatile unsigned short *pIOBASE = (unsigned short *)pContext->pusTemIOBASE;
if(bSoftReset)
{
pIOBASE[HwUSBMode >> REG_ALIGN_OFFSET] = USB_MODE_SOFT_RESET;
Sleep(50);
}
//
//Enable USB
//
pIOBASE[HwUSBAddress >> REG_ALIGN_OFFSET] |= USB_ADDRESS_DEVICE_ENABLE;
// Sleep(10);
//
// Configure the ISP1581 and enable the SoftConnect pull-up.
//
pIOBASE[HwUSBMode >> REG_ALIGN_OFFSET]=0;/*disable the ,and SoftConnect pull-down*/
pIOBASE[HwUSBMode >> REG_ALIGN_OFFSET] |=
USB_MODE_CLOCK_ON |
USB_MODE_WAKE_UP_CS |
USB_MODE_INT_ENABLE |
USB_MODE_SOFT_CONNECT;/*0x09=|1001|*/
// Sleep(10);
//
// Configure the interrupt line.
//
pIOBASE[HwUSBIntConfig >> REG_ALIGN_OFFSET] |=
USB_INTCONFIG_CDBGMOD_ACK |
USB_INTCONFIG_DDBGMODIN_ACK |
USB_INTCONFIG_DDBGMODOUT_ACK |
0x01;
//
// Enable the interrupts for the bulk endpoints.
//
dwIntMask =
// USB_INT_EP7_RX |
// USB_INT_EP7_TX |
// USB_INT_EP6_RX |
// USB_INT_EP6_TX |
// USB_INT_EP5_RX |
// USB_INT_EP5_TX |
// USB_INT_EP4_RX |
// USB_INT_EP4_TX |
// USB_INT_EP3_RX |
// USB_INT_EP3_TX |
USB_INT_EP2_RX |
USB_INT_EP2_TX |
USB_INT_EP1_RX |
USB_INT_EP1_TX |
USB_INT_EP0_RX |
USB_INT_EP0_TX |
USB_INT_HS_STATUS |
USB_INT_EP0_SETUP |
USB_INT_BUS_RESET ;
//|USB_INT_DMA);
pIOBASE[HwUSBIntEnable >> REG_ALIGN_OFFSET] = (unsigned short) dwIntMask;
pIOBASE[(HwUSBIntEnable >> REG_ALIGN_OFFSET) + 1] = (unsigned short) (dwIntMask>>16);
//
// Reset 1581 dma core
//
pIOBASE[HwUSBDMACommand >> REG_ALIGN_OFFSET] = USB_DMACOMMAND_RESET_DMA;
//
// Set DMA ep to an unused endpoint.
//
pIOBASE[HwUSBDMAEndpoint >> REG_ALIGN_OFFSET] = USB_DMAEP_SEVEN_OUT;
//
// init 1581 DMA
//
pIOBASE[HwUSBDMAConfig >> REG_ALIGN_OFFSET] =
(USB_DMACONFIG_BURST_1|
USB_DMACONFIG_MODE_DACK |
USB_DMACONFIG_WIDTH_16);
pIOBASE[HwUSBDMAHardware >> REG_ALIGN_OFFSET] =
(USB_DMAHW_ENDIAN_NORMAL |
USB_PIN_CONFIG |
USB_DMAHW_WRITE_ACTIVE_LOW |
USB_DMAHW_READ_ACTIVE_LOW);
//
// enable 1581 DMA interrupt
//
pIOBASE[HwUSBDMAIntEnable >> REG_ALIGN_OFFSET] = 0x0D00;
}
static
VOID
ResetDevice(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -