📄 pdd.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//
// Copyright (c) Intrinsyc Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Intrinsyc 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 LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
// File: pdd.c
//
// This file contains USB function PDD implementation. Actual implementation
// doesn't use DMA transfers and it doesn't support ISO endpoints.
//
#include <windows.h>
#include <nkintr.h>
#include <pm.h>
#include <ceddk.h>
#include <ceddkex.h>
#include <cebus.h>
#include <usbfntypes.h>
#include <usbfn.h>
#include <omap2420.h>
#include <devload.h>
#include <oal_intr.h>
extern BOOL InitializeHardware();
void PDD_Dump(OMAP2420_USBD_REGS * pPddRegs);
static void printUsbdDriverSettings();
//------------------------------------------------------------------------------
//
// Define: USBD_IRQ_MASK
//
// This is composite interrupt mask used in driver.
//
#define USBD_IRQ_MASK (USBD_IRQ_EN_EP_RX | USBD_IRQ_EN_EP_TX | USBD_IRQ_EN_DS_CHG | USBD_IRQ_EN_EP0)
//------------------------------------------------------------------------------
//
// Type: USBFN_EP
//
// Internal PDD structure which holds info about endpoint direction,
// max packet size and active transfer.
//
typedef struct
{
WORD maxPacketSize;
BOOL dirRx;
BOOL fZeroLengthNeeded;
STransfer *pTransfer;
} USBFN_EP;
//------------------------------------------------------------------------------
//
// Type: USBFN_PDD
//
// Internal PDD context structure.
//
typedef struct
{
DWORD memBase;
DWORD memLen;
DWORD priority256;
DWORD irq[3];
VOID *pMddContext;
PFN_UFN_MDD_NOTIFY pfnNotify;
HANDLE hParentBus;
OMAP2420_USBD_REGS *pUSBDRegs;
DWORD sysIntr;
HANDLE hIntrEvent;
BOOL exitIntrThread;
HANDLE hIntrThread;
CEDEVICE_POWER_STATE m_NewPowerState;
CEDEVICE_POWER_STATE m_CurrentPowerState;
DWORD devState;
BOOL selfPowered;
BOOL setupDirRx;
WORD setupCount;
HANDLE hSetupEvent;
CRITICAL_SECTION epCS;
USBFN_EP ep[USBD_EP_COUNT];
BOOL fakeDsChange; // To workaround MDD problem
} USBFN_PDD;
//------------------------------------------------------------------------------
// Device registry parameters
static const DEVICE_REGISTRY_PARAM g_deviceRegParams[] = {
{
L"MemBase", PARAM_DWORD, TRUE, offset(USBFN_PDD, memBase),
fieldsize(USBFN_PDD, memBase), NULL
}, {
L"MemLen", PARAM_DWORD, TRUE, offset(USBFN_PDD, memLen),
fieldsize(USBFN_PDD, memLen), NULL
}, {
L"Irq", PARAM_MULTIDWORD, TRUE, offset(USBFN_PDD, irq),
fieldsize(USBFN_PDD, irq), NULL
}, {
L"Priority256", PARAM_DWORD, FALSE, offset(USBFN_PDD, priority256),
fieldsize(USBFN_PDD, priority256), (void *)101
}
};
//------------------------------------------------------------------------------
//
// Global: dpCurSettings
//
#ifdef DEBUG
#define ZONE_INTERRUPTS DEBUGZONE(8)
#define ZONE_POWER DEBUGZONE(9)
#define ZONE_PDD DEBUGZONE(15)
extern DBGPARAM dpCurSettings = {
L"UsbFn", {
L"Error", L"Warning", L"Init", L"Transfer",
L"Pipe", L"Send", L"Receive", L"USB Events",
L"Interrupts", L"Power", L"", L"",
L"Function", L"Comments", L"", L"PDD"
},
DBG_ERROR|DBG_INIT
};
#endif
//------------------------------------------------------------------------------
//
// Function: Log2
//
// Trivial log with base 2 function used in EP configuration.
//
static DWORD Log2(DWORD value)
{
DWORD rc = 0;
while (value != 0)
{
value >>= 1;
rc++;
}
if (rc > 0)
{
rc--;
}
return rc;
}
// Routines to synchronize access to the indexed endpoint registers.
#ifdef DEBUG
static int InEp = 0;
#endif // DEBUG
static VOID Select(USBFN_PDD *pPdd, DWORD dwVal)
{
EnterCriticalSection(&pPdd->epCS);
ASSERT(InEp++ >= 0);
OUTREG32(&pPdd->pUSBDRegs->EP_NUM, dwVal);
}
static VOID SelectSetup(USBFN_PDD *pPdd)
{
// Select setup FIFO (this clears USBD_INT_SETUP flag)
Select(pPdd, USBD_EP_NUM_SETUP);
}
static VOID SelectEp(USBFN_PDD *pPdd, DWORD epNum)
{
Select(pPdd, USBD_EP_NUM_SEL | epNum);
}
static VOID Deselect(USBFN_PDD *pPdd, DWORD dwValue)
{
OUTREG32(&pPdd->pUSBDRegs->EP_NUM, dwValue);
ASSERT(--InEp >= 0);
LeaveCriticalSection(&pPdd->epCS);
}
static VOID DeselectSetup(USBFN_PDD *pPdd)
{
Deselect(pPdd, 0);
}
static VOID DeselectEp(USBFN_PDD *pPdd, DWORD epNum)
{
Deselect(pPdd, epNum);
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_PowerDown
//
// LEGACY FUNCTION: Do not use!
//
// This function is provided for backwards compatibility only.
// It is included in the USB Client Driver's function table (which gets
// exported to the rest of the operating system), and thus other modules
// may be expecting it to be a callable function.
//
VOID WINAPI UfnPdd_PowerDown(VOID *pPddContext)
{
}
//------------------------------------------------------------------------------
//
// Function: UfnPdd_PowerUp
//
// LEGACY FUNCTION: Do not use!
//
// This function is provided for backwards compatibility only.
// It is included in the USB Client Driver's function table (which gets
// exported to the rest of the operating system), and thus other modules
// may be expecting it to be a callable function.
//
VOID WINAPI UfnPdd_PowerUp(VOID *pPddContext)
{
}
////////////////////////////////////////////////////////////////////////////////
//
// Function: UpdateDevicePower()
//
// Purpose: Puts the USB Client Device in the Power State provided in *pPdd
//
// Parameters: pPdd = Pointer to USBFN_PDD Structure containing device info
//
// Returns: TRUE if the power state was successfully updated,
// or FALSE if it was not.
//
// Notes: Power States D0, D1, and D2 are considered "on".
// Power States D3 and D4 are considered "off".
//
////////////////////////////////////////////////////////////////////////////////
//
BOOL UpdateDevicePower(USBFN_PDD * pPdd)
{
BOOL bRV = TRUE;
DWORD regBit = 0x00000001;
DWORD cbRet = 0x00000000;
if (pPdd != NULL)
{
DEBUGMSG(ZONE_POWER, (L"USBD UpdateDevicePower() - "
L"Changing Power State from D%u to D%u\r\n", (int)(pPdd->m_CurrentPowerState), (int)(pPdd->m_NewPowerState)));
switch (pPdd->m_CurrentPowerState)
{
case D0:
case D1:
case D2:
if (SetDevicePowerState(pPdd->hParentBus, pPdd->m_NewPowerState, NULL))
{
if ((pPdd->m_NewPowerState == D3) || (pPdd->m_NewPowerState == D4))
{
DEBUGMSG(ZONE_POWER, (L"USBD UpdateDevicePower() - "
L"Turning the Power Off\r\n"));
// Disable the USBD Transceiver
if (pPdd->pUSBDRegs)
{
CLRREG32(&pPdd->pUSBDRegs->SYSCON1, USBD_SYSCON1_PULLUP_EN);
}
// Turn off the USBD Clocks
KernelIoControl(IOCTL_ICLK2_DIS, (VOID *)®Bit, sizeof(DWORD), NULL, 0, &cbRet);
KernelIoControl(IOCTL_FCLK2_DIS, (VOID *)®Bit, sizeof(DWORD), NULL, 0, &cbRet);
}
}
else
{
bRV = FALSE;
}
break;
case D3:
case D4:
if (SetDevicePowerState(pPdd->hParentBus, pPdd->m_NewPowerState, NULL))
{
if ((pPdd->m_NewPowerState == D0) || (pPdd->m_NewPowerState == D1) || (pPdd->m_NewPowerState == D2))
{
DEBUGMSG(ZONE_POWER, (L"USBD UpdateDevicePower() - "
L"Turning the Power On\r\n"));
// Turn on the USBD Clocks
KernelIoControl(IOCTL_ICLK2_ENB, (VOID *)®Bit, sizeof(DWORD), NULL, 0, &cbRet);
KernelIoControl(IOCTL_FCLK2_ENB, (VOID *)®Bit, sizeof(DWORD), NULL, 0, &cbRet);
// Enable the USBD Transceiver
if (pPdd->pUSBDRegs)
{
SETREG32(&pPdd->pUSBDRegs->SYSCON1, USBD_SYSCON1_PULLUP_EN);
}
}
}
else
{
bRV = FALSE;
}
break;
default:
bRV = FALSE;
break;
}
if (bRV)
{
pPdd->m_CurrentPowerState = pPdd->m_NewPowerState;
}
}
return bRV;
}
//------------------------------------------------------------------------------
//
// Function: SetupEvent
//
// This function handles setup packet interrupts.
//
static VOID SetupEvent(USBFN_PDD *pPdd)
{
OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
DWORD rawFifoData = 0x00000000;
WORD data[4];
USB_DEVICE_REQUEST *pSetup = (USB_DEVICE_REQUEST*)data;
do {
// Select setup FIFO (this clears USBD_INT_SETUP flag)
SelectSetup(pPdd);
// Read setup data
rawFifoData = INREG32(&pUSBDRegs->DATA);
data[0] = (WORD)(rawFifoData & 0x0000FFFF);
rawFifoData = INREG32(&pUSBDRegs->DATA);
data[1] = (WORD)(rawFifoData & 0x0000FFFF);
rawFifoData = INREG32(&pUSBDRegs->DATA);
data[2] = (WORD)(rawFifoData & 0x0000FFFF);
rawFifoData = INREG32(&pUSBDRegs->DATA);
data[3] = (WORD)(rawFifoData & 0x0000FFFF);
// Deselect setup FIFO
DeselectSetup(pPdd);
} while ((INREG32(&pUSBDRegs->IRQ_SRC) & USBD_INT_SETUP) != 0);
/*
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - data[0] = 0x%04X\r\n", data[0]));
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - data[1] = 0x%04X\r\n", data[1]));
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - data[2] = 0x%04X\r\n", data[2]));
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - data[3] = 0x%04X\r\n", data[3]));
// Make sure we are interpreting the above data correctly.
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - pSetup->bmRequestType = 0x%02X\r\n", pSetup->bmRequestType));
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - pSetup->bRequest = 0x%02X\r\n", pSetup->bRequest));
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - pSetup->wValue = 0x%04X\r\n", pSetup->wValue));
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - pSetup->wIndex = 0x%04X\r\n", pSetup->wIndex));
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - pSetup->wLength = 0x%04X\r\n", pSetup->wLength));
*/
// Save setup packet direction & size for later use
pPdd->setupDirRx = (pSetup->bmRequestType & 0x80) == 0;
pPdd->setupCount = pSetup->wLength;
// MDD doesn't call PDD back on configure message
if ((pSetup->bmRequestType == 0) && (pSetup->bRequest == USB_REQUEST_SET_CONFIGURATION))
{
if (pSetup->wValue != 0)
{
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - "
L"Changing USB Device state to Configured\r\n"));
// Move device to configured state
OUTREG32(&pUSBDRegs->SYSCON2, USBD_SYSCON2_DEV_CFG);
// Set self powered flag
if (pPdd->selfPowered)
{
DEBUGMSG(ZONE_INIT, (L"USBD SetupEvent() - "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -