SER2440_HW.C
资源名称:SMDK2440.rar [点击查看]
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:68k
源码类别:
Windows CE
开发平台:
Windows_Unix
- /*++
- 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) 1995-2000 Microsoft Corporation. All rights reserved.
- Copyright (c) 2001-2002 SAMSUNG Electronics Corporation. All rights reserved.
- Author hmseo@sec.samsung.com (SAMSUNG Electronics)
- Module Name:
- ser2440_hw.c
- Abstract:
- This file implements the standard device specific functions for a S3C2440
- based serial device.
- Functions:
- SER_RegAlloc
- SER_VirtualAlloc
- SER_VirtualFree
- ReadLSR
- ReadMSR
- ShowSerialRegisters
- ClearPendingInts
- S2440_SetIrDAIOP
- S2440_SetSerialIOP
- S2440_SetIOP
- SL_Open
- SL_Close
- SL_Init
- SL_PostInit
- SL_Deinit
- SL_ClearDTR
- SL_SetDTR
- SL_ClearRTS
- SL_SetRTS
- SL_ClearBreak
- SL_SetBreak
- SetBaudRate
- SL_SetBaudRate
- SL_SetByteSize
- SL_SetParity
- SL_SetStopBits
- SL_GetRxBufferSize
- SL_GetRxStart
- SL_GetInterruptType
- SL_RxIntr
- SL_PutBytes
- SL_TxIntr
- SL_TxIntrEx
- SL_LineIntr
- SL_OtherIntr
- SL_ModemIntr
- SL_GetStatus
- SL_Reset
- SL_GetModemStatus
- SL_PurgeComm
- SL_XmitComChar
- SL_PowerOff
- SL_PowerOn
- SL_SetDCB
- SL_SetCommTimeouts
- SL_Ioctl
- --*/
- #define DEBUGMODE 0
- #define ZONE_FUNCTION 1
- #define USERDBG 1
- #define ZONE_WRITE 1
- #include <windows.h>
- #include <types.h>
- #include <ceddk.h>
- #include <memory.h>
- #include <serhw.h>
- #include <ser16550.h>
- #include <hw16550.h>
- #include <nkintr.h>
- #include <devload.h>
- #include <windev.h>
- #include <notify.h>
- #include <pm.h>
- #include <excpt.h>
- #include "pmplatform.h"
- #include "S2440.h"
- #include "ser2440.h"
- #define PUBLIC
- #define PRIVATE static
- PRIVATE volatile IOPreg * v_pIOPregs;
- PRIVATE volatile UART0reg * v_pUART0regs;
- PRIVATE volatile UART1reg * v_pUART1regs;
- PRIVATE volatile UART2reg * v_pUART2regs;
- PRIVATE volatile INTreg * v_pINTregs;
- PRIVATE volatile PWMreg * v_pPWMregs;
- VOID SER_VirtualFree(VOID);
- BOOL SER_VirtualAlloc(VOID);
- VOID ReadLSR(PVOID pHead);
- VOID ReadMSR(PVOID pHead);
- BOOL SL_SetByteSize(PVOID pHead, ULONG ByteSize);
- BOOL SL_SetStopBits(PVOID pHead, ULONG StopBits);
- BOOL SL_SetParity(PVOID pHead, ULONG Parity);
- BOOL SerPowerOn(PVOID pHead);
- BOOL SerPowerOff(PVOID pHead);
- #define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION
- PRIVATE PVOID
- SER_RegAlloc(PVOID addr, INT sz)
- {
- PVOID reg;
- reg = (PVOID)VirtualAlloc(0, sz, MEM_RESERVE, PAGE_NOACCESS);
- if (reg)
- {
- if (!VirtualCopy(reg, addr, sz, PAGE_READWRITE | PAGE_NOCACHE ))
- {
- VirtualFree(reg, sz, MEM_RELEASE);
- reg = NULL;
- }
- }
- return reg;
- }
- PRIVATE BOOL
- SER_VirtualAlloc(VOID)
- {
- BOOL r = FALSE;
- RETAILMSG(DEBUGMODE,(TEXT("::: SER_VirtualAlloc()rn")));
- do
- {
- v_pIOPregs = (volatile IOPreg *)SER_RegAlloc((PVOID)IOP_BASE, sizeof(IOPreg));
- if (v_pIOPregs == NULL)
- {
- ERRORMSG(1,(TEXT("For IOPreg: VirtualAlloc failed!rn")));
- break;
- }
- v_pUART0regs = (volatile UART0reg *)SER_RegAlloc((PVOID)UART0_BASE, sizeof(UART0reg));
- if (v_pUART0regs == NULL)
- {
- ERRORMSG(1,(TEXT("For UART0reg: VirtualAlloc failed!rn")));
- break;
- }
- v_pUART1regs = (volatile UART1reg *)SER_RegAlloc((PVOID)UART1_BASE, sizeof(UART1reg));
- if (v_pUART1regs == NULL)
- {
- ERRORMSG(1,(TEXT("For UART1reg: VirtualAlloc failed!rn")));
- break;
- }
- v_pUART2regs = (volatile UART2reg *)SER_RegAlloc((PVOID)UART2_BASE, sizeof(UART2reg));
- if (v_pUART2regs == NULL)
- {
- ERRORMSG(1,(TEXT("For UART2reg: VirtualAlloc failed!rn")));
- break;
- }
- v_pINTregs = (volatile INTreg *)SER_RegAlloc((PVOID)INT_BASE, sizeof(INTreg));
- if (v_pINTregs == NULL)
- {
- ERRORMSG(1,(TEXT("For INTregs: VirtualAlloc failed!rn")));
- break;
- }
- v_pPWMregs = (volatile PWMreg *)SER_RegAlloc((PVOID)PWM_BASE, sizeof(PWMreg));
- if (v_pPWMregs == NULL)
- {
- ERRORMSG(1,(TEXT("For PWMregs: VirtualAlloc failed!rn")));
- break;
- }
- r = TRUE;
- } while (0);
- if (!r)
- {
- SER_VirtualFree();
- RETAILMSG(DEBUGMODE,(TEXT("::: SER_VirtualAlloc() - Failrn")));
- }
- else
- {
- RETAILMSG(DEBUGMODE,(TEXT("::: SER_VirtualAlloc() - Successrn")));
- }
- return r;
- }
- PRIVATE void
- SER_VirtualFree(VOID)
- {
- RETAILMSG(DEBUGMODE,(TEXT("::: SER_VirtualFree()rn")));
- if (v_pIOPregs)
- {
- VirtualFree((PVOID)v_pIOPregs, sizeof(IOPreg), MEM_RELEASE);
- v_pIOPregs = NULL;
- }
- if (v_pUART0regs)
- {
- VirtualFree((PVOID)v_pUART0regs, sizeof(UART0reg), MEM_RELEASE);
- v_pUART0regs = NULL;
- }
- if (v_pUART1regs)
- {
- VirtualFree((PVOID)v_pUART1regs, sizeof(UART1reg), MEM_RELEASE);
- v_pUART1regs = NULL;
- }
- if (v_pUART2regs)
- {
- VirtualFree((PVOID)v_pUART2regs, sizeof(UART2reg), MEM_RELEASE);
- v_pUART2regs = NULL;
- }
- if (v_pINTregs)
- {
- VirtualFree((PVOID)v_pINTregs, sizeof(INTreg), MEM_RELEASE);
- v_pINTregs = NULL;
- }
- if (v_pPWMregs)
- {
- VirtualFree((PVOID)v_pPWMregs, sizeof(INTreg), MEM_RELEASE);
- v_pPWMregs = NULL;
- }
- }
- //
- // Reading the LSR clears most of its bits. So, we provide this wrapper,
- // which reads the register, records any interesting values, and
- // stores the current LSR contents in the shadow register.
- //
- //__inline
- VOID
- ReadLSR(PVOID pHead)
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- ULONG LineEvents = 0;
- ULONG LineStatus = 0;
- UCHAR tmp;
- pHWHead->CommErrors = 0; // Clear old errors each time
- RETAILMSG(DEBUGMODE, (TEXT("ReadLSR rn")));
- try
- {
- LineStatus = INREG(pHWHead,rUERSTAT);
- RETAILMSG(DEBUGMODE, (TEXT("Line Status Register : 0x%xrn"), LineStatus));
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // pHWHead->LSR = SERIAL_LSR_THRE;
- }
- if ( LineStatus & (COM2440_LSR_OE | COM2440_LSR_PE | COM2440_LSR_FE))
- {
- // Note: Its not wise to do debug msgs in here since they will
- // pretty much guarantee that the FIFO gets overrun.
- if ( LineStatus & COM2440_LSR_OE )
- {
- // When overrun error occurs, S2440 rURXH must be read.
- tmp = *(pHWHead->pUFRXH);
- pHWHead->DroppedBytes++;
- pHWHead->CommErrors |= CE_OVERRUN;
- LineEvents |= EV_ERR;
- }
- if ( LineStatus & COM2440_LSR_PE )
- {
- pHWHead->CommErrors |= CE_RXPARITY;
- LineEvents |= EV_ERR;
- }
- if ( LineStatus & COM2440_LSR_FE )
- {
- pHWHead->CommErrors |= CE_FRAME;
- LineEvents |= EV_ERR;
- }
- }
- if ( LineStatus & COM2440_LSR_BI )
- LineEvents |= EV_BREAK;
- // Let WaitCommEvent know about this error
- if ( LineEvents )
- pHWHead->EventCallback( pHWHead->pMddHead, LineEvents );
- }
- //
- // Reading the MSR clears many of its bits. So, we provide this wrapper,
- // which reads the register, records any interesting values, and
- // stores the current MSR contents in the shadow register.
- // Note that we always have DDCD and DCTS enabled, so if someone
- // wants to keep an eye on these lines, its OK to simply read the
- // shadow register, since if the value changes, the interrupt
- // will cause the shadow to be updated.
- //
- //__inline
- VOID
- ReadMSR(PVOID pHead)
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- ULONG Events = 0;
- ULONG msr, msr_DSR;
- RETAILMSG(DEBUGMODE, (TEXT("ReadMSR rn")));
- try
- {
- // read nCTS status
- msr = INREG(pHWHead,rUMSTAT);
- RETAILMSG(DEBUGMODE, (TEXT("Modem Status Register : 0x%xrn"), msr));
- // read nDSR status
- // - As you know this routine is valid only at the SMDK2440 board.
- if ( !pHWHead->UseIrDA )
- {
- if(*(pHWHead->rDSRport) & (1<<(pHWHead->DsrPortNum))) // Low active
- msr_DSR = 0;
- else
- msr_DSR = 1;
- }
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- msr = 0;
- }
- // Save the MSR value in a shadow
- pHWHead->MSR = msr;
- // For changes, we use callback to evaluate the event
- if (msr & COM2440_MSR_DCTS) // Delta CTS (SERIAL_MSR_DCTS)
- {
- Events |= EV_CTS;
- pHWHead->vUMSTAT |= COM2440_MSR_DCTS;
- }
- if(msr & COM2440_MSR_CTS)
- pHWHead->vUMSTAT |= COM2440_MSR_CTS;
- else
- pHWHead->vUMSTAT &= ~COM2440_MSR_CTS;
- // S2440 does not support Delta DSR status by H/W,
- // so we have to check this by S/W.
- //
- // if(DSR : High->Low) - became active
- if (msr_DSR) // S2440 Evaluation Board bidged these two pins.
- {
- if(!(pHWHead->vUMSTAT & COM2440_MSR_DSR))
- {
- pHWHead->vUMSTAT |= COM2440_MSR_DDSR;
- Events |= EV_DSR;
- Events |= EV_RLSD; // DCD
- } // there is a change... H->L(became active)
- else
- pHWHead->vUMSTAT &= ~COM2440_MSR_DDSR;
- pHWHead->vUMSTAT |= COM2440_MSR_DSR;
- }
- // if(DSR : Low->High) - became in-active
- else
- {
- if((pHWHead->vUMSTAT & COM2440_MSR_DSR))
- {
- pHWHead->vUMSTAT |= COM2440_MSR_DDSR;
- Events |= EV_DSR;
- Events |= EV_RLSD; // DCD
- } // there is a change... L->H (became inactive)
- else
- pHWHead->vUMSTAT &= ~COM2440_MSR_DDSR;
- pHWHead->vUMSTAT &= ~COM2440_MSR_DSR;
- }
- RETAILMSG(DEBUGMODE, (TEXT("ReadMSR Events:0x%xrn"), Events));
- RETAILMSG(DEBUGMODE, (TEXT("ReadMSR MSR:0x%xrn"), msr));
- RETAILMSG(DEBUGMODE, (TEXT("ReadMSR MSR_DSR:0x%xrn"), msr_DSR));
- if ( Events )
- pHWHead->EventCallback( pHWHead->pMddHead, Events );
- }
- VOID
- ShowSerialRegisters(PVOID pHead)
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(1, (TEXT("InterruptType : 0x%X, 0x%X, 0x%X, 0x%Xrn"),
- *(pHWHead->UART_INTMASK),
- *(pHWHead->UART_INTSUBMASK),
- *(pHWHead->UART_INTSRCPND),
- *(pHWHead->UART_INTSUBSRCPND)));
- RETAILMSG(1, (TEXT("rULCON: 0x%x "), pHWHead->s2440SerReg->rULCON));
- RETAILMSG(1, (TEXT("rUCON: 0x%x "), pHWHead->s2440SerReg->rUCON));
- RETAILMSG(1, (TEXT("rUFCON: 0x%x "), pHWHead->s2440SerReg->rUFCON));
- RETAILMSG(1, (TEXT("rUMCON: 0x%x "), pHWHead->s2440SerReg->rUMCON));
- RETAILMSG(1, (TEXT("rUERSTAT: 0x%x "), pHWHead->s2440SerReg->rUERSTAT));
- RETAILMSG(1, (TEXT("rUFSTAT: 0x%x "), pHWHead->s2440SerReg->rUFSTAT));
- RETAILMSG(1, (TEXT("rUMSTAT: 0x%x "), pHWHead->s2440SerReg->rUMSTAT));
- RETAILMSG(1, (TEXT("rUTXH: 0x%x "), pHWHead->s2440SerReg->rUTXH));
- RETAILMSG(1, (TEXT("rURXH: 0x%x "), pHWHead->s2440SerReg->rURXH));
- RETAILMSG(1, (TEXT("rUBRDIV: 0x%xrn"), pHWHead->s2440SerReg->rUBRDIV));
- RETAILMSG(1, (TEXT("pHWHead->vUMSTAT: 0x%x rn"), pHWHead->vUMSTAT));
- RETAILMSG(1, (TEXT("pHWHead->CTSFlowOff: 0x%x rnrn"), pHWHead->CTSFlowOff));
- }
- #define BAUD_TABLE_SIZE 23
- static const
- PAIRS LS_BaudPairs[BAUD_TABLE_SIZE] =
- {
- {50, 2307},
- {75, 1538},
- {110, 1049},
- {135, 858},
- {150, 769},
- {300, 384},
- {600, 192},
- {1200, 96},
- {1800, 64},
- {2000, 58},
- {2400, 48},
- {3600, 32},
- {4800, 24},
- {7200, 16},
- {9600, 12},
- {12800, 9},
- {14400, 8},
- {19200, 6},
- {23040, 5},
- {28800, 4},
- {38400, 3},
- {57600, 2},
- {115200, 1}
- };
- static const
- LOOKUP_TBL LS_BaudTable = {BAUD_TABLE_SIZE, (PAIRS *) LS_BaudPairs};
- // Routine to clear any pending interrupts. Called from Init and PostInit
- // to make sure we atart out in a known state.
- VOID
- ClearPendingInts(PVOID pHead) // @parm PVOID returned by HWinit.
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- UINT32 tmpReg;
- EnterCriticalSection(&(pHWHead->RegCritSec));
- RETAILMSG(DEBUGMODE,(TEXT("ClearPendingInts rn")));
- try
- {
- SETREG(pHWHead,rUFCON,0x6); // tx, rx fifo reset
- ClearSubINTPnd(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
- ClearINTPnd(pHWHead, pHWHead->bINT);
- tmpReg = INREG(pHWHead,rUERSTAT);
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- RETAILMSG(1,(TEXT("SL_PostInit, 0x%X - ERRORrn"), pHWHead));
- // Just fall through & release CritSec
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- }
- // Routine to set some 2440 IO Ports.
- VOID
- S2440_SetIrDAIOP(PVOID pHead) // @parm points to device head
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE, (TEXT("S2440_SetIrDAIOP rn")));
- EnterCriticalSection(&(pHWHead->RegCritSec));
- // by jylee 2003.04.15
- v_pIOPregs->rGPBCON &= ~(0x3<<2); // clear GPBCON for GPB1 (nIRDAEN)
- v_pIOPregs->rGPBCON |= (0x1<<2); // set GPBCON for GPB1 output
- v_pIOPregs->rGPBUP |= (0x1<<1); // set GPB1 pullup disable (external pullup)
- v_pIOPregs->rGPBDAT &= ~(0x1<<1); // set GPB1 signal low
- v_pIOPregs->rGPHCON &= ~(0x3<<12 | 0x3<<14); // clear uart 2 - rx, tx
- v_pIOPregs->rGPHCON |= (0x2<<12 | 0x2<<14);
- v_pIOPregs->rGPHUP |= 0xc0;
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- }
- S2440_SetSerialIOP(PVOID pHead) // @parm points to device head
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE, (TEXT("S2440_SetSerialIOP rn")));
- EnterCriticalSection(&(pHWHead->RegCritSec));
- v_pIOPregs->rGPHCON &= ~(0x3<<0 | 0x3<<2 | 0x3<<4 | 0x3<<6); // clear uart 0 - rx, tx
- v_pIOPregs->rGPHCON |= (0x2<<4 | 0x2<<6);
- v_pIOPregs->rGPDCON &= ~(0x3<<0 | 0x3<<2);
- v_pIOPregs->rGPDCON |= (0x1<<0 | 0x0<<2);
- #if USE_AFC
- // set nRTS to GPO mode
- // for software flow-control
- v_pIOPregs->rGPHCON |= (0x2<<0 | 0x1<<2 );
- #else
- v_pIOPregs->rGPHCON |= (0x2<<0 | 0x2<<2 );
- #endif
- /*
- In the SMDK2440 board, if IRDA is enabled, following values are ignored.
- */
- #if 0 // Board version is not 0.17
- v_pIOPregs->rGPHUP |= 0xc3;
- pHWHead->rDTRport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
- pHWHead->rDSRport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
- pHWHead->DtrPortNum = 6;
- pHWHead->DsrPortNum = 7;
- #endif
- v_pIOPregs->rGPDUP |= 0x3;
- pHWHead->rDTRport = (volatile unsigned int *)&(v_pIOPregs->rGPDDAT);
- pHWHead->rDSRport = (volatile unsigned int *)&(v_pIOPregs->rGPDDAT);
- pHWHead->DtrPortNum = 0;
- pHWHead->DsrPortNum = 1;
- #if USE_AFC
- pHWHead->rCTSport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
- pHWHead->rRTSport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
- pHWHead->CtsPortNum = 0;
- pHWHead->RtsPortNum = 1;
- #endif
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- }
- VOID
- S2440_SetIOP(PVOID pHead) // @parm points to device head
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- if ( pHWHead->UseIrDA )
- {
- RETAILMSG(DEBUGMODE, (TEXT("S2440_SetIOP : IRDArn")));
- S2440_SetIrDAIOP(pHWHead);
- }
- else
- {
- RETAILMSG(DEBUGMODE, (TEXT("S2440_SetIOP : SERIALrn")));
- S2440_SetSerialIOP(pHWHead);
- }
- }
- //
- /////////////////// Start of exported entrypoints ////////////////
- //
- //
- // @doc OEM
- // @func PVOID | SL_Open | Configures 16550 for default behaviour.
- //
- VOID
- SL_Open(PVOID pHead) // @parm PVOID returned by HWinit.
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(1, (TEXT("SL_Open 0x%X (%d opens)rn"), pHead, pHWHead->OpenCount));
- // If the device is already open, all we do is increment count
- if ( pHWHead->OpenCount++ )
- {
- RETAILMSG(1, (TEXT("SL_Open 0x%X (%d opens)rn"), pHead, pHWHead->OpenCount));
- return ;
- }
- pHWHead->DroppedBytes = 0;
- pHWHead->CTSFlowOff = FALSE; // Not flowed off yet
- pHWHead->DSRFlowOff = FALSE; // Not flowed off yet
- pHWHead->CommErrors = 0;
- pHWHead->ModemStatus = 0;
- pHWHead->ConSetup = 6;
- pHWHead->vUMSTAT = 0;
- pHWHead->fSW_EnTxINT = FALSE;
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- S2440_SetIOP(pHead);
- // Get defaults from the DCB structure
- SL_SetBaudRate( pHead, pHWHead->dcb.BaudRate );
- SL_SetByteSize( pHead, pHWHead->dcb.ByteSize );
- SL_SetStopBits( pHead, pHWHead->dcb.StopBits );
- SL_SetParity(pHead, pHWHead->dcb.Parity );
- // UART Control, Modem, Fifo register setting.
- OUTREG(pHWHead,rUCON,0x2c5); //Clock selection=PCLK, tx=level,rx=pulse,enable timeout int.,
- //enable rx error int., Tx int, Rx int
- OUTREG(pHWHead,rUFCON,0x6); // Reset FIFO
- if (pHWHead->UseIrDA)
- {
- OUTREG(pHWHead,rUFCON,0x41); //FIFO enable : tx-4bytes, rx-4bytes
- OUTREG(pHWHead,rUMCON,0x00); //Disable auto flow control.
- }
- else
- {
- #if USE_AFC
- // by shin.0212.
- OUTREG(pHWHead,rUFCON,0x61); //FIFO enable : tx-4bytes, rx-12bytes
- OUTREG(pHWHead,rUMCON,0x10); //Enable auto flow control.
- #else
- OUTREG(pHWHead,rUFCON,0x41); //FIFO enable : tx-4bytes, rx-4bytes
- OUTREG(pHWHead,rUMCON,0x00); //Disable auto flow control.
- #endif
- }
- if ( pHWHead->UseIrDA )
- SETREG(pHWHead,rULCON,SER2440_IRMODE_MASK); // Infra-red mode enable.
- ClearPendingInts( pHWHead );
- EnINT(pHWHead, pHWHead->bINT);
- EnSubINT(pHWHead, pHWHead->bRxINT);
- // For CE 3.0, we are still supporting
- // the old style MDDs, and they don't call our PostInit, which
- // needs to happen sometime prior to this. So for now, we go ahead
- // ahead and clear out interrupts one last time. In 4.0, we can
- // kill the old serial MDD and assume that everyone uses the new
- // MDD and calls post init.
- SL_PostInit(pHWHead);
- ReadLSR(pHWHead);
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Just get out of here.
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- }
- //
- // @doc OEM
- // @func PVOID | SL_Close | Does nothing except keep track of the
- // open count so that other routines know what to do.
- //
- VOID
- SL_Close(PVOID pHead) // @parm PVOID returned by HWinit.
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(1, (TEXT("SL_Close rn")));
- if ( pHWHead->OpenCount ) pHWHead->OpenCount--;
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- SL_ClearRTS( pHWHead );
- OUTREG(pHWHead,rUMSTAT,0x0);
- // Disable all interrupts and clear MCR.
- DisEnSubINT(pHWHead, pHWHead->bRxINT);
- pHWHead->fSW_EnTxINT = FALSE;
- // This routhine for auto detect.
- S2440_SetIrDAIOP(pHead);
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Just get out of here.
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- }
- //
- // @doc OEM
- // @func PVOID | SL_Init | Initializes 16550 device head.
- //
- VOID
- SL_Init(
- PVOID pHead, // @parm points to device head
- PUCHAR pRegBase, // Pointer to 16550 register base
- UINT8 RegStride, // Stride amongst the 16550 registers
- EVENT_FUNC EventCallback, // This callback exists in MDD
- PVOID pMddHead, // This is the first parm to callback
- PLOOKUP_TBL pBaudTable // BaudRate Table
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE, (TEXT("SL_Init : IRDA = %d rn"), pHWHead->UseIrDA));
- SER_VirtualAlloc();
- if ( pHWHead->UseIrDA )
- {
- pHWHead->bINT = BIT_UART2;
- pHWHead->bTxINT = INTSUB_TXD2;
- pHWHead->bRxINT = INTSUB_RXD2;
- pHWHead->bErrINT = INTSUB_ERR2;
- pHWHead->s2440SerReg = (S2440_UART_REG *)v_pUART2regs;
- pRegBase = (PUCHAR)pHWHead->s2440SerReg;
- }
- else
- {
- pHWHead->bINT = BIT_UART0;
- pHWHead->bTxINT = INTSUB_TXD0;
- pHWHead->bRxINT = INTSUB_RXD0;
- pHWHead->bErrINT = INTSUB_ERR0;
- pHWHead->s2440SerReg = (S2440_UART_REG *)v_pUART0regs;
- pRegBase = (PUCHAR)pHWHead->s2440SerReg;
- }
- pHWHead->UART_INTMASK = (volatile unsigned int *)&(v_pINTregs->rINTMSK);
- pHWHead->UART_INTSUBMASK = (volatile unsigned int *)&(v_pINTregs->rINTSUBMSK);
- pHWHead->UART_INTPND = (volatile unsigned int *)&(v_pINTregs->rINTPND);
- pHWHead->UART_INTSRCPND = (volatile unsigned int *)&(v_pINTregs->rSRCPND);
- pHWHead->UART_INTSUBSRCPND = (volatile unsigned int *)&(v_pINTregs->rSUBSRCPND);
- pHWHead->vUMSTAT = 0;
- if ( pHWHead->UseIrDA )
- {
- pHWHead->pUFTXH = (volatile unsigned char *)&(v_pUART2regs->rUTXH);
- pHWHead->pUFRXH = (volatile unsigned char *)&(v_pUART2regs->rURXH);
- }
- else
- {
- pHWHead->pUFTXH = (volatile unsigned char *)&(v_pUART0regs->rUTXH);
- pHWHead->pUFRXH = (volatile unsigned char *)&(v_pUART0regs->rURXH);
- }
- RETAILMSG(DEBUGMODE, (TEXT("+ S2440_SetIrDAIOP rn")));
- S2440_SetIrDAIOP(pHead);
- RETAILMSG(DEBUGMODE, (TEXT("- S2440_SetIrDAIOP rn")));
- // Store info for callback function
- pHWHead->EventCallback = EventCallback;
- pHWHead->pMddHead = pMddHead;
- // Now set up remaining fields
- if ( pBaudTable != NULL )
- pHWHead->pBaudTable = (LOOKUP_TBL *) pBaudTable;
- else
- pHWHead->pBaudTable = (LOOKUP_TBL *) &LS_BaudTable;
- pHWHead->FlushDone = CreateEvent(0, FALSE, FALSE, NULL);
- pHWHead->OpenCount = 0;
- // Don't allow any interrupts till PostInit.
- DisEnINT(pHWHead, pHWHead->bINT);
- DisEnSubINT(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
- pHWHead->fSW_EnTxINT = FALSE;
- pHWHead->RxDiscard = FALSE;
- InitializeCriticalSection(&(pHWHead->TransmitCritSec));
- InitializeCriticalSection(&(pHWHead->RegCritSec));
- // Clear any interrupts which may be pending. Normally only
- // happens if we were warm reset.
- ClearPendingInts( pHWHead );
- }
- //
- // @doc OEM
- // @func void | SL_PostInit | This routine takes care of final initialization.
- //
- // @rdesc None.
- //
- BOOL
- SL_PostInit(PVOID pHead) // @parm PVOID returned by HWinit.
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE, (TEXT("SL_PostInit rn")));
- // Since we are just a library which might get used for
- // builtin ports which init at boot, or by PCMCIA ports
- // which init at Open, we can't do anything too fancy.
- // Lets just make sure we cancel any pending interrupts so
- // that if we are being used with an edge triggered PIC, he
- // will see an edge after the MDD hooks the interrupt.
- ClearPendingInts( pHWHead );
- return(TRUE);
- }
- //
- // @doc OEM
- // @func PVOID | SL_Deinit | De-initializes 16550 device head.
- //
- VOID
- SL_Deinit(PVOID pHead) // @parm points to device head
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE, (TEXT("SL_Deinit rn")));
- DeleteCriticalSection(&(pHWHead->TransmitCritSec));
- DeleteCriticalSection(&(pHWHead->RegCritSec));
- // Free the flushdone event
- if ( pHWHead->FlushDone )
- CloseHandle( pHWHead->FlushDone );
- SER_VirtualFree();
- }
- //
- // @doc OEM
- // @func void | SL_ClearDtr | This routine clears DTR.
- //
- // @rdesc None.
- //
- VOID
- SL_ClearDTR(PVOID pHead) // @parm PVOID returned by HWinit.
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE, (TEXT("+SL_ClearDTR, 0x%Xrn"), pHead));
- RETAILMSG(DEBUGMODE, (TEXT("UseIrDA, %drn"), pHWHead->UseIrDA));
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- // Low active pin.
- if ( !pHWHead->UseIrDA )
- *(pHWHead->rDTRport) |= (1<<(pHWHead->DtrPortNum));
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Just exit
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- RETAILMSG(DEBUGMODE, (TEXT("-SL_ClearDTR, 0x%Xrn"), pHead));
- }
- //
- // @doc OEM
- // @func VOID | SL_SetDTR | This routine sets DTR.
- //
- // @rdesc None.
- //
- VOID
- SL_SetDTR(PVOID pHead) // @parm PVOID returned by HWinit.
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE, (TEXT("+SL_SetDTR, 0x%Xrn"), pHead));
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- // Low active
- if ( !pHWHead->UseIrDA )
- *(pHWHead->rDTRport) &= ~(1<<(pHWHead->DtrPortNum));
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Just exit
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- RETAILMSG(DEBUGMODE, (TEXT("-SL_SetDTR, 0x%Xrn"), pHead));
- }
- //
- // @doc OEM
- // @func VOID | SL_ClearRTS | This routine clears RTS.
- //
- // @rdesc None.
- //
- VOID
- SL_ClearRTS(PVOID pHead) // @parm PVOID returned by HWinit.
- {
- #if 0 // by shin
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(0, (TEXT("+SL_ClearRTS, 0x%Xrn"), pHead));
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- CLEARREG(pHWHead, rUMCON, SER2440_RTS);
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Just exit
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- RETAILMSG(DEBUGMODE, (TEXT("-SL_ClearRTS, 0x%Xrn"), pHead));
- #else
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE, (TEXT("+SL_ClearRTS, 0x%Xrn"), pHead));
- if ( !pHWHead->UseIrDA )
- {
- #if USE_AFC
- // by 0212.
- *(pHWHead->rRTSport) |= (1<<(pHWHead->RtsPortNum));
- #else
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- CLEARREG(pHWHead, rUMCON, SER2440_RTS);
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Just exit
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- #endif
- }
- RETAILMSG(DEBUGMODE, (TEXT("-SL_ClearRTS, 0x%Xrn"), pHead));
- #endif
- }
- //
- // @doc OEM
- // @func VOID | SL_SetRTS | This routine sets RTS.
- //
- // @rdesc None.
- //
- VOID
- SL_SetRTS(PVOID pHead) // @parm PVOID returned by HWinit.
- {
- #if 0
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(0, (TEXT("+SL_SetRTS, 0x%Xrn"), pHead));
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- SETREG(pHWHead, rUMCON, SER2440_RTS);
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Just exit
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- RETAILMSG(DEBUGMODE, (TEXT("-SL_SetRTS, 0x%Xrn"), pHead));
- #else
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE, (TEXT("+SL_SetRTS, 0x%Xrn"), pHead));
- if ( !pHWHead->UseIrDA )
- {
- #if USE_AFC
- // by .0212.
- *(pHWHead->rRTSport) &= ~(1<<(pHWHead->RtsPortNum));
- #else
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- SETREG(pHWHead, rUMCON, SER2440_RTS);
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Just exit
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- #endif
- }
- RETAILMSG(DEBUGMODE, (TEXT("-SL_SetRTS, 0x%Xrn"), pHead));
- #endif
- }
- //
- // @doc OEM
- // @func VOID | SL_ClearBreak | This routine clears break.
- //
- // @rdesc None.
- //
- VOID
- SL_ClearBreak(PVOID pHead) // @parm PVOID returned by HWinit.
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE, (TEXT("SL_ClearBreak:rn")));
- // S2440 does not need to clear break signal, for cleared by automatic.
- }
- //
- // @doc OEM
- // @func VOID | SL_SetBreak | This routine sets break.
- //
- // @rdesc None.
- //
- VOID
- SL_SetBreak(PVOID pHead) // @parm PVOID returned by HWinit.
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE, (TEXT("+SL_SetBreak, 0x%Xrn"), pHead));
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- SETREG(pHWHead,rUCON,BS_SEND);
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Just exit
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- RETAILMSG(DEBUGMODE, (TEXT("-SL_SetBreak, 0x%Xrn"), pHead));
- }
- //
- // SetBaudRate
- //
- // Internal function. The only real reason for splitting this out
- // is so that we can call it from PowerOn and still allow SL_SetBaud
- // to do debug messages, acquire critical sections, etc.
- //
- BOOL
- SetBaudRate(PVOID pHead, ULONG BaudRate)
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- ClearPendingInts( pHWHead );
- RETAILMSG(1, (TEXT("SetBaudRate -> %drn"), BaudRate));
- if ( (pHWHead->s2440SerReg->rUCON & CS_MASK) == CS_PCLK )
- {
- // if ( BaudRate == 115200 || BaudRate == 38400 )
- // OUTREG(pHWHead,rUBRDIV,( (int)(S2440PCLK/16.0/BaudRate)));
- // else
- OUTREG(pHWHead,rUBRDIV,( (int)(S2440PCLK/16.0/BaudRate) -1 ));
- }
- else // if ( (pHWHead2->s2440SerReg->rUCON & CS_MASK) == CS_UCLK )
- OUTREG(pHWHead,rUBRDIV,( (int)(S2440UCLK/16.0/BaudRate) -1 ));
- return( TRUE );
- }
- //
- // @doc OEM
- // @func BOOL | SL_SetBaudRate |
- // This routine sets the baud rate of the device.
- //
- // @rdesc None.
- //
- BOOL
- SL_SetBaudRate(
- PVOID pHead, // @parm PVOID returned by HWInit
- ULONG BaudRate // @parm ULONG representing decimal baud rate.
- )
- {
- BOOL fRet;
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG (DEBUGMODE, (TEXT("+SL_SetbaudRate 0x%X, %drn"), pHead, BaudRate));
- try
- {
- // Enter critical section before calling function, since
- // we can't make sys calls inside SetBaudRate
- EnterCriticalSection(&(pHWHead->RegCritSec));
- fRet = SetBaudRate(pHead, BaudRate);
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- return( FALSE );
- }
- if ( fRet )
- {
- pHWHead->dcb.BaudRate = BaudRate;
- RETAILMSG(DEBUGMODE, (TEXT("-SL_SetbaudRate 0x%X (%d Baud)rn"), pHead, BaudRate));
- return( TRUE );
- }
- else
- {
- RETAILMSG(DEBUGMODE, (TEXT("-SL_SetbaudRate - Error setting %d, failing to %drn"), BaudRate, pHWHead->dcb.BaudRate));
- return( FALSE );
- }
- }
- //
- // @doc OEM
- // @func BOOL | SL_SetByteSize |
- // This routine sets the WordSize of the device.
- //
- // @rdesc None.
- //
- BOOL
- SL_SetByteSize(
- PVOID pHead, // @parm PVOID returned by HWInit
- ULONG ByteSize // @parm ULONG ByteSize field from DCB.
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- UINT32 lcr;
- BOOL bRet;
- RETAILMSG(DEBUGMODE,(TEXT("+SL_SetByteSize 0x%X, 0x%Xrn"), pHead, ByteSize));
- bRet = TRUE;
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try {
- lcr = (UINT32)INREG(pHWHead,rULCON);
- lcr &= ~SER2440_DATABIT_MASK;
- switch ( ByteSize )
- {
- case 5:
- lcr |= 0;//SERIAL_5_DATA;
- break;
- case 6:
- lcr |= 1;//SERIAL_6_DATA;
- break;
- case 7:
- lcr |= 2;//SERIAL_7_DATA;
- break;
- case 8:
- lcr |= 3;//SERIAL_8_DATA;
- break;
- default:
- bRet = FALSE;
- break;
- }
- if (bRet)
- {
- OUTREG(pHWHead,rULCON,lcr);
- }
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- bRet = FALSE;
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- RETAILMSG(DEBUGMODE,(TEXT("-SL_SetByteSize 0x%Xrn"), pHead));
- return(bRet);
- }
- //
- // @doc OEM
- // @func BOOL | SL_SetParity |
- // This routine sets the parity of the device.
- //
- // @rdesc None.
- //
- BOOL
- SL_SetParity(
- PVOID pHead, // @parm PVOID returned by HWInit
- ULONG Parity // @parm ULONG parity field from DCB.
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- UINT32 lcr;
- BOOL bRet;
- RETAILMSG(DEBUGMODE,(TEXT("+SL_SetParity 0x%X, 0x%Xrn"), pHead, Parity));
- bRet = TRUE;
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- lcr = (UINT32)INREG(pHWHead,rULCON);
- lcr &= ~SER2440_PARITY_MASK;
- switch ( Parity )
- {
- case ODDPARITY:
- lcr |= 0x20;//SERIAL_ODD_PARITY;
- break;
- case EVENPARITY:
- lcr |= 0x28;//SERIAL_EVEN_PARITY;
- break;
- case MARKPARITY:
- lcr |= 0x30;//SERIAL_MARK_PARITY;
- break;
- case SPACEPARITY:
- lcr |= 0x38;//SERIAL_SPACE_PARITY;
- break;
- case NOPARITY:
- lcr |= 0;//SERIAL_NONE_PARITY;
- break;
- default:
- bRet = FALSE;
- break;
- }
- if (bRet)
- {
- OUTREG(pHWHead,rULCON,lcr) ;
- }
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- bRet = FALSE;
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- RETAILMSG(DEBUGMODE, (TEXT("-SL_SetParity 0x%Xrn"), pHead));
- return(bRet);
- }
- //
- // @doc OEM
- // @func VOID | SL_SetStopBits |
- // This routine sets the Stop Bits for the device.
- //
- // @rdesc None.
- //
- BOOL
- SL_SetStopBits(
- PVOID pHead, // @parm PVOID returned by HWInit
- ULONG StopBits // @parm ULONG StopBits field from DCB.
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- UINT32 lcr;
- BOOL bRet;
- RETAILMSG (DEBUGMODE,(TEXT("+SL_SetStopBits 0x%X, 0x%Xrn"), pHead, StopBits));
- bRet = TRUE;
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- lcr = INREG(pHWHead,rULCON);
- lcr &= ~SER2440_STOPBIT_MASK;
- // Note that 1.5 stop bits only works if the word size
- // is 5 bits. Any other xmit word size will cause the
- // 1.5 stop bit setting to generate 2 stop bits.
- switch ( StopBits )
- {
- case ONESTOPBIT :
- lcr |= 0;//SERIAL_1_STOP ;
- break;
- case ONE5STOPBITS :
- //lcr |= SERIAL_1_5_STOP ;
- //break;
- case TWOSTOPBITS :
- lcr |= 4;//SERIAL_2_STOP ;
- break;
- default:
- bRet = FALSE;
- break;
- }
- if (bRet)
- {
- OUTREG(pHWHead,rULCON,lcr);
- }
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- bRet = FALSE;
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- RETAILMSG(DEBUGMODE,(TEXT("-SL_SetStopBits 0x%Xrn"), pHead));
- return(bRet);
- }
- //
- // @doc OEM
- // @func ULONG | SL_GetRxBufferSize | This function returns
- // the size of the hardware buffer passed to the interrupt
- // initialize function. It would be used only for devices
- // which share a buffer between the MDD/PDD and an ISR.
- //
- //
- // @rdesc This routine always returns 0 for 16550 UARTS.
- //
- ULONG
- SL_GetRxBufferSize(PVOID pHead)
- {
- RETAILMSG(DEBUGMODE, (TEXT("SL_GetRxBufferSize rn")));
- return(0);
- }
- //
- // @doc OEM
- // @func PVOID | SC_GetRxStart | This routine returns the start of the hardware
- // receive buffer. See SL_GetRxBufferSize.
- //
- // @rdesc The return value is a pointer to the start of the device receive buffer.
- //
- PVOID
- SL_GetRxStart(PVOID pHead) // @parm PVOID returned by SC_init.
- {
- RETAILMSG(DEBUGMODE, (TEXT("SL_GetRxStart rn")));
- return(NULL);
- }
- //
- // @doc OEM
- // @func ULONG | SL_GetInterruptType | This function is called
- // by the MDD whenever an interrupt occurs. The return code
- // is then checked by the MDD to determine which of the four
- // interrupt handling routines are to be called.
- //
- // @rdesc This routine returns a bitmask indicating which interrupts
- // are currently pending.
- //
- INTERRUPT_TYPE
- SL_GetInterruptType(PVOID pHead) // Pointer to hardware head
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- INTERRUPT_TYPE interrupts;
- ULONG IntPndVal=0;
- ULONG IntSubPndVal=0;
- try
- {
- IntPndVal = *(pHWHead->UART_INTSRCPND);
- IntSubPndVal = *(pHWHead->UART_INTSUBSRCPND);
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- RETAILMSG(DEBUGMODE, (TEXT("ACCESS VIOLATION ERROR rn")));
- IntPndVal = SER2440_INT_INVALID; // simulate no interrupt
- }
- RETAILMSG(DEBUGMODE, (TEXT("SL_GetInterruptType : 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%Xrn"),
- *(pHWHead->UART_INTMASK),
- *(pHWHead->UART_INTSUBMASK),
- *(pHWHead->UART_INTSRCPND),
- *(pHWHead->UART_INTSUBSRCPND),
- ~(*(pHWHead->UART_INTSUBMASK)) & *(pHWHead->UART_INTSUBSRCPND),
- pHWHead->fSW_EnTxINT));
- if ( IntPndVal & (pHWHead->bINT) )
- {
- if ( IntSubPndVal == SER2440_INT_INVALID )
- {
- RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: SER2440_INT_INVALIDrn")));
- interrupts = INTR_NONE;
- }
- else if(IntSubPndVal & (pHWHead->bErrINT) )
- {
- RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_LINErn")));
- interrupts = INTR_LINE; // Error status
- }
- else if((IntSubPndVal & (pHWHead->bTxINT)) && pHWHead->fSW_EnTxINT )
- {
- RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_TXrn")));
- interrupts = INTR_TX;
- }
- else if(IntSubPndVal & (pHWHead->bRxINT) )
- {
- RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_RXrn")));
- interrupts = INTR_RX; // Received valid data.
- }
- else
- {
- interrupts = INTR_NONE; // No interrupts pending, vector is useless
- ClearINTPnd(pHWHead, pHWHead->bINT);
- }
- }
- else
- {
- RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_NONE(pHWHead->bINT)rn")));
- interrupts = INTR_NONE; // No interrupts pending, vector is useless
- }
- return(interrupts);
- }
- // @doc OEM
- // @func ULONG | SL_RxIntr | This routine gets several characters from the hardware
- // receive buffer and puts them in a buffer provided via the second argument.
- // It returns the number of bytes lost to overrun.
- //
- // @rdesc The return value indicates the number of overruns detected.
- // The actual number of dropped characters may be higher.
- //
- ULONG
- SL_RxIntr(
- PVOID pHead, // @parm Pointer to hardware head
- PUCHAR pRxBuffer, // @parm Pointer to receive buffer
- ULONG *pBufflen // @parm In = max bytes to read, out = bytes read
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- ULONG RetVal = 0;
- ULONG TargetRoom = *pBufflen;
- UCHAR cEvtChar, cRXChar;
- ULONG rFifoStat, RxFifoCnt, RxDataReady, nRxIntSrc;
- BOOL fRXFlag = FALSE;
- BOOL fReplaceparityErrors = FALSE;
- BOOL fNull;
- *pBufflen = 0;
- nRxIntSrc = pHWHead->bRxINT;
- RETAILMSG(DEBUGMODE, (TEXT("SL_RxIntr rn")));
- // LAM - I have local copies of some DCB elements since I don't
- // want to keep dereferencing inside my read loop and there are too
- // many of them to trust the compiler.
- cEvtChar = pHWHead->dcb.EvtChar;
- fNull = pHWHead->dcb.fNull;
- if ( pHWHead->dcb.fErrorChar && pHWHead->dcb.fParity )
- fReplaceparityErrors = TRUE;
- try
- {
- // S2440 UART Rx strategy is different from SER16550..
- rFifoStat = INREG(pHWHead,rUFSTAT);
- RxFifoCnt = rFifoStat & 0x3f;
- if((rFifoStat & (1<<6))||(RxFifoCnt > 0))
- RxDataReady = 1;
- else
- RxDataReady = 0;
- while ( TargetRoom && RxDataReady)
- {
- // If the line is unstable, we may check the error status...
- // But now, I ignore it....
- // ReadLSR( pHWHead );
- // Read the byte
- cRXChar = *(pHWHead->pUFRXH);
- RETAILMSG(DEBUGMODE, (TEXT("SL_RxIntr : cRXChar = 0x%x rn"), cRXChar));
- // But we may want to discard it
- if ( pHWHead->dcb.fDsrSensitivity &&
- (! (pHWHead->vUMSTAT & COM2440_MSR_DSR)) )
- {
- // Do nothing - byte gets discarded
- RETAILMSG (1, (TEXT("Dropping byte because DSR is lowrn")));
- }
- else if (!cRXChar && fNull)
- {
- // Do nothing - byte gets discarded
- RETAILMSG (1, (TEXT("Dropping NULL byte due to fNullrn")));
- }
- else
- {
- // Do character replacement if parity error detected.
- // See if we need to generate an EV_RXFLAG for the received char.
- if ( cRXChar == cEvtChar )
- fRXFlag = TRUE;
- // Finally, we can get byte, update status and save.
- if (!pHWHead->RxDiscard )
- {
- *pRxBuffer++ = cRXChar;
- (*pBufflen)++;
- }
- else
- {
- RETAILMSG (1,(TEXT("SL_RXIntr : Dropping byte because now Txingrn")));
- }
- --TargetRoom;
- rFifoStat = INREG(pHWHead,rUFSTAT);
- RxFifoCnt = rFifoStat & 0x3f;
- if((rFifoStat & (1<<6))||(RxFifoCnt > 0))
- RxDataReady = 1;
- else
- RxDataReady = 0;
- }
- }
- //Clear interrupt pending bit
- ClearSubINTPnd(pHWHead, nRxIntSrc);
- if ( *(pHWHead->UART_INTSUBSRCPND) & ( pHWHead->bRxINT | pHWHead->bErrINT ) )
- {
- RETAILMSG (DEBUGMODE, (TEXT("*(pHWHead->UART_INTSUBSRCPND) = %x rn"), *(pHWHead->UART_INTSUBSRCPND)));
- RETAILMSG (DEBUGMODE, (TEXT("Do Not Clear bINT rn")));
- }
- else
- {
- ClearINTPnd(pHWHead, pHWHead->bINT);
- }
- EnINT(pHWHead, pHWHead->bINT);
- EnSubINT(pHWHead, nRxIntSrc);
- if ( !pHWHead->UseIrDA )
- {
- #if USE_AFC
- // Assert nRTS
- *(pHWHead->rRTSport) &= ~(1<<(pHWHead->RtsPortNum));
- #endif
- }
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // just exit
- }
- // if we saw one (or more) EVT chars, then generate an event
- if ( fRXFlag )
- pHWHead->EventCallback( pHWHead->pMddHead, EV_RXFLAG );
- if ( pHWHead->DroppedBytes )
- {
- RETAILMSG (DEBUGMODE, (TEXT("Rx drop %d.rn"), pHWHead->DroppedBytes));
- }
- RetVal = pHWHead->DroppedBytes;
- pHWHead->DroppedBytes = 0;
- return(RetVal);
- }
- // @doc OEM
- // @func ULONG | SL_PutBytes | This routine is called from the MDD
- // in order to write a stream of data to the device. (Obselete)
- //
- // @rdesc Always returns 0
- //
- ULONG
- SL_PutBytes(
- PVOID pHead, // @parm PVOID returned by HWInit.
- PUCHAR pSrc, // @parm Pointer to bytes to be sent.
- ULONG NumberOfBytes, // @parm Number of bytes to be sent.
- PULONG pBytesSent // @parm Pointer to actual number of bytes put.
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(1,(TEXT("This routine is called by old MDDrn")));
- return(0);
- }
- //
- // @doc OEM
- // @func ULONG | SL_TXIntr | This routine is called from the old MDD
- // whenever INTR_TX is returned by SL_GetInterruptType (Obselete)
- //
- // @rdesc None
- //
- VOID
- SL_TxIntr(PVOID pHead) // Hardware Head
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(1, (TEXT("SL_TxIntr(From old MDD)n")));
- }
- //
- // @doc OEM
- // @func ULONG | SL_TXIntrEx | This routine is called from the new MDD
- // whenever INTR_TX is returned by SL_GetInterruptType
- //
- // @rdesc None
- //
- VOID
- SL_TxIntrEx(
- PVOID pHead, // Hardware Head
- PUCHAR pTxBuffer, // @parm Pointer to receive buffer
- ULONG *pBufflen // @parm In = max bytes to transmit, out = bytes transmitted
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- UCHAR byteCount;
- ULONG NumberOfBytes = *pBufflen;
- ULONG rFifoStat, TxFifoCnt;
- unsigned int FifoModeReg;
- RETAILMSG(DEBUGMODE, (TEXT("SL_TxIntrEx rn")));
- // We may be done sending. If so, just disable the TX interrupts and return to the MDD.
- if( ! *pBufflen )
- {
- DisEnINT(pHWHead, pHWHead->bINT);
- DisEnSubINT(pHWHead, pHWHead->bTxINT);
- pHWHead->fSW_EnTxINT = FALSE;
- ClearINTPnd(pHWHead, pHWHead->bINT);
- return;
- }
- *pBufflen = 0; // In case we don't send anything below.
- // Disable xmit intr. Most 16550s will keep hammering
- // us with xmit interrupts if we don't turn them off
- // Whoever gets the FlushDone will then need to turn
- // TX Ints back on if needed.
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- // Need to signal FlushDone for XmitComChar
- PulseEvent(pHWHead->FlushDone);
- pHWHead->CommErrors &= ~CE_TXFULL;
- #if 0
- // If CTS flow control is desired, check cts. If clear, don't send,
- // but loop. When CTS comes back on, the OtherInt routine will
- // detect this and re-enable TX interrupts (causing Flushdone).
- // For finest granularity, we would check this in the loop below,
- // but for speed, I check it here (up to 8 xmit characters before
- // we actually flow off.
- if ( pHWHead->dcb.fOutxCtsFlow )
- {
- // ReadMSR( pHWHead );
- // We don't need to explicitly read the MSR, since we always enable
- // IER_MS, which ensures that we will get an interrupt and read
- // the MSR whenever CTS, DSR, TERI, or DCD change.
- if (! (pHWHead->MSR & SERIAL_MSR_CTS) )
- {
- unsigned char byte;
- RETAILMSG (DEBUGMODE, (TEXT("SL_TxIntrEx, flowed off via CTSn") ) );
- pHWHead->CTSFlowOff = TRUE; // Record flowed off state
- // We could return a positive value here, which would
- // cause the MDD to periodically check the flow control
- // status. However, we don't need to since we know that
- // the DCTS interrupt will cause the MDD to call us, and we
- // will subsequently fake a TX interrupt to the MDD, causing
- // him to call back into PutBytes.
- DisEnINT(pHWHead, pHWHead->bINT);
- DisEnSubINT(pHWHead, pHWHead->bTxINT);
- pHWHead->fSW_EnTxINT = FALSE;
- ClearINTPnd(pHWHead, pHWHead->bINT);
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- return;
- }
- }
- #endif
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Do nothing. The worst case is that this was a fluke,
- // and a TX Intr will come right back at us and we will
- // resume transmission.
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- // OK, now lets actually transmit some data.
- EnterCriticalSection(&(pHWHead->TransmitCritSec));
- EnterCriticalSection(&(pHWHead->RegCritSec));
- FifoModeReg = INREG(pHWHead, rUFCON);
- try
- {
- rFifoStat = INREG(pHWHead,rUFSTAT);
- TxFifoCnt = ((rFifoStat & SER2440_FIFOCNT_MASK_TX) >> 8);
- if (pHWHead->UseIrDA)
- {
- // IR is half-duplex.
- pHWHead->RxDiscard = TRUE;
- DisEnSubINT(pHWHead, pHWHead->bRxINT);
- }
- if (!(rFifoStat & SER2440_FIFOFULL_TX) && (TxFifoCnt <= (SER2440_FIFO_DEPTH_TX-1)))
- {
- byteCount = (unsigned char)(SER2440_FIFO_DEPTH_TX-TxFifoCnt);
- RETAILMSG(DEBUGMODE, (TEXT("SL_TxIntrEx : %d rn"), NumberOfBytes));
- for ( *pBufflen=0; NumberOfBytes && byteCount; NumberOfBytes--, byteCount-- )
- {
- unsigned int i, tmpreg;
- *(pHWHead->pUFTXH) = *pTxBuffer;
- RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt - *pTxBuffer = 0x%x rn"), *pTxBuffer));
- if (FifoModeReg&0x1) // FIFO Mode enabled.
- {
- for ( i = 0; i < 600000; i++ )
- {
- tmpreg = INREG(pHWHead, rUFSTAT);
- //tmpreg & (1<<14) == 1 -> Fifo full -> waiting...
- //tmpreg & 0x3f00 == 0 -> There is no data to send -> break loop.
- if ( (tmpreg & (1<<14)) == (1<<14) )
- {
- continue;
- }
- else break;
- }
- if ( i == 600000 ) // Time Out Error
- {
- RETAILMSG (1, (TEXT("SL_TxInt : Error : i = %d rn"), i));
- }
- }
- else // FIFO Mode disabled.
- {
- for ( i = 0; i < 600000; i++ )
- {
- tmpreg = INREG(pHWHead, rUTRSTAT);
- if ( tmpreg & 0x2 ) break;
- }
- if ( i == 600000 )
- {
- RETAILMSG (1, (TEXT("SL_TxInt : Error : i = %d rn"), i));
- }
- }
- ++pTxBuffer;
- (*pBufflen)++;
- //irda test...
- //RETAILMSG (1,(TEXT("T ")));
- }
- if (pHWHead->UseIrDA )
- {
- if (FifoModeReg&0x1) // FIFO Mode enabled.
- {
- unsigned int cnt = 0;
- for ( ;; )
- {
- unsigned int tmpreg;
- tmpreg = INREG(pHWHead, rUFSTAT);
- if ( (tmpreg & 0x3f00) == 0) break; // waitint to empty the tx buffer empty...
- if ( cnt++ > 600000 )
- {
- RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt : Reset TX FIFO : tmpreg = %x rn"), tmpreg));
- SETREG(pHWHead,rUFCON,0x4); // tx, rx fifo reset
- break;
- }
- }
- RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt : Exit for loop rn")));
- }
- }
- }
- else
- {
- RETAILMSG (1, (TEXT("SL_TxIntrEx: Not Send - rFifoStat[0x%x] TxFifoCnt[0x%x]rn"),
- rFifoStat, TxFifoCnt));
- }
- if (pHWHead->UseIrDA )
- {
- // IR is half-duplex.
- ClearPendingInts( pHWHead );
- EnSubINT(pHWHead, pHWHead->bRxINT);
- pHWHead->RxDiscard = FALSE;
- }
- // Enable xmit intr. We need to do this no matter what,
- // since the MDD relies on one final interrupt before
- // returning to the application.
- // ClearPendingInts( pHWHead );
- // Clear TX interrupt pending bit.
- ClearSubINTPnd(pHWHead, pHWHead->bTxINT);
- if ( !(GetSubINTStatus(pHWHead) & pHWHead->bRxINT) ) ClearINTPnd(pHWHead, pHWHead->bINT);
- EnINT(pHWHead, pHWHead->bINT);
- EnSubINT(pHWHead, pHWHead->bTxINT);
- pHWHead->fSW_EnTxINT = TRUE; // FALSE;
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Hmm, not sure what would cause this. Lets just tell
- // the MDD to go away until we get another TX
- // interrupt.
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- LeaveCriticalSection(&(pHWHead->TransmitCritSec));
- return;
- }
- //
- // @doc OEM
- // @func ULONG | SL_LineIntr | This routine is called from the MDD
- // whenever INTR_LINE is returned by SL_GetInterruptType.
- //
- // @rdesc None
- //
- VOID
- SL_LineIntr(PVOID pHead) // Hardware Head
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE,(TEXT("INTR_LINE rn")));
- SL_ModemIntr( pHWHead );
- ReadLSR( pHWHead );
- ClearSubINTPnd(pHWHead, pHWHead->bErrINT);
- if ( !(GetSubINTStatus(pHWHead) & pHWHead->bRxINT) )
- ClearINTPnd(pHWHead, pHWHead->bINT);
- EnINT(pHWHead, pHWHead->bINT);
- EnSubINT(pHWHead, pHWHead->bErrINT);
- }
- //
- // @doc OEM
- // @func ULONG | SL_OtherIntr | This routine is called from the MDD
- // whenever INTR_MODEM is returned by SL_GetInterruptType.
- //
- // @rdesc None
- //
- VOID
- SL_OtherIntr(PVOID pHead) // Hardware Head
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- // S2440 does not have modem interrupt.
- RETAILMSG(DEBUGMODE,(TEXT("+SL_OtherIntr rn")));
- ReadMSR( pHWHead );
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- // If we are currently flowed off via CTS or DSR, then
- // we better signal the TX thread when one of them changes
- // so that TX can resume sending.
- if ( pHWHead->DSRFlowOff && (pHWHead->vUMSTAT & COM2440_MSR_DSR))
- {
- RETAILMSG (DEBUGMODE, (TEXT("**********************PutBytes, flowed on via DSRn") ) );
- pHWHead->DSRFlowOff = FALSE;
- // DSR is set, so go ahead and resume sending
- EnINT(pHWHead, pHWHead->bINT);
- EnSubINT(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
- pHWHead->fSW_EnTxINT = TRUE;
- // Then simulate a TX intr to get things moving
- pHWHead->AddTXIntr = TRUE;
- }
- if ( pHWHead->CTSFlowOff && (pHWHead->vUMSTAT & COM2440_MSR_CTS))
- {
- RETAILMSG(DEBUGMODE, (TEXT("***********************PutBytes, flowed on via CTSn") ) );
- pHWHead->CTSFlowOff = FALSE;
- // CTS is set, so go ahead and resume sending
- EnINT(pHWHead, pHWHead->bINT);
- EnSubINT(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
- pHWHead->fSW_EnTxINT = TRUE;
- // Then simulate a TX intr to get things moving
- pHWHead->AddTXIntr = TRUE;
- }
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
- // Just exit
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- RETAILMSG(DEBUGMODE,(TEXT("-SL_OtherIntr 0x%Xrn"), pHead));
- }
- //
- // @doc OEM
- // @func ULONG | SL_OtherIntr | This routine is called from the MDD
- // whenever INTR_MODEM is returned by SL_GetInterruptType.
- //
- // @rdesc None
- //
- VOID
- SL_ModemIntr(PVOID pHead) // Hardware Head
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- INTERRUPT_TYPE it = INTR_NONE;
- ULONG win32status = 0;
- RETAILMSG (1, (TEXT("SL_ModemIntr - pHWHead->OpenCount %d rn"), pHWHead->OpenCount));
- if ( !pHWHead->OpenCount )
- {
- // We want to indicate a cable event.
- RETAILMSG(1, (TEXT("!pHWHead->OpenCount : 0x%Xrn"), pHWHead->OpenCount));
- if ( IsAPIReady(SH_WMGR))
- {
- RETAILMSG(1, (TEXT("IsAPIReady(SH_WMGR) == truern")));
- CeEventHasOccurred (NOTIFICATION_EVENT_RS232_DETECTED,NULL);
- RETAILMSG(1, (TEXT("Indicating RS232 Cable Eventrn")));
- RETAILMSG(1, (TEXT("Event occurred : NOTIFICATION_EVENT_RS232_DETECTEDrn")));
- }
- }
- else
- {
- RETAILMSG(1,(TEXT("+SL_ModemIntr 0x%Xrn"), pHead));
- SL_OtherIntr(pHead);
- }
- }
- //
- // @doc OEM
- // @func ULONG | SL_GetStatus | This structure is called by the MDD
- // to retrieve the contents of a COMSTAT structure.
- //
- // @rdesc The return is a ULONG, representing success (0) or failure (-1).
- //
- ULONG
- SL_GetStatus(
- PVOID pHead, // @parm PVOID returned by HWInit.
- LPCOMSTAT lpStat // Pointer to LPCOMMSTAT to hold status.
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- ULONG RetVal = pHWHead->CommErrors;
- RETAILMSG(1, (TEXT("+SL_GetStatus 0x%Xrn"), pHead));
- pHWHead->CommErrors = 0; // Clear old errors each time
- if ( lpStat )
- {
- try
- {
- if (pHWHead->CTSFlowOff)
- pHWHead->Status.fCtsHold = 1;
- else
- pHWHead->Status.fCtsHold = 0;
- if (pHWHead->DSRFlowOff)
- pHWHead->Status.fDsrHold = 1;
- else
- pHWHead->Status.fDsrHold = 0;
- // NOTE - I think what they really want to know here is
- // the amount of data in the MDD buffer, not the amount
- // in the UART itself. Just set to 0 for now since the
- // MDD doesn't take care of this.
- pHWHead->Status.cbInQue = 0;
- pHWHead->Status.cbOutQue = 0;
- memcpy(lpStat, &(pHWHead->Status), sizeof(COMSTAT));
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- RetVal = (ULONG)-1;
- }
- }
- else
- RetVal = (ULONG)-1;
- DEBUGMSG (ZONE_FUNCTION|USERDBG,
- (TEXT("-SL_GetStatus 0x%Xrn"), pHead));
- return(RetVal);
- }
- //
- // @doc OEM
- // @func ULONG | SL_Reset | Perform any operations associated
- // with a device reset
- //
- // @rdesc None.
- //
- VOID
- SL_Reset(PVOID pHead) // @parm PVOID returned by HWInit.
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE,(TEXT("+SL_Reset 0x%Xrn"), pHead));
- memset(&pHWHead->Status, 0, sizeof(COMSTAT));
- EnterCriticalSection(&(pHWHead->RegCritSec));
- try
- {
- DisEnINT(pHWHead, pHWHead->bINT);
- DisEnSubINT(pHWHead, pHWHead->bTxINT);
- // if ( GetSubINTStatus(pHWHead) )
- pHWHead->fSW_EnTxINT = FALSE;
- pHWHead->RxDiscard = FALSE;
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Do nothing
- }
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- DEBUGMSG (ZONE_FUNCTION, (TEXT("-SL_Reset 0x%Xrn"), pHead));
- }
- //
- // @doc OEM
- // @func VOID | SL_GetModemStatus | Retrieves modem status.
- //
- // @rdesc None.
- //
- VOID
- SL_GetModemStatus(
- PVOID pHead, // @parm PVOID returned by HWInit.
- PULONG pModemStatus // @parm PULONG passed in by user.
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- UINT8 ubModemStatus;
- RETAILMSG(DEBUGMODE, (TEXT("SL_GetModemStatus:rn")));
- ReadMSR( pHWHead );
- ubModemStatus = (unsigned char)pHWHead->vUMSTAT;
- RETAILMSG(DEBUGMODE, (TEXT("SL_GetModemStatus: ubModemStatus = 0x%xrn"), ubModemStatus));
- if ( ubModemStatus & COM2440_MSR_CTS )
- *pModemStatus |= MS_CTS_ON;
- if ( ubModemStatus & COM2440_MSR_DSR )
- {
- *pModemStatus |= MS_DSR_ON;
- *pModemStatus |= MS_RLSD_ON;
- }
- RETAILMSG(DEBUGMODE,(TEXT("-SL_GetModemStatus 0x%X (stat x%X) rn"), pHead, *pModemStatus));
- return;
- }
- //
- // @doc OEM
- // @func VOID | SL_PurgeComm | Purge RX and/or TX
- //
- // @rdesc None.
- //
- VOID
- SL_PurgeComm(
- PVOID pHead, // @parm PVOID returned by HWInit.
- DWORD fdwAction // @parm Action to take.
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(DEBUGMODE,(TEXT("+SL_PurgeComm 0x%Xrn"), fdwAction));
- return;
- }
- //
- // @doc OEM
- // @func BOOL | SL_XmitComChar | Transmit a char immediately
- //
- // @rdesc TRUE if succesful
- //
- BOOL
- SL_XmitComChar(
- PVOID pHead, // @parm PVOID returned by HWInit.
- UCHAR ComChar // @parm Character to transmit.
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- ULONG rFifoStat, TxFifoCnt;
- RETAILMSG (DEBUGMODE,(TEXT("+SL_XmitComChar 0x%Xrn"), pHead));
- // Get critical section, then transmit when buffer empties
- RETAILMSG(DEBUGMODE, (TEXT("XmitComChar wait for CritSec %x.rn"),&(pHWHead->TransmitCritSec)));
- EnterCriticalSection(&(pHWHead->TransmitCritSec));
- RETAILMSG(DEBUGMODE, (TEXT("XmitComChar got CritSec %x.rn"),&(pHWHead->TransmitCritSec)));
- try
- {
- while ( TRUE ) // We know THR will eventually empty
- {
- EnterCriticalSection(&(pHWHead->RegCritSec));
- // Write the character if we can
- rFifoStat = INREG(pHWHead,rUFSTAT);
- TxFifoCnt = (rFifoStat & SER2440_FIFOCNT_MASK_TX) >> 8;
- if (!(rFifoStat & SER2440_FIFOFULL_TX) && (TxFifoCnt < (SER2440_FIFO_DEPTH_TX-1)))
- {
- // FIFO is empty, send this character
- //OUTB(pHWHead, pData, ComChar);
- OUTREG(pHWHead,rUTXH,ComChar);
- // Make sure we release the register critical section
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- RETAILMSG(DEBUGMODE, (TEXT("XmitComChar wrote x%Xrn"),ComChar));
- break;
- }
- // If we couldn't write the data yet, then wait for a
- // TXINTR to come in and try it again.
- // Enable xmit intr.
- EnINT(pHWHead, pHWHead->bINT);
- EnSubINT(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
- pHWHead->fSW_EnTxINT = TRUE;
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- // Wait until the txintr has signalled.
- DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar WaitIntr x%Xrn"),
- pHWHead->FlushDone));
- WaitForSingleObject(pHWHead->FlushDone, (ULONG)1000);
- }
- }
- except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
- EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- // Make sure we release the register critical section
- LeaveCriticalSection(&(pHWHead->RegCritSec));
- }
- LeaveCriticalSection(&(pHWHead->TransmitCritSec));
- DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar released CritSec %x.rn"), &(pHWHead->TransmitCritSec)));
- DEBUGMSG (ZONE_FUNCTION, (TEXT("-SL_XmitComChar 0x%Xrn"), pHead));
- return(TRUE);
- }
- //
- // @doc OEM
- // @func BOOL | SL_PowerOff | Perform powerdown sequence.
- //
- // @rdesc TRUE if succesful
- //
- VOID
- SL_PowerOff(PVOID pHead) // @parm PVOID returned by HWInit.
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- RETAILMSG(0, (TEXT("SL_PowerOff rn")));
- if ( !pHWHead->UseIrDA )
- {
- // DeAssert DTR
- *(pHWHead->rDTRport) |= (1<<(pHWHead->DtrPortNum));
- // DeAssert RTS
- #if USE_AFC
- *(pHWHead->rRTSport) |= (1<<(pHWHead->RtsPortNum));
- #else
- CLEARREG(pHWHead, rUMCON, SER2440_RTS);
- #endif
- }
- pHWHead->sULCON = INREG(pHWHead, rULCON);
- pHWHead->sUCON = INREG(pHWHead, rUCON);
- pHWHead->sUMCON = INREG(pHWHead, rUMCON);
- pHWHead->sUFCON = INREG(pHWHead, rUFCON);
- pHWHead->sINTstat = (*(pHWHead->UART_INTSUBMASK) & (pHWHead->bTxINT | pHWHead->bRxINT));
- }
- //
- // @doc OEM
- // @func BOOL | SL_PowerOn | Perform poweron sequence.
- //
- // @rdesc TRUE if succesful
- //
- VOID
- SL_PowerOn(PVOID pHead) // @parm PVOID returned by HWInit.
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- // Restore any registers that we need
- RETAILMSG(DEBUGMODE, (TEXT("SL_PowerOn rn")));
- if ( !pHWHead->UseIrDA )
- {
- // Assert DTR
- *(pHWHead->rDTRport) &= ~(1<<(pHWHead->DtrPortNum));
- // Assert RTS
- #if USE_AFC
- *(pHWHead->rRTSport) &= ~(1<<(pHWHead->RtsPortNum));
- #else
- SETREG(pHWHead, rUMCON, SER2440_RTS);
- #endif
- }
- // In power handler context, so don't try to do a critical section
- OUTREG(pHWHead, rULCON, pHWHead->sULCON);
- OUTREG(pHWHead, rUCON, pHWHead->sUCON);
- OUTREG(pHWHead, rUMCON, pHWHead->sUMCON);
- OUTREG(pHWHead, rUFCON, pHWHead->sUFCON);
- if((pHWHead->sINTstat) & (pHWHead->bTxINT))
- {
- EnINT(pHWHead, pHWHead->bINT);
- EnSubINT(pHWHead, pHWHead->bTxINT);
- pHWHead->fSW_EnTxINT = TRUE;
- pHWHead->RxDiscard = FALSE;
- }
- if((pHWHead->sINTstat) & (pHWHead->bRxINT))
- {
- EnINT(pHWHead, pHWHead->bINT);
- EnSubINT(pHWHead, pHWHead->bRxINT);
- }
- // And we didn't save the Divisor Reg, so set baud rate
- // But don't call SL_SetBaud, since it does DebugMsg.
- // Call our internal function instead. Can't acquire
- // the RegCritSec, but shouldn't really need to since
- // we are in power context.
- SetBaudRate( pHWHead, pHWHead->dcb.BaudRate );
- return;
- pHWHead->EventCallback( pHWHead->pMddHead, EV_POWER );
- }
- //
- // @doc OEM
- // @func BOOL | SL_SetDCB | Sets new values for DCB. This
- // routine gets a DCB from the MDD. It must then compare
- // this to the current DCB, and if any fields have changed take
- // appropriate action.
- //
- // @rdesc BOOL
- //
- BOOL
- SL_SetDCB(
- PVOID pHead, // @parm PVOID returned by HWInit.
- LPDCB lpDCB // @parm Pointer to DCB structure
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- BOOL bRet;
- bRet = TRUE;
- RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : BaudRate is %drn"), lpDCB->BaudRate));
- RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set ByteSize is %drn"), lpDCB->ByteSize));
- RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set Parity is %drn"), lpDCB->Parity));
- RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set StopBits is %drn"), lpDCB->StopBits));
- // If the device is open, scan for changes and do whatever
- // is needed for the changed fields. if the device isn't
- // open yet, just save the DCB for later use by the open.
- if ( pHWHead->OpenCount )
- {
- // Note, fparity just says whether we should check
- // receive parity. And the 16550 won't let us NOT
- // check parity if we generate it. So this field
- // has no effect on the hardware.
- if ( lpDCB->BaudRate != pHWHead->dcb.BaudRate )
- {
- RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set BaudRate to %drn"), lpDCB->BaudRate));
- bRet = SL_SetBaudRate( pHWHead, lpDCB->BaudRate );
- }
- if ( bRet && (lpDCB->ByteSize != pHWHead->dcb.ByteSize ))
- {
- RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set ByteSize to %drn"), lpDCB->ByteSize));
- bRet = SL_SetByteSize( pHWHead, lpDCB->ByteSize );
- }
- if ( bRet && (lpDCB->Parity != pHWHead->dcb.Parity ))
- {
- RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set Parity to %drn"), lpDCB->Parity));
- bRet = SL_SetParity( pHWHead, lpDCB->Parity );
- }
- if ( bRet && (lpDCB->StopBits != pHWHead->dcb.StopBits ))
- {
- RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set StopBits to %drn"), lpDCB->StopBits));
- bRet = SL_SetStopBits( pHWHead, lpDCB->StopBits );
- }
- // Don't worry about fOutxCtsFlow. It is a flag which
- // will be examined every time we load the TX buffer.
- // No special action required here.
- }
- if (bRet)
- {
- // Now that we have done the right thing, store this DCB
- pHWHead->dcb = *lpDCB;
- }
- RETAILMSG(DEBUGMODE,(TEXT("-SL_SetDCB 0x%Xrn"), pHead));
- return(bRet);
- }
- //
- // @doc OEM
- // @func BOOL | SL_SetCommTimeouts | Sets new values for the
- // CommTimeouts structure. routine gets a DCB from the MDD. It
- // must then compare this to the current DCB, and if any fields
- // have changed take appropriate action.
- //
- // @rdesc ULONG
- //
- ULONG
- SL_SetCommTimeouts(
- PVOID pHead, // @parm PVOID returned by HWInit.
- LPCOMMTIMEOUTS lpCommTimeouts // @parm Pointer to CommTimeout structure
- )
- {
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- ULONG retval = 0;
- RETAILMSG(DEBUGMODE,(TEXT("+SL_SetCommTimeout 0x%Xrn"), pHead));
- // ShowSerialRegisters(pHead);
- // OK, first check for any changes and act upon them
- if ( lpCommTimeouts->WriteTotalTimeoutMultiplier !=
- pHWHead->CommTimeouts.WriteTotalTimeoutMultiplier )
- {
- }
- // Now that we have done the right thing, store this DCB
- pHWHead->CommTimeouts = *lpCommTimeouts;
- RETAILMSG(DEBUGMODE,(TEXT("-SL_SetCommTimeout 0x%Xrn"), pHead));
- return(retval);
- }
- //
- // @doc OEM
- // @func BOOL | SL_Ioctl | Device IO control routine.
- // @parm DWORD | dwOpenData | value returned from COM_Open call
- // @parm DWORD | dwCode | io control code to be performed
- // @parm PBYTE | pBufIn | input data to the device
- // @parm DWORD | dwLenIn | number of bytes being passed in
- // @parm PBYTE | pBufOut | output data from the device
- // @parm DWORD | dwLenOut |maximum number of bytes to receive from device
- // @parm PDWORD | pdwActualOut | actual number of bytes received from device
- //
- // @rdesc Returns TRUE for success, FALSE for failure
- //
- // @remark The MDD will pass any unrecognized IOCTLs through to this function.
- //
- BOOL
- SL_Ioctl(PVOID pHead, DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,
- PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
- {
- // PSER_INFO pHWHead = (PSER_INFO)pHead;
- PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
- DWORD dwErr = ERROR_SUCCESS;
- BOOL bRc = TRUE;
- switch (dwCode)
- {
- //
- // Power Management
- //
- case IOCTL_POWER_CAPABILITIES:
- {
- PPOWER_CAPABILITIES ppc;
- if ( !pdwActualOut || !pBufOut || (dwLenOut < sizeof(POWER_CAPABILITIES)))
- {
- bRc = FALSE;
- dwErr = ERROR_INVALID_PARAMETER;
- break;
- }
- ppc = (PPOWER_CAPABILITIES)pBufOut;
- memset(ppc, 0, sizeof(POWER_CAPABILITIES));
- // ppc->DeviceDx = 0x11; // support D0, D4
- ppc->DeviceDx = 0x11; // support D0-D2, D4 (no D3)
- // no wake
- // no inrush
- // Report our power consumption in uAmps rather than mWatts.
- ppc->Flags = POWER_CAP_PREFIX_MICRO | POWER_CAP_UNIT_AMPS;
- // (UART @ 1.2 mA + IR Transmitter LED ON @ 32 mA) = 33.2 mA = 33200 uA @ 200 MHz
- // IR Transmitter LED OFF @ 1.5 nA
- ppc->Power[D0] = 33200;
- *pdwActualOut = sizeof(POWER_CAPABILITIES);
- }
- break;
- case IOCTL_POWER_SET:
- {
- CEDEVICE_POWER_STATE NewDx;
- if ( !pdwActualOut || !pBufOut || (dwLenOut < sizeof(CEDEVICE_POWER_STATE)))
- {
- bRc = FALSE;
- dwErr = ERROR_INVALID_PARAMETER;
- break;
- }
- NewDx = *(PCEDEVICE_POWER_STATE)pBufOut;
- if ( VALID_DX(NewDx))
- {
- // grab the CS since the normal Xxx_PowerXxx can not.
- EnterCriticalSection( &pHWHead->RegCritSec );
- switch ( NewDx )
- {
- case D0:
- SerPowerOn(pHead);
- break;
- default:
- SerPowerOff(pHead);
- break;
- }
- // return our Dx
- *(PCEDEVICE_POWER_STATE)pBufOut = pHWHead->Dx;
- RETAILMSG(1, (TEXT("IrDA: IOCTL_POWER_SET: D%u => D%u rn"),
- NewDx, pHWHead->Dx));
- LeaveCriticalSection( &pHWHead->RegCritSec );
- *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
- }
- else
- {
- bRc = FALSE;
- dwErr = ERROR_INVALID_PARAMETER;
- }
- }
- break;
- case IOCTL_POWER_GET:
- if ( !pdwActualOut || !pBufOut || (dwLenOut < sizeof(CEDEVICE_POWER_STATE)))
- {
- bRc = FALSE;
- dwErr = ERROR_INVALID_PARAMETER;
- break;
- }
- *(PCEDEVICE_POWER_STATE)pBufOut = pHWHead->Dx;
- DEBUGMSG(1, (TEXT("IrDA: IOCTL_POWER_GET: D%u rn"), pHWHead->Dx));
- *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
- break;
- default:
- bRc = FALSE;
- DEBUGMSG (ZONE_FUNCTION, (TEXT(" Unsupported ioctl 0x%Xrn"), dwCode));
- break;
- }
- return(bRc);
- }