?? sc2410_usb_ser.c
字號:
/*+
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.
Copyright (c) 2001. Samsung Electronics, co. ltd All rights reserved.
Module Name:
Abstract:
S3C2410 USB function(ACTIVE SYNC) device driver (Wrapper layer)
rev:
2003.3.19 : updated for USB-DMA (purnnamu)
2002.5.7 : Add to s3c2410_code (Seung-han, Lim)
2002.1.22 : First release/no error recovery (kwangyoon LEE, kwangyoon@samsung.com)
Notes:
*/
/* MiTAC Int'l Corp. 2002
$release notes
Modifier sign date Description
================================================================================
Jocky jocky0308 03/08/2006 Do not set too many events.
Ed Yeh edyeh1108 11/8/2005 Add AC-in event.
Jonathan Jonathan01_0915 09/15/2005 Modify S2440 USB Driver to PNA500
*/
#include <windows.h>
#include <types.h>
#include <ceddk.h>
#include <memory.h>
#include <notify.h>
#include <serhw.h>
#include "S2410.h"
#include <SC2410_usb_hw.h>
#include <SC2410_usb_ser.h>
#include <nkintr.h>
#include <oalintr.h>
#include <devload.h>
#include <windev.h>
#undef ZONE_INIT
#include <serdbg.h>
#include <celog.h>
#include <drv_glob.h> //:-)
#include "drvlib.h" //Jonathan01_0915
extern VOID SerialEventHandler(PVOID pHead);
extern void msWait(unsigned msVal);
extern volatile USBD_GLOBALS *usbdShMem; //:-)
//Jonathan01_0915 start
volatile PDRIVER_GLOBALS pDriverGlobals = NULL;
volatile IOPreg *s2410IOP = NULL;
volatile CLKPWRreg *s2410CLKPW = NULL;
//Jonathan01_0915 end
static HANDLE hUSBAcInIntr = NULL; //edyeh1108
__inline static VOID
SignalRemoval( PSER_INFO pHWHead )
{
pHWHead->ModemStatus &= ~MS_RLSD_ON;
EvaluateEventFlag(pHWHead->pMddHead, EV_RLSD);
}
static
DWORD WINAPI SerEventThread(PSER_INFO pHWHead)
{
ULONG WaitReturn;
static HWND fgp=NULL, prev_fgp = NULL;
static HWND dialog_hwnd = NULL;
static ULONG firstplug = 0, toretry = 0;
static PROCESS_INFORMATION pi_usbcnect, pi_repllog;
DEBUGMSG(1, (TEXT("++SerEventThread\r\n")));
DEBUGMSG(1, (TEXT("Spinning in dispatch thread %X\n\r"), pHWHead));
while (!pHWHead->pDispatchThread)
Sleep(20);
while (!pHWHead->KillRxThread) {
DEBUGMSG (1, (TEXT("Event %X, Index %d, Int %d\r\n"),
pHWHead->hSerialEvent,
pHWHead->dwDevIndex,
pHWHead->pHWObj->dwIntID ));
// Ugly. We don't get an interrupt when we are unplugged from the
// bus, but we'd like to know when that happens. So we use a timeout
// on our interrupt wait. This effectively allows me to poll the SOF
// status, and if SOFs stop arriving, I'll assume we have been
// disconnected from the bus. Wait is last, allowing us to essentially
// spoof one interrupt right at startup.
// Only poll if we are opened and active. Otherwise no one cares
#ifdef POLL_FOR_DISCONNECT
if (pHWHead->cOpenCount && pHWHead->dConfIdx)
{
// DEBUGMSG(1, (TEXT("waitforsingleobject in up\r\n")));
WaitReturn = WaitForSingleObject(pHWHead->hSerialEvent, SC2410_USB_POLL_RATE);
// DEBUGMSG(1, (TEXT("waitforsingleobject in\r\n")));
}
else
#endif
{
//DEBUGMSG(1, (TEXT("waitforsingleobject out up\r\n")));
WaitReturn = WaitForSingleObject(pHWHead->hSerialEvent, INFINITE);
/*
DEBUGMSG(1, (TEXT("waitforsingleobject out\r\n")));
if (WaitReturn == WAIT_ABANDONED)
{
DEBUGMSG(1, (TEXT("WAIT_ABANDONED\r\n")));
}
if (WaitReturn == WAIT_OBJECT_0)
{
DEBUGMSG(1, (TEXT("WAIT_OBJECT_0\r\n")));
}
if (WaitReturn == WAIT_TIMEOUT)
{
DEBUGMSG(1, (TEXT("WAIT_TIMEOUT\r\n")));
}
if (WaitReturn == WAIT_FAILED)
{
DEBUGMSG(1, (TEXT("WAIT_FAILED\r\n")));
}
*/
}
SerialEventHandler(pHWHead->pMddHead);
InterruptDone(pHWHead->pHWObj->dwIntID);
}
DEBUGMSG (1, (TEXT("--SerEventThread %x exiting\r\n"), pHWHead));
return (0);
}
static
BOOL StartEventThread(PSER_INFO pHWHead)
{
// Initialize the interrupt to be associated with the hSerialEvent
// event. If this call fails, then another process has registered
// for the interrupt, so fail the init and set the hSerialEvent to NULL.
DEBUGMSG(1, (TEXT("Initializing interrupt 0x%X, 0x%X\n\r"),
pHWHead->pHWObj->dwIntID, pHWHead->hSerialEvent));
if (!InterruptInitialize(pHWHead->pHWObj->dwIntID, pHWHead->hSerialEvent, 0, 0))
{
DEBUGMSG(1, (TEXT("Error initializing interrupt\n\r")));
return (FALSE);
}
InterruptDone(pHWHead->pHWObj->dwIntID);
// Now set up the dispatch thread
pHWHead->KillRxThread = 0;
DEBUGMSG(1, (TEXT("Spinning thread%X\n\r"), pHWHead));
pHWHead->pDispatchThread = CreateThread(NULL,0, SerEventThread,
pHWHead, 0,NULL);
if (pHWHead->pDispatchThread == NULL)
{
DEBUGMSG(1, (TEXT("Error creating Event thread (%d)\n\r"), GetLastError()));
return (FALSE);
}
DEBUGMSG (1, (TEXT("Created Event thread %X\r\n"), pHWHead->pDispatchThread));
DEBUGMSG (1, (TEXT("About to set priority\r\n")));
CeSetThreadPriority(pHWHead->pDispatchThread, DEFAULT_THREAD_PRIO);
DEBUGMSG (1, (TEXT("Back from setting priority\r\n")));
return (TRUE);
}
/***************************************************************
@doc OEM
@func VOID | SerSetBaudRate |
* This routine sets the baud rate of the device.
* Not exported to users, only to driver.
*
@rdesc None.
****************************************************************/
static
BOOL SerSetBaudRate( PVOID pHead, // @parm PVOID returned by SerInit
ULONG BaudRate ) // @parm ULONG representing decimal baud rate.
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
DEBUGMSG(1, (TEXT("SerSetBaudRate\r\n")));
// Baudrate is meaningless. Just be agreeable and say we did it.
return (TRUE);
}
/****************************************************************
@doc INTERNAL
@func VOID | SerUSB_InternalMapRegisterAddresses |
This routine maps the ASIC registers.
It's an artifact of this
implementation.
@rdesc None.
****************************************************************/
static
void SerUSBInternalMapRegisterAddresses( PSER_INFO pHWHead )
{
PUCHAR pVMem;
BOOL bMapReturn;
ULONG err = 0;
DEBUGMSG(1, (TEXT("++SerUSBInternalMapRegisterAddresses\r\n")));
// Map CSR registers.
pVMem = (PUCHAR)VirtualAlloc(0, PAGE_SIZE*2, MEM_RESERVE, PAGE_NOACCESS);
if (pVMem)
{
DEBUGMSG(1, (TEXT("VirtualAlloc Succeeded\r\n")));
bMapReturn = VirtualCopy( pVMem,
(LPVOID)pHWHead->dwIOBase,
PAGE_SIZE,
PAGE_READWRITE | PAGE_NOCACHE );
if (!bMapReturn)
{
err = GetLastError();
DEBUGMSG(1, (TEXT("Virtual Copy: Serial SPACE FAILED\r\n")));
}
pVMem = (BYTE *)pVMem;
pHWHead->pUSBCtrlAddr=(volatile struct udcreg *)((BYTE *)pVMem + 0x140); // offset
bMapReturn = VirtualCopy( pVMem+PAGE_SIZE,
(LPVOID)IOP_BASE,
PAGE_SIZE,
PAGE_READWRITE | PAGE_NOCACHE );
if (!bMapReturn)
{
err = GetLastError();
DEBUGMSG(1, (TEXT("Virtual Copy: IOP SPACE FAILED\r\n")));
}
pHWHead->pIrqCtrlAddr=(volatile IOPreg *)(pVMem+PAGE_SIZE);
bMapReturn = VirtualCopy( pVMem+PAGE_SIZE,
(LPVOID)CLKPWR_BASE,
PAGE_SIZE,
PAGE_READWRITE | PAGE_NOCACHE );
if (!bMapReturn)
{
err = GetLastError();
DEBUGMSG(1, (TEXT("Virtual Copy: CLKPWR SPACE FAILED\r\n")));
}
pHWHead->pCLKPWR = (volatile CLKPWRreg *)(pVMem+PAGE_SIZE);
} else {
DEBUGMSG(1, (TEXT("Virtual Alloc: FAILED\r\n")));
}
DEBUGMSG(1, (TEXT("VirtualCopy Succeeded, pVMem:%x\r\n"), pVMem));
DEBUGMSG(1, (TEXT("--SerUSBInternalMapRegisterAddresses\r\n")));
}
static
BOOL SerSetIRBaudRate( PSER_INFO pHWHead, ULONG baud ) // @parm baud rate - ignored
{
DEBUGMSG(1, (TEXT("Serial set IR Baud %d\r\n"), baud));
// We don't support IR
return (FALSE);
}
/*******************************************************************************
Routine:
Ser_GetRegistryData
Description:
Take the registry path provided to COM_Init and use it to find this
requested comm port's DeviceArrayIndex, the IOPort Base Address, and the
Interrupt number.
Arguments:
LPCTSTR regKeyPath the registry path passed in to COM_Init.
Return Value:
-1 if there is an error.
******************************************************************************/
static
BOOL Ser_GetRegistryData(PSER_INFO pHWHead, LPCTSTR regKeyPath)
{
#define GCI_BUFFER_SIZE 256
LONG regError;
HKEY hKey;
TCHAR devKeyPath[GCI_BUFFER_SIZE];
DWORD dwDataSize = GCI_BUFFER_SIZE;
DEBUGMSG(1,
(TEXT("Ser_GetRegistryData Try to open %s\r\n"),regKeyPath));
// We've been handed the name of a key in the registry that was generated
// on the fly by device.exe. We're going to open that key and pull from it
// a value that is the name of this serial port's real key. That key
// will have the DeviceArrayIndex that we're trying to find.
regError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
regKeyPath,
0,
KEY_ALL_ACCESS,
&hKey);
if (regError != ERROR_SUCCESS)
{
DEBUGMSG(1,(TEXT("Failed to open %s, Error 0x%X\r\n"),regKeyPath,regError));
return (FALSE);
}
regError = RegQueryValueEx( hKey,
DEVLOAD_DEVKEY_VALNAME,
NULL,
NULL,
(LPBYTE)devKeyPath,
&dwDataSize);
// We're done with that registry key, so close it.
RegCloseKey (hKey);
if (regError != ERROR_SUCCESS)
{
DEBUGMSG(1, (TEXT("Failed to find data at %s\\%s, Error 0x%X\r\n"),
regKeyPath, DEVLOAD_DEVKEY_VALNAME, regError));
return (FALSE);
}
DEBUGMSG(1, (TEXT("Try to open %s\r\n"), devKeyPath));
regError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
devKeyPath,
0,
KEY_ALL_ACCESS,
&hKey);
if (regError != ERROR_SUCCESS)
{
DEBUGMSG(1,(TEXT("Failed to open %s, Error 0x%X\r\n"), devKeyPath, regError));
return (FALSE);
}
// Okay, we're finally ready to try and load our registry data.
dwDataSize = SC2410USB_REG_DEVINDEX_VAL_LEN;
regError = RegQueryValueEx(hKey,
SC2410USB_REG_DEVINDEX_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwDevIndex),
&dwDataSize);
if (regError == ERROR_SUCCESS)
{
dwDataSize = SC2410USB_REG_IRQ_VAL_LEN;
regError = RegQueryValueEx( hKey,
SC2410USB_REG_IRQ_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwIRQ),
&dwDataSize );
}
if (regError == ERROR_SUCCESS)
{
dwDataSize = SC2410USB_REG_IOBASE_VAL_LEN;
regError = RegQueryValueEx( hKey,
SC2410USB_REG_IOBASE_VAL_NAME,
NULL,
NULL,
(LPBYTE)(&pHWHead->dwIOBase),
&dwDataSize);
}
if (regError == ERROR_SUCCESS)
{
dwDataSize = SC2410USB_REG_IOLEN_VAL_LEN;
regError = RegQueryValueEx( hKey,
SC2410USB_REG_IOLEN_VAL_NAME,
NULL,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -