SER2440_HW.C
上传用户:qiulin1960
上传日期:2013-10-16
资源大小:2844k
文件大小:68k
源码类别:

Windows CE

开发平台:

Windows_Unix

  1. /*++
  2. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. PARTICULAR PURPOSE.
  6. Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.
  7. Copyright (c) 2001-2002 SAMSUNG Electronics Corporation.  All rights reserved.
  8. Author hmseo@sec.samsung.com (SAMSUNG Electronics)
  9. Module Name:  
  10. ser2440_hw.c
  11. Abstract:  
  12.     This file implements the standard device specific functions for a S3C2440
  13.     based serial device.
  14. Functions:
  15. SER_RegAlloc
  16. SER_VirtualAlloc
  17. SER_VirtualFree
  18. ReadLSR
  19. ReadMSR
  20. ShowSerialRegisters
  21. ClearPendingInts
  22. S2440_SetIrDAIOP
  23. S2440_SetSerialIOP
  24. S2440_SetIOP
  25. SL_Open
  26. SL_Close
  27. SL_Init
  28. SL_PostInit
  29. SL_Deinit
  30. SL_ClearDTR
  31. SL_SetDTR
  32. SL_ClearRTS
  33. SL_SetRTS
  34. SL_ClearBreak
  35. SL_SetBreak
  36. SetBaudRate
  37. SL_SetBaudRate
  38. SL_SetByteSize
  39. SL_SetParity
  40. SL_SetStopBits
  41. SL_GetRxBufferSize
  42. SL_GetRxStart
  43. SL_GetInterruptType
  44. SL_RxIntr
  45. SL_PutBytes
  46. SL_TxIntr
  47. SL_TxIntrEx
  48. SL_LineIntr
  49. SL_OtherIntr
  50. SL_ModemIntr
  51. SL_GetStatus
  52. SL_Reset
  53. SL_GetModemStatus
  54. SL_PurgeComm
  55. SL_XmitComChar
  56. SL_PowerOff
  57. SL_PowerOn
  58. SL_SetDCB
  59. SL_SetCommTimeouts
  60. SL_Ioctl
  61. --*/
  62. #define DEBUGMODE 0
  63. #define ZONE_FUNCTION 1
  64. #define USERDBG 1
  65. #define ZONE_WRITE 1
  66. #include <windows.h>
  67. #include <types.h>
  68. #include <ceddk.h>
  69. #include <memory.h>
  70. #include <serhw.h>
  71. #include <ser16550.h>
  72. #include <hw16550.h>
  73. #include <nkintr.h>
  74. #include <devload.h>
  75. #include <windev.h>
  76. #include <notify.h>
  77. #include <pm.h>
  78. #include <excpt.h>
  79. #include "pmplatform.h"
  80. #include "S2440.h"
  81. #include "ser2440.h"
  82. #define PUBLIC
  83. #define PRIVATE static
  84. PRIVATE volatile IOPreg   * v_pIOPregs;
  85. PRIVATE volatile UART0reg * v_pUART0regs;
  86. PRIVATE volatile UART1reg * v_pUART1regs;
  87. PRIVATE volatile UART2reg * v_pUART2regs;
  88. PRIVATE volatile INTreg   * v_pINTregs;
  89. PRIVATE volatile PWMreg   * v_pPWMregs;
  90. VOID SER_VirtualFree(VOID);
  91. BOOL SER_VirtualAlloc(VOID);
  92. VOID ReadLSR(PVOID pHead);
  93. VOID ReadMSR(PVOID pHead);
  94. BOOL SL_SetByteSize(PVOID pHead, ULONG ByteSize);
  95. BOOL SL_SetStopBits(PVOID pHead, ULONG StopBits);
  96. BOOL SL_SetParity(PVOID pHead, ULONG Parity);
  97. BOOL SerPowerOn(PVOID   pHead);
  98. BOOL SerPowerOff(PVOID   pHead);
  99. #define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION 
  100. PRIVATE PVOID
  101. SER_RegAlloc(PVOID addr, INT sz)
  102. {
  103. PVOID reg;
  104. reg = (PVOID)VirtualAlloc(0, sz, MEM_RESERVE, PAGE_NOACCESS);
  105. if (reg)
  106. {
  107. if (!VirtualCopy(reg, addr, sz, PAGE_READWRITE | PAGE_NOCACHE )) 
  108. {
  109. VirtualFree(reg, sz, MEM_RELEASE);
  110. reg = NULL;
  111. }
  112. }
  113. return reg;
  114. }
  115. PRIVATE BOOL
  116. SER_VirtualAlloc(VOID)
  117. {
  118. BOOL r = FALSE;
  119.     RETAILMSG(DEBUGMODE,(TEXT("::: SER_VirtualAlloc()rn")));
  120. do
  121. {
  122. v_pIOPregs = (volatile IOPreg *)SER_RegAlloc((PVOID)IOP_BASE, sizeof(IOPreg));
  123. if (v_pIOPregs == NULL) 
  124. {
  125. ERRORMSG(1,(TEXT("For IOPreg: VirtualAlloc failed!rn")));
  126. break;
  127. }
  128. v_pUART0regs = (volatile UART0reg *)SER_RegAlloc((PVOID)UART0_BASE, sizeof(UART0reg));
  129. if (v_pUART0regs == NULL) 
  130. {
  131.      ERRORMSG(1,(TEXT("For UART0reg: VirtualAlloc failed!rn")));
  132.     break;
  133. }
  134. v_pUART1regs = (volatile UART1reg *)SER_RegAlloc((PVOID)UART1_BASE, sizeof(UART1reg));
  135. if (v_pUART1regs == NULL) 
  136. {
  137.      ERRORMSG(1,(TEXT("For UART1reg: VirtualAlloc failed!rn")));
  138.     break;
  139. }
  140. v_pUART2regs = (volatile UART2reg *)SER_RegAlloc((PVOID)UART2_BASE, sizeof(UART2reg));
  141. if (v_pUART2regs == NULL) 
  142. {
  143.      ERRORMSG(1,(TEXT("For UART2reg: VirtualAlloc failed!rn")));
  144.     break;
  145. }
  146. v_pINTregs = (volatile INTreg *)SER_RegAlloc((PVOID)INT_BASE, sizeof(INTreg));
  147. if (v_pINTregs == NULL) 
  148. {
  149.      ERRORMSG(1,(TEXT("For INTregs: VirtualAlloc failed!rn")));
  150.     break;
  151. }
  152. v_pPWMregs = (volatile PWMreg *)SER_RegAlloc((PVOID)PWM_BASE, sizeof(PWMreg));
  153. if (v_pPWMregs == NULL) 
  154. {
  155.      ERRORMSG(1,(TEXT("For PWMregs: VirtualAlloc failed!rn")));
  156.     break;
  157. }
  158. r = TRUE;
  159. } while (0);
  160. if (!r)
  161. {
  162. SER_VirtualFree();
  163. RETAILMSG(DEBUGMODE,(TEXT("::: SER_VirtualAlloc() - Failrn")));
  164. }
  165. else
  166. {
  167. RETAILMSG(DEBUGMODE,(TEXT("::: SER_VirtualAlloc() - Successrn")));
  168. }
  169. return r;
  170. }
  171. PRIVATE void
  172. SER_VirtualFree(VOID)
  173. {
  174.     RETAILMSG(DEBUGMODE,(TEXT("::: SER_VirtualFree()rn")));
  175. if (v_pIOPregs)
  176.     {
  177.         VirtualFree((PVOID)v_pIOPregs, sizeof(IOPreg), MEM_RELEASE);
  178.         v_pIOPregs = NULL;
  179.     }
  180.     if (v_pUART0regs)
  181.     {   
  182.         VirtualFree((PVOID)v_pUART0regs, sizeof(UART0reg), MEM_RELEASE);
  183.         v_pUART0regs = NULL;
  184.     } 
  185.     if (v_pUART1regs)
  186.     {   
  187.         VirtualFree((PVOID)v_pUART1regs, sizeof(UART1reg), MEM_RELEASE);
  188.         v_pUART1regs = NULL;
  189.     } 
  190.     if (v_pUART2regs)
  191.     {   
  192.         VirtualFree((PVOID)v_pUART2regs, sizeof(UART2reg), MEM_RELEASE);
  193.         v_pUART2regs = NULL;
  194.     } 
  195.     if (v_pINTregs)
  196.     {   
  197.         VirtualFree((PVOID)v_pINTregs, sizeof(INTreg), MEM_RELEASE);
  198.         v_pINTregs = NULL;
  199.     } 
  200.     if (v_pPWMregs)
  201.     {   
  202.         VirtualFree((PVOID)v_pPWMregs, sizeof(INTreg), MEM_RELEASE);
  203.         v_pPWMregs = NULL;
  204.     } 
  205. }
  206. //
  207. // Reading the LSR clears most of its bits.  So, we provide this wrapper,
  208. // which reads the register, records any interesting values, and
  209. // stores the current LSR contents in the shadow register.
  210. //
  211. //__inline
  212. VOID
  213. ReadLSR(PVOID pHead)
  214. {
  215. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  216. ULONG LineEvents             = 0;
  217. ULONG LineStatus             = 0;
  218. UCHAR tmp;
  219. pHWHead->CommErrors = 0; // Clear old errors each time
  220. RETAILMSG(DEBUGMODE, (TEXT("ReadLSR rn")));
  221. try 
  222. {
  223. LineStatus = INREG(pHWHead,rUERSTAT);
  224. RETAILMSG(DEBUGMODE,  (TEXT("Line Status Register : 0x%xrn"), LineStatus));
  225. }
  226. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  227. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 
  228. {
  229. // pHWHead->LSR = SERIAL_LSR_THRE;
  230. }
  231. if ( LineStatus & (COM2440_LSR_OE | COM2440_LSR_PE | COM2440_LSR_FE))
  232. {
  233. // Note: Its not wise to do debug msgs in here since they will
  234. // pretty much guarantee that the FIFO gets overrun.
  235. if ( LineStatus & COM2440_LSR_OE )
  236. {
  237. // When overrun error occurs, S2440 rURXH must be read.
  238. tmp = *(pHWHead->pUFRXH);
  239. pHWHead->DroppedBytes++;
  240. pHWHead->CommErrors |= CE_OVERRUN;
  241. LineEvents |= EV_ERR;
  242. }
  243. if ( LineStatus & COM2440_LSR_PE )
  244. {
  245. pHWHead->CommErrors |= CE_RXPARITY;
  246. LineEvents |= EV_ERR;
  247. }
  248. if ( LineStatus & COM2440_LSR_FE )
  249. {
  250. pHWHead->CommErrors |= CE_FRAME;
  251. LineEvents |= EV_ERR;
  252. }
  253. }
  254. if ( LineStatus & COM2440_LSR_BI )
  255. LineEvents |= EV_BREAK;
  256. // Let WaitCommEvent know about this error
  257. if ( LineEvents )
  258. pHWHead->EventCallback( pHWHead->pMddHead, LineEvents );
  259. }
  260. //
  261. // Reading the MSR clears many of its bits.  So, we provide this wrapper,
  262. // which reads the register, records any interesting values, and
  263. // stores the current MSR contents in the shadow register.
  264. // Note that we always have DDCD and DCTS enabled, so if someone
  265. // wants to keep an eye on these lines, its OK to simply read the
  266. // shadow register, since if the value changes, the interrupt
  267. // will cause the shadow to be updated.
  268. //
  269. //__inline
  270. VOID
  271. ReadMSR(PVOID pHead)
  272. {
  273. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  274. ULONG Events = 0;
  275. ULONG msr, msr_DSR;
  276. RETAILMSG(DEBUGMODE, (TEXT("ReadMSR rn")));
  277. try 
  278. {
  279. // read nCTS status
  280. msr = INREG(pHWHead,rUMSTAT);
  281. RETAILMSG(DEBUGMODE,  (TEXT("Modem Status Register : 0x%xrn"), msr));
  282. // read nDSR status 
  283. // - As you know this routine is valid only at the SMDK2440 board.
  284. if ( !pHWHead->UseIrDA )
  285. {
  286. if(*(pHWHead->rDSRport) & (1<<(pHWHead->DsrPortNum))) // Low active
  287.     msr_DSR = 0;
  288. else
  289.     msr_DSR = 1;
  290. }
  291. }
  292. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  293. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  294. {
  295. msr = 0;
  296. }
  297.     // Save the MSR value in a shadow
  298.     pHWHead->MSR = msr;
  299. // For changes, we use callback to evaluate the event
  300. if (msr & COM2440_MSR_DCTS)  // Delta CTS (SERIAL_MSR_DCTS)
  301. {
  302. Events |= EV_CTS;
  303. pHWHead->vUMSTAT |= COM2440_MSR_DCTS;
  304. if(msr & COM2440_MSR_CTS) 
  305. pHWHead->vUMSTAT |= COM2440_MSR_CTS;
  306. else
  307. pHWHead->vUMSTAT &= ~COM2440_MSR_CTS;
  308. // S2440 does not support Delta DSR status by H/W,
  309. // so we have to check this by S/W.
  310. //
  311. // if(DSR : High->Low) - became active
  312. if (msr_DSR) // S2440 Evaluation Board bidged these two pins.
  313. {
  314. if(!(pHWHead->vUMSTAT & COM2440_MSR_DSR))
  315. {
  316. pHWHead->vUMSTAT |= COM2440_MSR_DDSR;
  317. Events |= EV_DSR;
  318. Events |= EV_RLSD;  // DCD
  319. }    // there is a change... H->L(became active)
  320. else
  321. pHWHead->vUMSTAT &= ~COM2440_MSR_DDSR;
  322. pHWHead->vUMSTAT |= COM2440_MSR_DSR;
  323. }
  324. // if(DSR : Low->High) - became in-active
  325. else
  326. {
  327. if((pHWHead->vUMSTAT & COM2440_MSR_DSR))
  328. {
  329. pHWHead->vUMSTAT |= COM2440_MSR_DDSR;
  330. Events |= EV_DSR;
  331. Events |= EV_RLSD;  // DCD
  332. }   // there is a change... L->H (became inactive)
  333. else
  334. pHWHead->vUMSTAT &= ~COM2440_MSR_DDSR;
  335. pHWHead->vUMSTAT &= ~COM2440_MSR_DSR;
  336. }
  337. RETAILMSG(DEBUGMODE,  (TEXT("ReadMSR Events:0x%xrn"), Events));
  338. RETAILMSG(DEBUGMODE,  (TEXT("ReadMSR MSR:0x%xrn"), msr));
  339. RETAILMSG(DEBUGMODE,  (TEXT("ReadMSR MSR_DSR:0x%xrn"), msr_DSR));   
  340. if ( Events )
  341. pHWHead->EventCallback( pHWHead->pMddHead, Events );
  342. }
  343. VOID
  344. ShowSerialRegisters(PVOID  pHead)
  345. {
  346. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  347. RETAILMSG(1, (TEXT("InterruptType : 0x%X, 0x%X, 0x%X, 0x%Xrn"), 
  348. *(pHWHead->UART_INTMASK), 
  349. *(pHWHead->UART_INTSUBMASK),  
  350. *(pHWHead->UART_INTSRCPND), 
  351. *(pHWHead->UART_INTSUBSRCPND)));
  352. RETAILMSG(1,  (TEXT("rULCON: 0x%x "), pHWHead->s2440SerReg->rULCON));
  353. RETAILMSG(1,  (TEXT("rUCON: 0x%x "), pHWHead->s2440SerReg->rUCON));
  354. RETAILMSG(1,  (TEXT("rUFCON: 0x%x "), pHWHead->s2440SerReg->rUFCON));
  355. RETAILMSG(1,  (TEXT("rUMCON: 0x%x "), pHWHead->s2440SerReg->rUMCON));
  356. RETAILMSG(1,  (TEXT("rUERSTAT: 0x%x "), pHWHead->s2440SerReg->rUERSTAT));
  357. RETAILMSG(1,  (TEXT("rUFSTAT: 0x%x "), pHWHead->s2440SerReg->rUFSTAT));
  358. RETAILMSG(1,  (TEXT("rUMSTAT: 0x%x "), pHWHead->s2440SerReg->rUMSTAT));
  359. RETAILMSG(1,  (TEXT("rUTXH: 0x%x "), pHWHead->s2440SerReg->rUTXH));
  360. RETAILMSG(1,  (TEXT("rURXH: 0x%x "), pHWHead->s2440SerReg->rURXH));
  361. RETAILMSG(1,  (TEXT("rUBRDIV: 0x%xrn"), pHWHead->s2440SerReg->rUBRDIV));
  362. RETAILMSG(1,  (TEXT("pHWHead->vUMSTAT: 0x%x rn"), pHWHead->vUMSTAT));
  363. RETAILMSG(1,  (TEXT("pHWHead->CTSFlowOff: 0x%x rnrn"), pHWHead->CTSFlowOff));
  364. }
  365. #define BAUD_TABLE_SIZE 23
  366. static const
  367. PAIRS    LS_BaudPairs[BAUD_TABLE_SIZE] =
  368. {
  369. {50,        2307},
  370. {75,        1538},
  371. {110,       1049},
  372. {135,        858},
  373. {150,        769},
  374. {300,        384},
  375. {600,        192},
  376. {1200,        96},
  377. {1800,        64},
  378. {2000,        58},
  379. {2400,        48},
  380. {3600,        32},
  381. {4800,        24},
  382. {7200,        16},
  383. {9600,        12},
  384. {12800,        9},
  385. {14400,        8},
  386. {19200,        6},
  387. {23040,        5},
  388. {28800,        4},
  389. {38400,        3},
  390. {57600,        2},
  391. {115200,       1}
  392. };
  393. static const
  394. LOOKUP_TBL  LS_BaudTable = {BAUD_TABLE_SIZE, (PAIRS *) LS_BaudPairs};
  395. // Routine to clear any pending interrupts.  Called from Init and PostInit
  396. // to make sure we atart out in a known state.
  397. VOID
  398. ClearPendingInts(PVOID   pHead) // @parm PVOID returned by HWinit.
  399. {
  400. PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
  401. UINT32 tmpReg;
  402. EnterCriticalSection(&(pHWHead->RegCritSec));
  403. RETAILMSG(DEBUGMODE,(TEXT("ClearPendingInts rn")));
  404. try
  405. {
  406. SETREG(pHWHead,rUFCON,0x6);    // tx, rx fifo reset
  407. ClearSubINTPnd(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
  408. ClearINTPnd(pHWHead, pHWHead->bINT);
  409. tmpReg = INREG(pHWHead,rUERSTAT);
  410. }
  411. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  412. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  413. {
  414. RETAILMSG(1,(TEXT("SL_PostInit, 0x%X - ERRORrn"), pHWHead));
  415. // Just fall through & release CritSec
  416. }
  417. LeaveCriticalSection(&(pHWHead->RegCritSec));
  418. }
  419. // Routine to set some 2440 IO Ports.
  420. VOID
  421. S2440_SetIrDAIOP(PVOID   pHead) // @parm points to device head
  422. {
  423. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  424. RETAILMSG(DEBUGMODE, (TEXT("S2440_SetIrDAIOP rn")));
  425. EnterCriticalSection(&(pHWHead->RegCritSec));
  426. // by jylee 2003.04.15
  427. v_pIOPregs->rGPBCON &= ~(0x3<<2); // clear GPBCON for GPB1 (nIRDAEN)
  428. v_pIOPregs->rGPBCON |=  (0x1<<2); // set GPBCON for GPB1 output
  429. v_pIOPregs->rGPBUP  |=  (0x1<<1); // set GPB1 pullup disable (external pullup)
  430. v_pIOPregs->rGPBDAT &= ~(0x1<<1); // set GPB1 signal low 
  431. v_pIOPregs->rGPHCON &= ~(0x3<<12 | 0x3<<14); // clear uart 2 - rx, tx
  432. v_pIOPregs->rGPHCON |=  (0x2<<12 | 0x2<<14); 
  433. v_pIOPregs->rGPHUP  |=  0xc0;
  434. LeaveCriticalSection(&(pHWHead->RegCritSec));
  435. }
  436. S2440_SetSerialIOP(PVOID   pHead) // @parm points to device head
  437. {
  438. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  439. RETAILMSG(DEBUGMODE, (TEXT("S2440_SetSerialIOP rn")));
  440. EnterCriticalSection(&(pHWHead->RegCritSec));
  441. v_pIOPregs->rGPHCON &= ~(0x3<<0 | 0x3<<2 | 0x3<<4 | 0x3<<6); // clear uart 0 - rx, tx
  442. v_pIOPregs->rGPHCON |= (0x2<<4 | 0x2<<6); 
  443. v_pIOPregs->rGPDCON &= ~(0x3<<0 | 0x3<<2);
  444. v_pIOPregs->rGPDCON |= (0x1<<0 | 0x0<<2);
  445. #if USE_AFC
  446. // set nRTS to GPO mode
  447. // for software flow-control
  448. v_pIOPregs->rGPHCON |= (0x2<<0 | 0x1<<2 );
  449. #else
  450. v_pIOPregs->rGPHCON |= (0x2<<0 | 0x2<<2 );
  451. #endif
  452. /*
  453. In the SMDK2440 board, if IRDA is enabled, following values are ignored.
  454. */
  455. #if 0 // Board version is not 0.17
  456. v_pIOPregs->rGPHUP  |= 0xc3;
  457. pHWHead->rDTRport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
  458. pHWHead->rDSRport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
  459. pHWHead->DtrPortNum = 6;
  460. pHWHead->DsrPortNum = 7;
  461. #endif
  462. v_pIOPregs->rGPDUP  |= 0x3;
  463. pHWHead->rDTRport = (volatile unsigned int *)&(v_pIOPregs->rGPDDAT);
  464. pHWHead->rDSRport = (volatile unsigned int *)&(v_pIOPregs->rGPDDAT);
  465. pHWHead->DtrPortNum = 0;
  466. pHWHead->DsrPortNum = 1;
  467. #if USE_AFC    
  468.   pHWHead->rCTSport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
  469. pHWHead->rRTSport = (volatile unsigned int *)&(v_pIOPregs->rGPHDAT);
  470. pHWHead->CtsPortNum = 0;
  471. pHWHead->RtsPortNum = 1;
  472. #endif
  473. LeaveCriticalSection(&(pHWHead->RegCritSec));
  474. }
  475. VOID
  476. S2440_SetIOP(PVOID   pHead) // @parm points to device head
  477. {
  478. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  479. if ( pHWHead->UseIrDA )
  480. {
  481. RETAILMSG(DEBUGMODE, (TEXT("S2440_SetIOP : IRDArn")));
  482. S2440_SetIrDAIOP(pHWHead);
  483. }
  484. else
  485. {
  486. RETAILMSG(DEBUGMODE, (TEXT("S2440_SetIOP : SERIALrn")));
  487. S2440_SetSerialIOP(pHWHead);
  488. }
  489. }
  490. //
  491. /////////////////// Start of exported entrypoints ////////////////
  492. //
  493. //
  494. // @doc OEM 
  495. // @func PVOID | SL_Open | Configures 16550 for default behaviour.
  496. //
  497. VOID
  498. SL_Open(PVOID   pHead) // @parm PVOID returned by HWinit.
  499. {
  500. PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
  501. RETAILMSG(1, (TEXT("SL_Open 0x%X (%d opens)rn"), pHead, pHWHead->OpenCount));
  502. // If the device is already open, all we do is increment count
  503. if ( pHWHead->OpenCount++ )
  504. {
  505. RETAILMSG(1, (TEXT("SL_Open 0x%X (%d opens)rn"), pHead, pHWHead->OpenCount));
  506. return ;
  507. }
  508. pHWHead->DroppedBytes = 0;
  509. pHWHead->CTSFlowOff   = FALSE;  // Not flowed off yet
  510. pHWHead->DSRFlowOff   = FALSE;  // Not flowed off yet
  511. pHWHead->CommErrors   = 0;
  512. pHWHead->ModemStatus  = 0;
  513. pHWHead->ConSetup     = 6;
  514. pHWHead->vUMSTAT      = 0;
  515. pHWHead->fSW_EnTxINT  = FALSE;
  516. EnterCriticalSection(&(pHWHead->RegCritSec));
  517. try
  518. {
  519. S2440_SetIOP(pHead);
  520. // Get defaults from the DCB structure
  521. SL_SetBaudRate( pHead, pHWHead->dcb.BaudRate );
  522. SL_SetByteSize( pHead, pHWHead->dcb.ByteSize );
  523. SL_SetStopBits( pHead, pHWHead->dcb.StopBits );
  524. SL_SetParity(pHead, pHWHead->dcb.Parity );
  525. // UART Control, Modem, Fifo register setting.
  526. OUTREG(pHWHead,rUCON,0x2c5);   //Clock selection=PCLK, tx=level,rx=pulse,enable timeout int.,
  527. //enable rx error int., Tx int, Rx int
  528. OUTREG(pHWHead,rUFCON,0x6);    // Reset FIFO
  529. if (pHWHead->UseIrDA) 
  530. {
  531. OUTREG(pHWHead,rUFCON,0x41);   //FIFO enable : tx-4bytes, rx-4bytes
  532. OUTREG(pHWHead,rUMCON,0x00);   //Disable auto flow control.
  533. }
  534. else 
  535. {
  536. #if USE_AFC
  537. // by shin.0212.
  538. OUTREG(pHWHead,rUFCON,0x61);   //FIFO enable : tx-4bytes, rx-12bytes
  539. OUTREG(pHWHead,rUMCON,0x10);   //Enable auto flow control.  
  540. #else
  541. OUTREG(pHWHead,rUFCON,0x41);   //FIFO enable : tx-4bytes, rx-4bytes
  542. OUTREG(pHWHead,rUMCON,0x00);   //Disable auto flow control.
  543. #endif
  544. }
  545. if ( pHWHead->UseIrDA )
  546. SETREG(pHWHead,rULCON,SER2440_IRMODE_MASK);   // Infra-red mode enable.
  547. ClearPendingInts( pHWHead );
  548. EnINT(pHWHead, pHWHead->bINT);
  549. EnSubINT(pHWHead, pHWHead->bRxINT);
  550. // For CE 3.0, we are still supporting
  551. // the old style MDDs, and they don't call our PostInit, which
  552. // needs to happen sometime prior to this.  So for now, we go ahead
  553. // ahead and clear out interrupts one last time.  In 4.0, we can
  554. // kill the old serial MDD and assume that everyone uses the new
  555. // MDD and calls post init.  
  556. SL_PostInit(pHWHead);
  557. ReadLSR(pHWHead);
  558. }
  559. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  560. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  561. {
  562. // Just get out of here.
  563. }
  564. LeaveCriticalSection(&(pHWHead->RegCritSec));
  565. }
  566. //
  567. // @doc OEM 
  568. // @func PVOID | SL_Close | Does nothing except keep track of the
  569. // open count so that other routines know what to do.
  570. //
  571. VOID
  572. SL_Close(PVOID   pHead) // @parm PVOID returned by HWinit.
  573. {
  574. PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
  575. RETAILMSG(1, (TEXT("SL_Close rn")));
  576. if ( pHWHead->OpenCount ) pHWHead->OpenCount--;
  577. EnterCriticalSection(&(pHWHead->RegCritSec));
  578. try
  579. {
  580. SL_ClearRTS( pHWHead );
  581. OUTREG(pHWHead,rUMSTAT,0x0);
  582. // Disable all interrupts and clear MCR.
  583. DisEnSubINT(pHWHead, pHWHead->bRxINT);
  584. pHWHead->fSW_EnTxINT = FALSE;
  585. // This routhine for auto detect.
  586. S2440_SetIrDAIOP(pHead);
  587. }
  588. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  589. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  590. {
  591. // Just get out of here.
  592. }
  593. LeaveCriticalSection(&(pHWHead->RegCritSec));
  594. }
  595. //
  596. // @doc OEM 
  597. // @func PVOID | SL_Init | Initializes 16550 device head.  
  598. //
  599. VOID
  600. SL_Init(
  601.        PVOID   pHead, // @parm points to device head
  602.        PUCHAR  pRegBase, // Pointer to 16550 register base
  603.        UINT8   RegStride, // Stride amongst the 16550 registers
  604.        EVENT_FUNC EventCallback, // This callback exists in MDD
  605.        PVOID   pMddHead,   // This is the first parm to callback
  606.        PLOOKUP_TBL   pBaudTable  // BaudRate Table
  607.        )
  608. {
  609. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  610. RETAILMSG(DEBUGMODE, (TEXT("SL_Init : IRDA = %d rn"), pHWHead->UseIrDA));
  611. SER_VirtualAlloc();
  612. if ( pHWHead->UseIrDA )
  613. {
  614. pHWHead->bINT = BIT_UART2;
  615. pHWHead->bTxINT = INTSUB_TXD2;
  616. pHWHead->bRxINT = INTSUB_RXD2;
  617. pHWHead->bErrINT = INTSUB_ERR2;
  618. pHWHead->s2440SerReg = (S2440_UART_REG *)v_pUART2regs;
  619. pRegBase = (PUCHAR)pHWHead->s2440SerReg;
  620. }
  621. else
  622. {
  623. pHWHead->bINT = BIT_UART0;
  624. pHWHead->bTxINT = INTSUB_TXD0;
  625. pHWHead->bRxINT = INTSUB_RXD0;
  626. pHWHead->bErrINT = INTSUB_ERR0;
  627. pHWHead->s2440SerReg = (S2440_UART_REG *)v_pUART0regs;
  628. pRegBase = (PUCHAR)pHWHead->s2440SerReg;
  629. }
  630. pHWHead->UART_INTMASK = (volatile unsigned int *)&(v_pINTregs->rINTMSK);
  631. pHWHead->UART_INTSUBMASK = (volatile unsigned int *)&(v_pINTregs->rINTSUBMSK);
  632. pHWHead->UART_INTPND = (volatile unsigned int *)&(v_pINTregs->rINTPND);
  633. pHWHead->UART_INTSRCPND = (volatile unsigned int *)&(v_pINTregs->rSRCPND);
  634. pHWHead->UART_INTSUBSRCPND = (volatile unsigned int *)&(v_pINTregs->rSUBSRCPND);
  635. pHWHead->vUMSTAT = 0;
  636. if ( pHWHead->UseIrDA )
  637. {
  638. pHWHead->pUFTXH = (volatile unsigned char *)&(v_pUART2regs->rUTXH);
  639. pHWHead->pUFRXH = (volatile unsigned char *)&(v_pUART2regs->rURXH);    
  640. }
  641. else
  642. {
  643. pHWHead->pUFTXH = (volatile unsigned char *)&(v_pUART0regs->rUTXH);
  644. pHWHead->pUFRXH = (volatile unsigned char *)&(v_pUART0regs->rURXH);    
  645. }
  646. RETAILMSG(DEBUGMODE, (TEXT("+ S2440_SetIrDAIOP rn")));
  647. S2440_SetIrDAIOP(pHead);
  648. RETAILMSG(DEBUGMODE, (TEXT("- S2440_SetIrDAIOP rn")));
  649. // Store info for callback function
  650. pHWHead->EventCallback = EventCallback;
  651. pHWHead->pMddHead = pMddHead;
  652. // Now set up remaining fields
  653. if ( pBaudTable != NULL )
  654. pHWHead->pBaudTable = (LOOKUP_TBL *) pBaudTable;
  655. else
  656. pHWHead->pBaudTable = (LOOKUP_TBL *) &LS_BaudTable;
  657. pHWHead->FlushDone      = CreateEvent(0, FALSE, FALSE, NULL);
  658. pHWHead->OpenCount = 0;
  659. // Don't allow any interrupts till PostInit.
  660. DisEnINT(pHWHead, pHWHead->bINT);
  661. DisEnSubINT(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
  662. pHWHead->fSW_EnTxINT = FALSE;
  663. pHWHead->RxDiscard = FALSE;
  664. InitializeCriticalSection(&(pHWHead->TransmitCritSec));
  665. InitializeCriticalSection(&(pHWHead->RegCritSec));
  666. // Clear any interrupts which may be pending.  Normally only
  667. // happens if we were warm reset.
  668. ClearPendingInts( pHWHead );
  669. }
  670. //
  671. // @doc OEM
  672. // @func void | SL_PostInit | This routine takes care of final initialization.
  673. //
  674. // @rdesc None.
  675. //
  676. BOOL
  677. SL_PostInit(PVOID   pHead) // @parm PVOID returned by HWinit.
  678. {
  679. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  680. RETAILMSG(DEBUGMODE, (TEXT("SL_PostInit rn")));
  681. // Since we are just a library which might get used for 
  682. // builtin ports which init at boot, or by PCMCIA ports
  683. // which init at Open, we can't do anything too fancy.
  684. // Lets just make sure we cancel any pending interrupts so
  685. // that if we are being used with an edge triggered PIC, he
  686. // will see an edge after the MDD hooks the interrupt.
  687. ClearPendingInts( pHWHead );
  688. return(TRUE);
  689. }
  690. //
  691. // @doc OEM 
  692. // @func PVOID | SL_Deinit | De-initializes 16550 device head.  
  693. //
  694. VOID
  695. SL_Deinit(PVOID   pHead) // @parm points to device head
  696. {
  697. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  698. RETAILMSG(DEBUGMODE, (TEXT("SL_Deinit rn")));
  699. DeleteCriticalSection(&(pHWHead->TransmitCritSec));
  700. DeleteCriticalSection(&(pHWHead->RegCritSec));
  701. // Free the flushdone event
  702. if ( pHWHead->FlushDone )
  703.     CloseHandle( pHWHead->FlushDone );
  704. SER_VirtualFree();
  705. }
  706. //
  707. // @doc OEM
  708. // @func void | SL_ClearDtr | This routine clears DTR.
  709. //
  710. // @rdesc None.
  711. //
  712. VOID
  713. SL_ClearDTR(PVOID   pHead) // @parm PVOID returned by HWinit.
  714. {
  715. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  716. RETAILMSG(DEBUGMODE, (TEXT("+SL_ClearDTR, 0x%Xrn"), pHead));
  717. RETAILMSG(DEBUGMODE, (TEXT("UseIrDA, %drn"), pHWHead->UseIrDA));
  718. EnterCriticalSection(&(pHWHead->RegCritSec));
  719. try
  720. {
  721. // Low active pin.
  722. if ( !pHWHead->UseIrDA )
  723. *(pHWHead->rDTRport) |= (1<<(pHWHead->DtrPortNum));
  724. }
  725. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  726. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  727. {
  728. // Just exit
  729. }
  730. LeaveCriticalSection(&(pHWHead->RegCritSec));
  731. RETAILMSG(DEBUGMODE, (TEXT("-SL_ClearDTR, 0x%Xrn"), pHead));
  732. }
  733. //
  734. // @doc OEM
  735. // @func VOID | SL_SetDTR | This routine sets DTR.
  736. // 
  737. // @rdesc None.
  738. //
  739. VOID
  740. SL_SetDTR(PVOID   pHead) // @parm PVOID returned by HWinit.
  741. {    
  742. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  743. RETAILMSG(DEBUGMODE, (TEXT("+SL_SetDTR, 0x%Xrn"), pHead));
  744. EnterCriticalSection(&(pHWHead->RegCritSec));
  745. try
  746. {
  747. // Low active
  748. if ( !pHWHead->UseIrDA )
  749. *(pHWHead->rDTRport) &= ~(1<<(pHWHead->DtrPortNum));
  750. }
  751. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  752. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  753. {
  754. // Just exit
  755. }
  756. LeaveCriticalSection(&(pHWHead->RegCritSec));
  757. RETAILMSG(DEBUGMODE, (TEXT("-SL_SetDTR, 0x%Xrn"), pHead));
  758. }
  759. //
  760. // @doc OEM
  761. // @func VOID | SL_ClearRTS | This routine clears RTS.
  762. // 
  763. // @rdesc None.
  764. // 
  765. VOID
  766. SL_ClearRTS(PVOID   pHead) // @parm PVOID returned by HWinit.
  767. {
  768. #if 0 // by shin
  769. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  770. RETAILMSG(0, (TEXT("+SL_ClearRTS, 0x%Xrn"), pHead));
  771. EnterCriticalSection(&(pHWHead->RegCritSec));
  772. try
  773. {
  774. CLEARREG(pHWHead, rUMCON, SER2440_RTS);
  775. }
  776. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  777. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  778. {
  779. // Just exit
  780. }
  781. LeaveCriticalSection(&(pHWHead->RegCritSec));
  782. RETAILMSG(DEBUGMODE, (TEXT("-SL_ClearRTS, 0x%Xrn"), pHead));
  783. #else
  784. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  785. RETAILMSG(DEBUGMODE, (TEXT("+SL_ClearRTS, 0x%Xrn"), pHead));
  786. if ( !pHWHead->UseIrDA )
  787. {
  788. #if USE_AFC
  789. // by 0212.
  790. *(pHWHead->rRTSport) |= (1<<(pHWHead->RtsPortNum));
  791. #else
  792. EnterCriticalSection(&(pHWHead->RegCritSec));
  793. try
  794. {
  795. CLEARREG(pHWHead, rUMCON, SER2440_RTS);
  796. }
  797. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  798. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  799. {
  800. // Just exit
  801. }
  802. LeaveCriticalSection(&(pHWHead->RegCritSec));
  803. #endif
  804. }
  805. RETAILMSG(DEBUGMODE, (TEXT("-SL_ClearRTS, 0x%Xrn"), pHead));
  806. #endif
  807. }
  808. //
  809. // @doc OEM
  810. // @func VOID | SL_SetRTS | This routine sets RTS.
  811. // 
  812. // @rdesc None.
  813. //
  814. VOID
  815. SL_SetRTS(PVOID   pHead) // @parm PVOID returned by HWinit.
  816. {
  817. #if 0
  818. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  819. RETAILMSG(0, (TEXT("+SL_SetRTS, 0x%Xrn"), pHead));
  820. EnterCriticalSection(&(pHWHead->RegCritSec));
  821. try
  822. {
  823. SETREG(pHWHead, rUMCON, SER2440_RTS);
  824. }
  825. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  826. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  827. {
  828. // Just exit
  829. }
  830. LeaveCriticalSection(&(pHWHead->RegCritSec));
  831. RETAILMSG(DEBUGMODE, (TEXT("-SL_SetRTS, 0x%Xrn"), pHead));
  832. #else
  833. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  834. RETAILMSG(DEBUGMODE, (TEXT("+SL_SetRTS, 0x%Xrn"), pHead));
  835. if ( !pHWHead->UseIrDA )
  836. {
  837. #if USE_AFC
  838. // by .0212.
  839. *(pHWHead->rRTSport) &= ~(1<<(pHWHead->RtsPortNum));
  840. #else
  841. EnterCriticalSection(&(pHWHead->RegCritSec));
  842. try
  843. {
  844. SETREG(pHWHead, rUMCON, SER2440_RTS);
  845. }
  846. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  847. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  848. {
  849. // Just exit
  850. }
  851. LeaveCriticalSection(&(pHWHead->RegCritSec));
  852. #endif
  853. }
  854. RETAILMSG(DEBUGMODE, (TEXT("-SL_SetRTS, 0x%Xrn"), pHead));
  855. #endif
  856. }
  857. //
  858. // @doc OEM
  859. // @func VOID | SL_ClearBreak | This routine clears break.
  860. // 
  861. // @rdesc None.
  862. // 
  863. VOID
  864. SL_ClearBreak(PVOID   pHead) // @parm PVOID returned by HWinit.
  865. {
  866. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  867. RETAILMSG(DEBUGMODE,  (TEXT("SL_ClearBreak:rn"))); 
  868. // S2440 does not need to clear break signal, for cleared by automatic.
  869. }
  870. //
  871. // @doc OEM
  872. // @func VOID | SL_SetBreak | This routine sets break.
  873. // 
  874. // @rdesc None.
  875. //
  876. VOID
  877. SL_SetBreak(PVOID   pHead) // @parm PVOID returned by HWinit.
  878. {
  879. PS2440_UART_INFO    pHWHead = (PS2440_UART_INFO)pHead;
  880. RETAILMSG(DEBUGMODE, (TEXT("+SL_SetBreak, 0x%Xrn"), pHead));
  881. EnterCriticalSection(&(pHWHead->RegCritSec));
  882. try
  883. {
  884. SETREG(pHWHead,rUCON,BS_SEND);
  885. }
  886. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  887. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  888. {
  889. // Just exit
  890. }
  891. LeaveCriticalSection(&(pHWHead->RegCritSec));
  892. RETAILMSG(DEBUGMODE, (TEXT("-SL_SetBreak, 0x%Xrn"), pHead));
  893. }
  894. //
  895. // SetBaudRate
  896. //
  897. // Internal function.  The only real reason for splitting this out
  898. // is so that we can call it from PowerOn and still allow SL_SetBaud
  899. // to do debug messages, acquire critical sections, etc.
  900. //
  901. BOOL
  902. SetBaudRate(PVOID   pHead, ULONG   BaudRate)
  903. {
  904. PS2440_UART_INFO    pHWHead = (PS2440_UART_INFO)pHead;
  905. ClearPendingInts( pHWHead );
  906. RETAILMSG(1, (TEXT("SetBaudRate -> %drn"), BaudRate));
  907. if ( (pHWHead->s2440SerReg->rUCON & CS_MASK) == CS_PCLK )
  908. {
  909. // if ( BaudRate == 115200 || BaudRate == 38400 )
  910. // OUTREG(pHWHead,rUBRDIV,( (int)(S2440PCLK/16.0/BaudRate)));
  911. // else
  912. OUTREG(pHWHead,rUBRDIV,( (int)(S2440PCLK/16.0/BaudRate) -1 ));
  913. }
  914. else // if  ( (pHWHead2->s2440SerReg->rUCON & CS_MASK) == CS_UCLK )
  915. OUTREG(pHWHead,rUBRDIV,( (int)(S2440UCLK/16.0/BaudRate) -1 ));
  916. return( TRUE );
  917. }
  918. //
  919. // @doc OEM
  920. // @func BOOL | SL_SetBaudRate |
  921. //  This routine sets the baud rate of the device.
  922. //
  923. // @rdesc None.
  924. //
  925. BOOL
  926. SL_SetBaudRate(
  927.               PVOID   pHead,    // @parm     PVOID returned by HWInit
  928.               ULONG   BaudRate    // @parm     ULONG representing decimal baud rate.
  929.               )
  930. {
  931. BOOL fRet;
  932. PS2440_UART_INFO    pHWHead = (PS2440_UART_INFO)pHead;
  933. RETAILMSG (DEBUGMODE, (TEXT("+SL_SetbaudRate 0x%X, %drn"), pHead, BaudRate));
  934. try
  935. {
  936. // Enter critical section before calling function, since
  937. // we can't make sys calls inside SetBaudRate
  938. EnterCriticalSection(&(pHWHead->RegCritSec));
  939. fRet = SetBaudRate(pHead, BaudRate);
  940. LeaveCriticalSection(&(pHWHead->RegCritSec));
  941. }
  942. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  943. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  944. {
  945. return( FALSE );
  946. }
  947. if ( fRet )
  948. {
  949. pHWHead->dcb.BaudRate = BaudRate;
  950. RETAILMSG(DEBUGMODE, (TEXT("-SL_SetbaudRate 0x%X (%d Baud)rn"), pHead, BaudRate));
  951. return( TRUE );
  952. }
  953. else
  954. {
  955. RETAILMSG(DEBUGMODE, (TEXT("-SL_SetbaudRate - Error setting %d, failing to %drn"), BaudRate, pHWHead->dcb.BaudRate));
  956. return( FALSE );
  957. }
  958. }
  959. //
  960. // @doc OEM
  961. // @func BOOL | SL_SetByteSize |
  962. //  This routine sets the WordSize of the device.
  963. //
  964. // @rdesc None.
  965. //
  966. BOOL
  967. SL_SetByteSize(
  968.               PVOID   pHead,        // @parm     PVOID returned by HWInit
  969.               ULONG   ByteSize    // @parm     ULONG ByteSize field from DCB.
  970.               )
  971. {
  972. PS2440_UART_INFO    pHWHead = (PS2440_UART_INFO)pHead;
  973. UINT32 lcr;
  974. BOOL bRet;
  975. RETAILMSG(DEBUGMODE,(TEXT("+SL_SetByteSize 0x%X, 0x%Xrn"), pHead, ByteSize));
  976. bRet = TRUE;
  977. EnterCriticalSection(&(pHWHead->RegCritSec));
  978. try {      
  979. lcr = (UINT32)INREG(pHWHead,rULCON);
  980. lcr &= ~SER2440_DATABIT_MASK;
  981. switch ( ByteSize )
  982. {
  983. case 5:
  984. lcr |= 0;//SERIAL_5_DATA;
  985. break;
  986. case 6:
  987. lcr |= 1;//SERIAL_6_DATA;
  988. break;
  989. case 7:
  990. lcr |= 2;//SERIAL_7_DATA;
  991. break;
  992. case 8:
  993. lcr |= 3;//SERIAL_8_DATA;
  994. break;
  995. default:
  996. bRet = FALSE;
  997. break;
  998. }
  999. if (bRet)
  1000. {
  1001. OUTREG(pHWHead,rULCON,lcr); 
  1002. }
  1003. }
  1004. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  1005. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  1006. {
  1007. bRet = FALSE;
  1008. }
  1009. LeaveCriticalSection(&(pHWHead->RegCritSec));
  1010. RETAILMSG(DEBUGMODE,(TEXT("-SL_SetByteSize 0x%Xrn"), pHead));
  1011. return(bRet);
  1012. }
  1013. //
  1014. // @doc OEM
  1015. // @func BOOL | SL_SetParity |
  1016. //  This routine sets the parity of the device.
  1017. //
  1018. // @rdesc None.
  1019. //
  1020. BOOL
  1021. SL_SetParity(
  1022.             PVOID   pHead,    // @parm     PVOID returned by HWInit
  1023.             ULONG   Parity    // @parm     ULONG parity field from DCB.
  1024.             )
  1025. {
  1026. PS2440_UART_INFO    pHWHead = (PS2440_UART_INFO)pHead;
  1027. UINT32 lcr;
  1028. BOOL bRet;
  1029. RETAILMSG(DEBUGMODE,(TEXT("+SL_SetParity 0x%X, 0x%Xrn"), pHead, Parity));
  1030. bRet = TRUE;
  1031. EnterCriticalSection(&(pHWHead->RegCritSec));
  1032. try
  1033. {
  1034. lcr = (UINT32)INREG(pHWHead,rULCON);      
  1035. lcr &= ~SER2440_PARITY_MASK;
  1036. switch ( Parity )
  1037. {
  1038. case ODDPARITY:
  1039. lcr |= 0x20;//SERIAL_ODD_PARITY;
  1040. break;
  1041. case EVENPARITY:
  1042. lcr |= 0x28;//SERIAL_EVEN_PARITY;
  1043. break;
  1044. case MARKPARITY:
  1045. lcr |= 0x30;//SERIAL_MARK_PARITY;
  1046. break;
  1047. case SPACEPARITY:
  1048. lcr |= 0x38;//SERIAL_SPACE_PARITY;
  1049. break;
  1050. case NOPARITY:
  1051. lcr |= 0;//SERIAL_NONE_PARITY;
  1052. break;
  1053. default:
  1054. bRet = FALSE;
  1055. break;
  1056. }
  1057. if (bRet)
  1058. {
  1059. OUTREG(pHWHead,rULCON,lcr) ;
  1060. }
  1061. }
  1062. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  1063. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  1064. {
  1065. bRet = FALSE;
  1066. }
  1067. LeaveCriticalSection(&(pHWHead->RegCritSec));
  1068. RETAILMSG(DEBUGMODE, (TEXT("-SL_SetParity 0x%Xrn"), pHead));
  1069. return(bRet);
  1070. }
  1071. //
  1072. // @doc OEM
  1073. // @func VOID | SL_SetStopBits |
  1074. //  This routine sets the Stop Bits for the device.
  1075. //
  1076. // @rdesc None.
  1077. //
  1078. BOOL
  1079. SL_SetStopBits(
  1080.               PVOID   pHead,      // @parm     PVOID returned by HWInit
  1081.               ULONG   StopBits  // @parm     ULONG StopBits field from DCB.
  1082.               )
  1083. {
  1084. PS2440_UART_INFO    pHWHead = (PS2440_UART_INFO)pHead;
  1085. UINT32 lcr;
  1086. BOOL bRet;
  1087. RETAILMSG (DEBUGMODE,(TEXT("+SL_SetStopBits 0x%X, 0x%Xrn"), pHead, StopBits));
  1088. bRet = TRUE;
  1089. EnterCriticalSection(&(pHWHead->RegCritSec));
  1090. try
  1091. {
  1092. lcr = INREG(pHWHead,rULCON);
  1093. lcr &= ~SER2440_STOPBIT_MASK;
  1094. // Note that 1.5 stop bits only works if the word size
  1095. // is 5 bits.  Any other xmit word size will cause the
  1096. // 1.5 stop bit setting to generate 2 stop bits.        
  1097. switch ( StopBits )
  1098. {
  1099. case ONESTOPBIT :
  1100. lcr |= 0;//SERIAL_1_STOP ;
  1101. break;
  1102. case ONE5STOPBITS :
  1103. //lcr |= SERIAL_1_5_STOP ;
  1104. //break;
  1105. case TWOSTOPBITS :
  1106. lcr |= 4;//SERIAL_2_STOP ;
  1107. break;
  1108. default:
  1109. bRet = FALSE;
  1110. break;
  1111. }
  1112. if (bRet)
  1113. {
  1114. OUTREG(pHWHead,rULCON,lcr);
  1115. }
  1116. }
  1117. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  1118. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  1119. {
  1120. bRet = FALSE;
  1121. }
  1122. LeaveCriticalSection(&(pHWHead->RegCritSec));
  1123. RETAILMSG(DEBUGMODE,(TEXT("-SL_SetStopBits 0x%Xrn"), pHead));
  1124. return(bRet);
  1125. }
  1126. //
  1127. // @doc OEM
  1128. // @func ULONG | SL_GetRxBufferSize | This function returns
  1129. // the size of the hardware buffer passed to the interrupt
  1130. // initialize function.  It would be used only for devices
  1131. // which share a buffer between the MDD/PDD and an ISR.
  1132. //
  1133. // 
  1134. // @rdesc This routine always returns 0 for 16550 UARTS.
  1135. // 
  1136. ULONG
  1137. SL_GetRxBufferSize(PVOID pHead)
  1138. {
  1139. RETAILMSG(DEBUGMODE, (TEXT("SL_GetRxBufferSize rn")));
  1140. return(0);
  1141. }
  1142. //
  1143. // @doc OEM
  1144. // @func PVOID | SC_GetRxStart | This routine returns the start of the hardware
  1145. // receive buffer.  See SL_GetRxBufferSize.
  1146. // 
  1147. // @rdesc The return value is a pointer to the start of the device receive buffer.
  1148. // 
  1149. PVOID
  1150. SL_GetRxStart(PVOID   pHead) // @parm PVOID returned by SC_init.
  1151. {
  1152. RETAILMSG(DEBUGMODE, (TEXT("SL_GetRxStart rn")));
  1153. return(NULL);
  1154. }
  1155. //
  1156. // @doc OEM
  1157. // @func ULONG | SL_GetInterruptType | This function is called
  1158. //   by the MDD whenever an interrupt occurs.  The return code
  1159. //   is then checked by the MDD to determine which of the four
  1160. //   interrupt handling routines are to be called.
  1161. // 
  1162. // @rdesc This routine returns a bitmask indicating which interrupts
  1163. //   are currently pending.
  1164. // 
  1165. INTERRUPT_TYPE
  1166. SL_GetInterruptType(PVOID pHead) // Pointer to hardware head
  1167. {
  1168. PS2440_UART_INFO    pHWHead = (PS2440_UART_INFO)pHead;
  1169. INTERRUPT_TYPE interrupts;
  1170. ULONG IntPndVal=0;
  1171. ULONG IntSubPndVal=0;
  1172. try
  1173. {
  1174. IntPndVal = *(pHWHead->UART_INTSRCPND);
  1175. IntSubPndVal = *(pHWHead->UART_INTSUBSRCPND);
  1176. }
  1177. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  1178. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  1179. {
  1180. RETAILMSG(DEBUGMODE, (TEXT("ACCESS VIOLATION ERROR rn")));
  1181. IntPndVal = SER2440_INT_INVALID; // simulate no interrupt
  1182. }
  1183. RETAILMSG(DEBUGMODE, (TEXT("SL_GetInterruptType : 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%Xrn"),
  1184. *(pHWHead->UART_INTMASK),
  1185. *(pHWHead->UART_INTSUBMASK),
  1186. *(pHWHead->UART_INTSRCPND),
  1187. *(pHWHead->UART_INTSUBSRCPND),
  1188. ~(*(pHWHead->UART_INTSUBMASK)) & *(pHWHead->UART_INTSUBSRCPND),
  1189. pHWHead->fSW_EnTxINT));
  1190. if ( IntPndVal & (pHWHead->bINT) )
  1191. {
  1192. if ( IntSubPndVal == SER2440_INT_INVALID )
  1193. {      
  1194. RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: SER2440_INT_INVALIDrn")));
  1195. interrupts = INTR_NONE;
  1196. }
  1197. else if(IntSubPndVal & (pHWHead->bErrINT) )
  1198. {
  1199. RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_LINErn")));
  1200. interrupts = INTR_LINE;  // Error status
  1201. }
  1202. else if((IntSubPndVal & (pHWHead->bTxINT)) && pHWHead->fSW_EnTxINT )
  1203. {
  1204. RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_TXrn")));
  1205. interrupts = INTR_TX;
  1206. }
  1207. else if(IntSubPndVal & (pHWHead->bRxINT) )
  1208. {
  1209. RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_RXrn")));
  1210. interrupts = INTR_RX;    // Received valid data.
  1211. }
  1212. else 
  1213. {
  1214. interrupts = INTR_NONE;  // No interrupts pending, vector is useless
  1215. ClearINTPnd(pHWHead, pHWHead->bINT);
  1216. }
  1217. }
  1218. else
  1219. {
  1220. RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_NONE(pHWHead->bINT)rn")));
  1221. interrupts = INTR_NONE;  // No interrupts pending, vector is useless
  1222. }
  1223. return(interrupts);
  1224. }
  1225. // @doc OEM
  1226. // @func ULONG | SL_RxIntr | This routine gets several characters from the hardware
  1227. //   receive buffer and puts them in a buffer provided via the second argument.
  1228. //   It returns the number of bytes lost to overrun.
  1229. // 
  1230. // @rdesc The return value indicates the number of overruns detected.
  1231. //   The actual number of dropped characters may be higher.
  1232. //
  1233. ULONG
  1234. SL_RxIntr(
  1235.          PVOID pHead,                // @parm Pointer to hardware head
  1236.          PUCHAR pRxBuffer,           // @parm Pointer to receive buffer
  1237.          ULONG *pBufflen             // @parm In = max bytes to read, out = bytes read
  1238.          )
  1239. {
  1240. PS2440_UART_INFO   pHWHead    = (PS2440_UART_INFO)pHead;
  1241. ULONG RetVal               = 0;
  1242. ULONG TargetRoom           = *pBufflen;
  1243. UCHAR cEvtChar, cRXChar;
  1244. ULONG rFifoStat, RxFifoCnt, RxDataReady, nRxIntSrc;
  1245. BOOL fRXFlag              = FALSE;
  1246. BOOL fReplaceparityErrors = FALSE;
  1247. BOOL fNull;
  1248. *pBufflen = 0;
  1249. nRxIntSrc = pHWHead->bRxINT;
  1250. RETAILMSG(DEBUGMODE, (TEXT("SL_RxIntr rn")));
  1251. // LAM - I have local copies of some DCB elements since I don't
  1252. // want to keep dereferencing inside my read loop and there are too
  1253. // many of them to trust the compiler.
  1254. cEvtChar = pHWHead->dcb.EvtChar;
  1255. fNull = pHWHead->dcb.fNull;
  1256. if ( pHWHead->dcb.fErrorChar && pHWHead->dcb.fParity )
  1257. fReplaceparityErrors = TRUE;
  1258. try
  1259. {
  1260. // S2440 UART Rx strategy is different from SER16550..
  1261. rFifoStat = INREG(pHWHead,rUFSTAT);
  1262. RxFifoCnt = rFifoStat & 0x3f;
  1263. if((rFifoStat & (1<<6))||(RxFifoCnt > 0))
  1264. RxDataReady = 1;
  1265. else
  1266. RxDataReady = 0;
  1267. while ( TargetRoom && RxDataReady)
  1268. {
  1269. // If the line is unstable, we may check the error status...
  1270. // But now, I ignore it....
  1271. // ReadLSR( pHWHead );
  1272. // Read the byte
  1273. cRXChar = *(pHWHead->pUFRXH);
  1274. RETAILMSG(DEBUGMODE, (TEXT("SL_RxIntr : cRXChar = 0x%x rn"), cRXChar));
  1275. // But we may want to discard it
  1276. if ( pHWHead->dcb.fDsrSensitivity &&
  1277. (! (pHWHead->vUMSTAT & COM2440_MSR_DSR)) )
  1278. {
  1279. // Do nothing - byte gets discarded
  1280. RETAILMSG (1, (TEXT("Dropping byte because DSR is lowrn")));
  1281. }
  1282. else if (!cRXChar && fNull)
  1283. {
  1284. // Do nothing - byte gets discarded
  1285. RETAILMSG (1, (TEXT("Dropping NULL byte due to fNullrn")));
  1286. }
  1287. else
  1288. {
  1289. // Do character replacement if parity error detected.
  1290. // See if we need to generate an EV_RXFLAG for the received char.
  1291. if ( cRXChar == cEvtChar )
  1292. fRXFlag = TRUE;
  1293.  
  1294. // Finally, we can get byte, update status and save.
  1295. if (!pHWHead->RxDiscard )
  1296. {
  1297. *pRxBuffer++ = cRXChar;
  1298. (*pBufflen)++;
  1299. }
  1300. else
  1301. {
  1302. RETAILMSG (1,(TEXT("SL_RXIntr : Dropping byte because now Txingrn")));
  1303. }
  1304. --TargetRoom;
  1305. rFifoStat = INREG(pHWHead,rUFSTAT);
  1306. RxFifoCnt = rFifoStat & 0x3f;
  1307. if((rFifoStat & (1<<6))||(RxFifoCnt > 0))
  1308. RxDataReady = 1;
  1309. else
  1310. RxDataReady = 0;
  1311. }
  1312. }
  1313. //Clear interrupt pending bit
  1314. ClearSubINTPnd(pHWHead, nRxIntSrc);
  1315. if ( *(pHWHead->UART_INTSUBSRCPND) & ( pHWHead->bRxINT | pHWHead->bErrINT ) )
  1316. {
  1317. RETAILMSG (DEBUGMODE, (TEXT("*(pHWHead->UART_INTSUBSRCPND) = %x rn"), *(pHWHead->UART_INTSUBSRCPND)));
  1318. RETAILMSG (DEBUGMODE, (TEXT("Do Not Clear bINT rn")));
  1319. }
  1320. else
  1321. {
  1322. ClearINTPnd(pHWHead, pHWHead->bINT);
  1323. }
  1324. EnINT(pHWHead, pHWHead->bINT);
  1325. EnSubINT(pHWHead, nRxIntSrc);
  1326. if ( !pHWHead->UseIrDA )
  1327. {
  1328. #if USE_AFC
  1329. // Assert nRTS
  1330. *(pHWHead->rRTSport) &= ~(1<<(pHWHead->RtsPortNum));
  1331. #endif
  1332. }
  1333. }
  1334. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  1335. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  1336. {
  1337. // just exit
  1338. }
  1339. // if we saw one (or more) EVT chars, then generate an event
  1340. if ( fRXFlag )
  1341. pHWHead->EventCallback( pHWHead->pMddHead, EV_RXFLAG );
  1342. if ( pHWHead->DroppedBytes )
  1343. {
  1344. RETAILMSG (DEBUGMODE, (TEXT("Rx drop %d.rn"), pHWHead->DroppedBytes));
  1345. }
  1346.     
  1347. RetVal = pHWHead->DroppedBytes;
  1348. pHWHead->DroppedBytes = 0;
  1349. return(RetVal);
  1350. }
  1351. // @doc OEM
  1352. // @func ULONG | SL_PutBytes | This routine is called from the MDD
  1353. //   in order to write a stream of data to the device. (Obselete)
  1354. // 
  1355. // @rdesc Always returns 0
  1356. //
  1357. ULONG
  1358. SL_PutBytes(
  1359.            PVOID   pHead,        // @parm    PVOID returned by HWInit.
  1360.            PUCHAR  pSrc,        // @parm    Pointer to bytes to be sent.
  1361.            ULONG   NumberOfBytes,  // @parm    Number of bytes to be sent.
  1362.            PULONG  pBytesSent        // @parm    Pointer to actual number of bytes put.
  1363.            )
  1364. {
  1365. PS2440_UART_INFO   pHWHead    = (PS2440_UART_INFO)pHead;
  1366. RETAILMSG(1,(TEXT("This routine is called by old MDDrn")));
  1367. return(0);
  1368. }
  1369. //
  1370. // @doc OEM
  1371. // @func ULONG | SL_TXIntr | This routine is called from the old MDD
  1372. //   whenever INTR_TX is returned by SL_GetInterruptType (Obselete)
  1373. // 
  1374. // @rdesc None
  1375. //
  1376. VOID
  1377. SL_TxIntr(PVOID pHead) // Hardware Head
  1378. {
  1379.     PS2440_UART_INFO   pHWHead    = (PS2440_UART_INFO)pHead;
  1380.     RETAILMSG(1, (TEXT("SL_TxIntr(From old MDD)n")));
  1381. }
  1382. //
  1383. // @doc OEM
  1384. // @func ULONG | SL_TXIntrEx | This routine is called from the new MDD
  1385. //   whenever INTR_TX is returned by SL_GetInterruptType
  1386. // 
  1387. // @rdesc None
  1388. //
  1389. VOID
  1390. SL_TxIntrEx(
  1391.            PVOID pHead,                // Hardware Head
  1392.            PUCHAR pTxBuffer,          // @parm Pointer to receive buffer
  1393.            ULONG *pBufflen            // @parm In = max bytes to transmit, out = bytes transmitted
  1394.            )
  1395. {
  1396. PS2440_UART_INFO   pHWHead    = (PS2440_UART_INFO)pHead;
  1397. UCHAR byteCount;
  1398. ULONG NumberOfBytes = *pBufflen;
  1399. ULONG rFifoStat, TxFifoCnt;
  1400. unsigned int FifoModeReg;
  1401.    
  1402. RETAILMSG(DEBUGMODE, (TEXT("SL_TxIntrEx rn")));
  1403. // We may be done sending.  If so, just disable the TX interrupts and return to the MDD.  
  1404. if( ! *pBufflen )
  1405. {
  1406. DisEnINT(pHWHead, pHWHead->bINT);
  1407. DisEnSubINT(pHWHead, pHWHead->bTxINT);
  1408. pHWHead->fSW_EnTxINT = FALSE;
  1409. ClearINTPnd(pHWHead, pHWHead->bINT);
  1410. return;
  1411. }
  1412.     
  1413. *pBufflen = 0;  // In case we don't send anything below.
  1414. // Disable xmit intr.  Most 16550s will keep hammering
  1415. // us with xmit interrupts if we don't turn them off
  1416. // Whoever gets the FlushDone will then need to turn
  1417. // TX Ints back on if needed.
  1418. EnterCriticalSection(&(pHWHead->RegCritSec));
  1419. try
  1420. {
  1421. // Need to signal FlushDone for XmitComChar
  1422. PulseEvent(pHWHead->FlushDone);
  1423. pHWHead->CommErrors &= ~CE_TXFULL;
  1424. #if 0
  1425.         // If CTS flow control is desired, check cts. If clear, don't send,
  1426.         // but loop.  When CTS comes back on, the OtherInt routine will
  1427.         // detect this and re-enable TX interrupts (causing Flushdone).
  1428.         // For finest granularity, we would check this in the loop below,
  1429.         // but for speed, I check it here (up to 8 xmit characters before
  1430.         // we actually flow off.
  1431.         if ( pHWHead->dcb.fOutxCtsFlow )
  1432. {
  1433.             // ReadMSR( pHWHead );
  1434.             // We don't need to explicitly read the MSR, since we always enable
  1435.             // IER_MS, which ensures that we will get an interrupt and read
  1436.             // the MSR whenever CTS, DSR, TERI, or DCD change.
  1437.             if (! (pHWHead->MSR & SERIAL_MSR_CTS) )
  1438. {
  1439.                 unsigned char byte;
  1440.                 RETAILMSG (DEBUGMODE, (TEXT("SL_TxIntrEx, flowed off via CTSn") ) );
  1441.                 pHWHead->CTSFlowOff = TRUE;  // Record flowed off state
  1442.                 // We could return a positive value here, which would
  1443.                 // cause the MDD to periodically check the flow control
  1444.                 // status.  However, we don't need to since we know that
  1445.                 // the DCTS interrupt will cause the MDD to call us, and we
  1446.                 // will subsequently fake a TX interrupt to the MDD, causing
  1447.                 // him to call back into PutBytes.
  1448. DisEnINT(pHWHead, pHWHead->bINT);
  1449. DisEnSubINT(pHWHead, pHWHead->bTxINT);
  1450. pHWHead->fSW_EnTxINT = FALSE;
  1451. ClearINTPnd(pHWHead, pHWHead->bINT);
  1452.                 LeaveCriticalSection(&(pHWHead->RegCritSec));
  1453.                 return;
  1454.             }
  1455. }
  1456. #endif
  1457. }
  1458. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  1459. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  1460. {
  1461. // Do nothing.  The worst case is that this was a fluke,
  1462. // and a TX Intr will come right back at us and we will
  1463. // resume transmission.
  1464. }
  1465. LeaveCriticalSection(&(pHWHead->RegCritSec));
  1466. //  OK, now lets actually transmit some data.
  1467. EnterCriticalSection(&(pHWHead->TransmitCritSec));
  1468. EnterCriticalSection(&(pHWHead->RegCritSec));
  1469. FifoModeReg = INREG(pHWHead, rUFCON);
  1470. try
  1471. {
  1472. rFifoStat = INREG(pHWHead,rUFSTAT);
  1473. TxFifoCnt = ((rFifoStat & SER2440_FIFOCNT_MASK_TX) >> 8);
  1474. if (pHWHead->UseIrDA)
  1475. {
  1476. // IR is half-duplex.
  1477. pHWHead->RxDiscard = TRUE;
  1478. DisEnSubINT(pHWHead, pHWHead->bRxINT);
  1479. }
  1480. if (!(rFifoStat & SER2440_FIFOFULL_TX) && (TxFifoCnt <= (SER2440_FIFO_DEPTH_TX-1)))
  1481. {
  1482. byteCount = (unsigned char)(SER2440_FIFO_DEPTH_TX-TxFifoCnt);
  1483. RETAILMSG(DEBUGMODE, (TEXT("SL_TxIntrEx : %d rn"), NumberOfBytes));
  1484. for ( *pBufflen=0; NumberOfBytes && byteCount; NumberOfBytes--, byteCount-- )
  1485. {
  1486. unsigned int i, tmpreg;
  1487. *(pHWHead->pUFTXH) = *pTxBuffer;
  1488. RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt - *pTxBuffer = 0x%x rn"), *pTxBuffer));
  1489. if (FifoModeReg&0x1) // FIFO Mode enabled.
  1490. {
  1491. for ( i = 0; i < 600000; i++ )
  1492. {
  1493. tmpreg = INREG(pHWHead, rUFSTAT);
  1494. //tmpreg & (1<<14) == 1  ->  Fifo full -> waiting...
  1495. //tmpreg & 0x3f00 == 0 -> There is no data to send -> break loop.
  1496. if ( (tmpreg & (1<<14)) == (1<<14) )
  1497. {
  1498. continue;
  1499. }
  1500. else break;
  1501. }
  1502. if ( i == 600000 ) // Time Out Error
  1503. {
  1504. RETAILMSG (1, (TEXT("SL_TxInt : Error : i = %d rn"), i));
  1505. }
  1506. }
  1507. else // FIFO Mode disabled.
  1508. {
  1509. for ( i = 0; i < 600000; i++ )
  1510. {
  1511. tmpreg = INREG(pHWHead, rUTRSTAT);
  1512. if ( tmpreg & 0x2 ) break;
  1513. }
  1514. if ( i == 600000 )
  1515. {
  1516. RETAILMSG (1, (TEXT("SL_TxInt : Error : i = %d rn"), i));
  1517. }
  1518. }
  1519. ++pTxBuffer;
  1520. (*pBufflen)++;
  1521. //irda test...
  1522. //RETAILMSG (1,(TEXT("T ")));
  1523. }
  1524. if (pHWHead->UseIrDA )
  1525. {
  1526. if (FifoModeReg&0x1) // FIFO Mode enabled.
  1527. {
  1528. unsigned int cnt = 0;
  1529. for ( ;; )
  1530. {
  1531. unsigned int tmpreg;
  1532. tmpreg = INREG(pHWHead, rUFSTAT);
  1533. if ( (tmpreg & 0x3f00) == 0) break; // waitint to empty the tx buffer empty...
  1534. if ( cnt++ > 600000 )
  1535. {
  1536. RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt : Reset TX FIFO :  tmpreg = %x rn"), tmpreg));
  1537. SETREG(pHWHead,rUFCON,0x4);    // tx, rx fifo reset
  1538. break;
  1539. }
  1540. }
  1541. RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt : Exit for loop rn")));
  1542. }
  1543. }
  1544. }
  1545. else
  1546. {
  1547. RETAILMSG (1, (TEXT("SL_TxIntrEx: Not Send - rFifoStat[0x%x] TxFifoCnt[0x%x]rn"),
  1548. rFifoStat, TxFifoCnt));
  1549. }
  1550. if (pHWHead->UseIrDA )
  1551. {
  1552. // IR is half-duplex.
  1553. ClearPendingInts( pHWHead );
  1554. EnSubINT(pHWHead, pHWHead->bRxINT);
  1555. pHWHead->RxDiscard = FALSE;
  1556. }
  1557. // Enable xmit intr. We need to do this no matter what, 
  1558. // since the MDD relies on one final interrupt before
  1559. // returning to the application. 
  1560. // ClearPendingInts( pHWHead );
  1561. // Clear TX interrupt pending bit.
  1562. ClearSubINTPnd(pHWHead, pHWHead->bTxINT);
  1563. if ( !(GetSubINTStatus(pHWHead) & pHWHead->bRxINT) )  ClearINTPnd(pHWHead, pHWHead->bINT);
  1564. EnINT(pHWHead, pHWHead->bINT);
  1565. EnSubINT(pHWHead, pHWHead->bTxINT);
  1566. pHWHead->fSW_EnTxINT = TRUE;  // FALSE;
  1567. }
  1568. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  1569. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  1570. {
  1571. // Hmm, not sure what would cause this.  Lets just tell
  1572. // the MDD to go away until we get another TX
  1573. // interrupt.
  1574. }
  1575. LeaveCriticalSection(&(pHWHead->RegCritSec));
  1576. LeaveCriticalSection(&(pHWHead->TransmitCritSec));
  1577. return;
  1578. }
  1579. //
  1580. // @doc OEM
  1581. // @func ULONG | SL_LineIntr | This routine is called from the MDD
  1582. //   whenever INTR_LINE is returned by SL_GetInterruptType.
  1583. // 
  1584. // @rdesc None
  1585. //
  1586. VOID
  1587. SL_LineIntr(PVOID pHead) // Hardware Head
  1588. {
  1589. PS2440_UART_INFO   pHWHead    = (PS2440_UART_INFO)pHead;
  1590. RETAILMSG(DEBUGMODE,(TEXT("INTR_LINE rn")));
  1591. SL_ModemIntr( pHWHead );
  1592. ReadLSR( pHWHead );
  1593. ClearSubINTPnd(pHWHead, pHWHead->bErrINT);
  1594. if ( !(GetSubINTStatus(pHWHead) & pHWHead->bRxINT) ) 
  1595. ClearINTPnd(pHWHead, pHWHead->bINT);
  1596. EnINT(pHWHead, pHWHead->bINT);
  1597. EnSubINT(pHWHead, pHWHead->bErrINT);
  1598. }
  1599. //
  1600. // @doc OEM
  1601. // @func ULONG | SL_OtherIntr | This routine is called from the MDD
  1602. //   whenever INTR_MODEM is returned by SL_GetInterruptType.
  1603. // 
  1604. // @rdesc None
  1605. //
  1606. VOID
  1607. SL_OtherIntr(PVOID pHead) // Hardware Head
  1608. {
  1609.     PS2440_UART_INFO   pHWHead    = (PS2440_UART_INFO)pHead;
  1610.     // S2440 does not have modem interrupt.
  1611.     RETAILMSG(DEBUGMODE,(TEXT("+SL_OtherIntr rn")));
  1612.     ReadMSR( pHWHead );
  1613.     EnterCriticalSection(&(pHWHead->RegCritSec));
  1614.     try
  1615. {
  1616.         // If we are currently flowed off via CTS or DSR, then
  1617.         // we better signal the TX thread when one of them changes
  1618.         // so that TX can resume sending.
  1619.         if ( pHWHead->DSRFlowOff && (pHWHead->vUMSTAT & COM2440_MSR_DSR))
  1620. {
  1621.             RETAILMSG (DEBUGMODE, (TEXT("**********************PutBytes, flowed on via DSRn") ) );
  1622.             pHWHead->DSRFlowOff = FALSE;
  1623.             // DSR is set, so go ahead and resume sending            
  1624.             EnINT(pHWHead, pHWHead->bINT);
  1625.             EnSubINT(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
  1626.             pHWHead->fSW_EnTxINT = TRUE;
  1627.             // Then simulate a TX intr to get things moving
  1628.             pHWHead->AddTXIntr = TRUE;
  1629.         }
  1630.         if ( pHWHead->CTSFlowOff && (pHWHead->vUMSTAT & COM2440_MSR_CTS))
  1631. {
  1632.             RETAILMSG(DEBUGMODE, (TEXT("***********************PutBytes, flowed on via CTSn") ) );
  1633.             pHWHead->CTSFlowOff = FALSE;
  1634.             // CTS is set, so go ahead and resume sending
  1635.             EnINT(pHWHead, pHWHead->bINT);
  1636.             EnSubINT(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
  1637.             pHWHead->fSW_EnTxINT = TRUE;
  1638.             // Then simulate a TX intr to get things moving
  1639.             pHWHead->AddTXIntr = TRUE;
  1640.         }
  1641.         
  1642.     }
  1643.     except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  1644.             EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
  1645.         // Just exit
  1646.     }
  1647.     LeaveCriticalSection(&(pHWHead->RegCritSec));
  1648.     RETAILMSG(DEBUGMODE,(TEXT("-SL_OtherIntr 0x%Xrn"), pHead));
  1649. }
  1650. //
  1651. // @doc OEM
  1652. // @func ULONG | SL_OtherIntr | This routine is called from the MDD
  1653. //   whenever INTR_MODEM is returned by SL_GetInterruptType.
  1654. // 
  1655. // @rdesc None
  1656. //
  1657. VOID
  1658. SL_ModemIntr(PVOID pHead) // Hardware Head
  1659. {
  1660. PS2440_UART_INFO   pHWHead    = (PS2440_UART_INFO)pHead;
  1661. INTERRUPT_TYPE      it = INTR_NONE;
  1662. ULONG               win32status = 0;
  1663. RETAILMSG (1, (TEXT("SL_ModemIntr - pHWHead->OpenCount %d rn"), pHWHead->OpenCount));
  1664. if ( !pHWHead->OpenCount )
  1665. {
  1666. // We want to indicate a cable event.
  1667. RETAILMSG(1, (TEXT("!pHWHead->OpenCount : 0x%Xrn"), pHWHead->OpenCount));
  1668. if ( IsAPIReady(SH_WMGR))
  1669. {
  1670. RETAILMSG(1, (TEXT("IsAPIReady(SH_WMGR) == truern")));
  1671. CeEventHasOccurred (NOTIFICATION_EVENT_RS232_DETECTED,NULL);
  1672. RETAILMSG(1, (TEXT("Indicating RS232 Cable Eventrn")));
  1673. RETAILMSG(1, (TEXT("Event occurred : NOTIFICATION_EVENT_RS232_DETECTEDrn")));
  1674. }
  1675. }
  1676. else
  1677. {
  1678. RETAILMSG(1,(TEXT("+SL_ModemIntr 0x%Xrn"), pHead));
  1679. SL_OtherIntr(pHead);
  1680. }
  1681. }
  1682. //  
  1683. // @doc OEM
  1684. // @func    ULONG | SL_GetStatus | This structure is called by the MDD
  1685. //   to retrieve the contents of a COMSTAT structure.
  1686. //
  1687. // @rdesc    The return is a ULONG, representing success (0) or failure (-1).
  1688. //
  1689. ULONG
  1690. SL_GetStatus(
  1691.             PVOID    pHead,    // @parm PVOID returned by HWInit.
  1692.             LPCOMSTAT    lpStat    // Pointer to LPCOMMSTAT to hold status.
  1693.             )
  1694. {
  1695.     PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
  1696.     ULONG      RetVal  = pHWHead->CommErrors;
  1697. RETAILMSG(1, (TEXT("+SL_GetStatus 0x%Xrn"), pHead));
  1698. pHWHead->CommErrors = 0; // Clear old errors each time
  1699.     if ( lpStat )
  1700. {
  1701. try
  1702. {
  1703.             if (pHWHead->CTSFlowOff)
  1704.                 pHWHead->Status.fCtsHold = 1;
  1705.             else
  1706.                 pHWHead->Status.fCtsHold = 0;
  1707.             if (pHWHead->DSRFlowOff)
  1708.                 pHWHead->Status.fDsrHold = 1;
  1709.             else
  1710.                 pHWHead->Status.fDsrHold = 0;
  1711.             // NOTE - I think what they really want to know here is
  1712.             // the amount of data in the MDD buffer, not the amount
  1713.             // in the UART itself.  Just set to 0 for now since the
  1714.             // MDD doesn't take care of this.
  1715.             pHWHead->Status.cbInQue  = 0;
  1716.             pHWHead->Status.cbOutQue = 0;
  1717.             memcpy(lpStat, &(pHWHead->Status), sizeof(COMSTAT));
  1718.         }
  1719.         except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  1720.                 EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  1721. {
  1722.             RetVal = (ULONG)-1;
  1723.         }        
  1724.     } 
  1725. else
  1726.         RetVal = (ULONG)-1;
  1727.     DEBUGMSG (ZONE_FUNCTION|USERDBG,
  1728.               (TEXT("-SL_GetStatus 0x%Xrn"), pHead));
  1729.     return(RetVal);
  1730. }
  1731. //
  1732. // @doc OEM
  1733. // @func    ULONG | SL_Reset | Perform any operations associated
  1734. //   with a device reset
  1735. //
  1736. // @rdesc    None.
  1737. //
  1738. VOID
  1739. SL_Reset(PVOID   pHead) // @parm PVOID returned by HWInit.
  1740. {
  1741. PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
  1742. RETAILMSG(DEBUGMODE,(TEXT("+SL_Reset 0x%Xrn"), pHead));
  1743. memset(&pHWHead->Status, 0, sizeof(COMSTAT));
  1744. EnterCriticalSection(&(pHWHead->RegCritSec));
  1745. try
  1746. {
  1747. DisEnINT(pHWHead, pHWHead->bINT);
  1748. DisEnSubINT(pHWHead, pHWHead->bTxINT);
  1749. // if ( GetSubINTStatus(pHWHead) )
  1750. pHWHead->fSW_EnTxINT = FALSE;
  1751. pHWHead->RxDiscard = FALSE;
  1752. }
  1753. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  1754. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  1755. {
  1756. // Do nothing
  1757. }
  1758. LeaveCriticalSection(&(pHWHead->RegCritSec));
  1759. DEBUGMSG (ZONE_FUNCTION, (TEXT("-SL_Reset 0x%Xrn"), pHead));
  1760. }
  1761. //
  1762. // @doc OEM
  1763. // @func    VOID | SL_GetModemStatus | Retrieves modem status.
  1764. //
  1765. // @rdesc    None.
  1766. //
  1767. VOID
  1768. SL_GetModemStatus(
  1769.                  PVOID   pHead,        // @parm PVOID returned by HWInit.
  1770.                  PULONG  pModemStatus    // @parm PULONG passed in by user.
  1771.                  )
  1772. {
  1773. PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
  1774. UINT8 ubModemStatus;
  1775. RETAILMSG(DEBUGMODE,  (TEXT("SL_GetModemStatus:rn")));
  1776. ReadMSR( pHWHead );
  1777. ubModemStatus = (unsigned char)pHWHead->vUMSTAT;
  1778. RETAILMSG(DEBUGMODE,  (TEXT("SL_GetModemStatus: ubModemStatus = 0x%xrn"), ubModemStatus));
  1779. if ( ubModemStatus & COM2440_MSR_CTS )
  1780. *pModemStatus |= MS_CTS_ON;
  1781. if ( ubModemStatus & COM2440_MSR_DSR )
  1782. {
  1783. *pModemStatus |= MS_DSR_ON;
  1784. *pModemStatus |= MS_RLSD_ON;
  1785. }
  1786. RETAILMSG(DEBUGMODE,(TEXT("-SL_GetModemStatus 0x%X (stat x%X) rn"), pHead, *pModemStatus));
  1787. return;
  1788. }
  1789. //
  1790. // @doc OEM
  1791. // @func    VOID | SL_PurgeComm | Purge RX and/or TX
  1792. // 
  1793. // @rdesc    None.
  1794. //
  1795. VOID
  1796. SL_PurgeComm(
  1797.             PVOID   pHead,        // @parm PVOID returned by HWInit.
  1798.             DWORD   fdwAction        // @parm Action to take. 
  1799.             )
  1800. {
  1801. PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
  1802. RETAILMSG(DEBUGMODE,(TEXT("+SL_PurgeComm 0x%Xrn"), fdwAction));
  1803. return;
  1804. }
  1805. //
  1806. // @doc OEM
  1807. // @func    BOOL | SL_XmitComChar | Transmit a char immediately
  1808. // 
  1809. // @rdesc    TRUE if succesful
  1810. //
  1811. BOOL
  1812. SL_XmitComChar(
  1813.               PVOID   pHead,    // @parm PVOID returned by HWInit.
  1814.               UCHAR   ComChar   // @parm Character to transmit. 
  1815.               )
  1816. {
  1817. PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
  1818. ULONG       rFifoStat, TxFifoCnt; 
  1819. RETAILMSG (DEBUGMODE,(TEXT("+SL_XmitComChar 0x%Xrn"), pHead));
  1820. // Get critical section, then transmit when buffer empties
  1821. RETAILMSG(DEBUGMODE, (TEXT("XmitComChar wait for CritSec %x.rn"),&(pHWHead->TransmitCritSec)));
  1822. EnterCriticalSection(&(pHWHead->TransmitCritSec));
  1823. RETAILMSG(DEBUGMODE, (TEXT("XmitComChar got CritSec %x.rn"),&(pHWHead->TransmitCritSec)));
  1824. try
  1825. {
  1826. while ( TRUE ) // We know THR will eventually empty
  1827. {
  1828. EnterCriticalSection(&(pHWHead->RegCritSec));
  1829. // Write the character if we can
  1830. rFifoStat = INREG(pHWHead,rUFSTAT);
  1831. TxFifoCnt = (rFifoStat & SER2440_FIFOCNT_MASK_TX) >> 8;
  1832. if (!(rFifoStat & SER2440_FIFOFULL_TX) && (TxFifoCnt < (SER2440_FIFO_DEPTH_TX-1)))
  1833. {
  1834. // FIFO is empty, send this character
  1835. //OUTB(pHWHead, pData, ComChar);
  1836. OUTREG(pHWHead,rUTXH,ComChar);
  1837. // Make sure we release the register critical section
  1838. LeaveCriticalSection(&(pHWHead->RegCritSec));
  1839. RETAILMSG(DEBUGMODE, (TEXT("XmitComChar wrote x%Xrn"),ComChar));
  1840. break;
  1841. }
  1842. // If we couldn't write the data yet, then wait for a
  1843. // TXINTR to come in and try it again.
  1844. // Enable xmit intr.
  1845. EnINT(pHWHead, pHWHead->bINT);
  1846. EnSubINT(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
  1847. pHWHead->fSW_EnTxINT = TRUE;
  1848. LeaveCriticalSection(&(pHWHead->RegCritSec));
  1849. // Wait until the txintr has signalled.
  1850. DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar WaitIntr x%Xrn"),
  1851. pHWHead->FlushDone));
  1852. WaitForSingleObject(pHWHead->FlushDone, (ULONG)1000);
  1853. }
  1854. }
  1855. except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
  1856. EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
  1857. {
  1858. // Make sure we release the register critical section
  1859. LeaveCriticalSection(&(pHWHead->RegCritSec));
  1860. }
  1861. LeaveCriticalSection(&(pHWHead->TransmitCritSec));
  1862. DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar released CritSec %x.rn"), &(pHWHead->TransmitCritSec)));
  1863. DEBUGMSG (ZONE_FUNCTION, (TEXT("-SL_XmitComChar 0x%Xrn"), pHead));
  1864. return(TRUE);
  1865. }
  1866. //
  1867. // @doc OEM
  1868. // @func    BOOL | SL_PowerOff | Perform powerdown sequence.
  1869. // 
  1870. // @rdesc    TRUE if succesful
  1871. //
  1872. VOID
  1873. SL_PowerOff(PVOID   pHead) // @parm    PVOID returned by HWInit.
  1874. {
  1875. PS2440_UART_INFO   pHWHead   = (PS2440_UART_INFO)pHead;
  1876. RETAILMSG(0, (TEXT("SL_PowerOff rn")));
  1877. if ( !pHWHead->UseIrDA )
  1878. {
  1879. // DeAssert DTR
  1880. *(pHWHead->rDTRport) |= (1<<(pHWHead->DtrPortNum));
  1881. // DeAssert RTS
  1882. #if USE_AFC
  1883. *(pHWHead->rRTSport) |= (1<<(pHWHead->RtsPortNum));
  1884. #else
  1885. CLEARREG(pHWHead, rUMCON, SER2440_RTS);
  1886. #endif
  1887. }
  1888. pHWHead->sULCON = INREG(pHWHead, rULCON);
  1889. pHWHead->sUCON  = INREG(pHWHead, rUCON);
  1890. pHWHead->sUMCON = INREG(pHWHead, rUMCON);
  1891. pHWHead->sUFCON = INREG(pHWHead, rUFCON);        
  1892. pHWHead->sINTstat = (*(pHWHead->UART_INTSUBMASK) & (pHWHead->bTxINT | pHWHead->bRxINT));
  1893. }
  1894. //
  1895. // @doc OEM
  1896. // @func    BOOL | SL_PowerOn | Perform poweron sequence.
  1897. // 
  1898. // @rdesc    TRUE if succesful
  1899. //
  1900. VOID
  1901. SL_PowerOn(PVOID   pHead) // @parm    PVOID returned by HWInit.
  1902. {
  1903. PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
  1904. // Restore any registers that we need
  1905. RETAILMSG(DEBUGMODE, (TEXT("SL_PowerOn rn")));
  1906. if ( !pHWHead->UseIrDA )
  1907. {
  1908. // Assert DTR
  1909. *(pHWHead->rDTRport) &= ~(1<<(pHWHead->DtrPortNum));
  1910. // Assert RTS
  1911. #if USE_AFC
  1912. *(pHWHead->rRTSport) &= ~(1<<(pHWHead->RtsPortNum));
  1913. #else
  1914. SETREG(pHWHead, rUMCON, SER2440_RTS);
  1915. #endif
  1916. }
  1917. // In power handler context, so don't try to do a critical section
  1918. OUTREG(pHWHead, rULCON, pHWHead->sULCON); 
  1919. OUTREG(pHWHead, rUCON,  pHWHead->sUCON); 
  1920. OUTREG(pHWHead, rUMCON, pHWHead->sUMCON); 
  1921. OUTREG(pHWHead, rUFCON, pHWHead->sUFCON); 
  1922. if((pHWHead->sINTstat) & (pHWHead->bTxINT))
  1923. {
  1924. EnINT(pHWHead, pHWHead->bINT);
  1925. EnSubINT(pHWHead, pHWHead->bTxINT);
  1926. pHWHead->fSW_EnTxINT = TRUE;
  1927. pHWHead->RxDiscard = FALSE;
  1928. }
  1929. if((pHWHead->sINTstat) & (pHWHead->bRxINT))
  1930. {
  1931. EnINT(pHWHead, pHWHead->bINT);
  1932. EnSubINT(pHWHead, pHWHead->bRxINT);
  1933. }
  1934. // And we didn't save the Divisor Reg, so set baud rate
  1935. // But don't call SL_SetBaud, since it does DebugMsg.
  1936. // Call our internal function instead.  Can't acquire
  1937. // the RegCritSec, but shouldn't really need to since
  1938. // we are in power context.
  1939. SetBaudRate( pHWHead, pHWHead->dcb.BaudRate );
  1940. return;
  1941. pHWHead->EventCallback( pHWHead->pMddHead, EV_POWER );
  1942. }
  1943. //
  1944. // @doc OEM
  1945. // @func    BOOL | SL_SetDCB | Sets new values for DCB.  This
  1946. // routine gets a DCB from the MDD.  It must then compare
  1947. // this to the current DCB, and if any fields have changed take
  1948. // appropriate action.
  1949. // 
  1950. // @rdesc    BOOL
  1951. //
  1952. BOOL
  1953. SL_SetDCB(
  1954.          PVOID   pHead,        // @parm    PVOID returned by HWInit.
  1955.          LPDCB   lpDCB       // @parm    Pointer to DCB structure
  1956.          )
  1957. {
  1958. PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
  1959. BOOL bRet;
  1960. bRet = TRUE;
  1961. RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : BaudRate is %drn"), lpDCB->BaudRate));
  1962. RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set ByteSize is %drn"), lpDCB->ByteSize));
  1963. RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set Parity is %drn"), lpDCB->Parity));
  1964. RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set StopBits is %drn"), lpDCB->StopBits));
  1965. // If the device is open, scan for changes and do whatever
  1966. // is needed for the changed fields.  if the device isn't
  1967. // open yet, just save the DCB for later use by the open.
  1968. if ( pHWHead->OpenCount )
  1969. {
  1970. // Note, fparity just says whether we should check
  1971. // receive parity.  And the 16550 won't let us NOT
  1972. // check parity if we generate it.  So this field
  1973. // has no effect on the hardware.
  1974. if ( lpDCB->BaudRate != pHWHead->dcb.BaudRate )
  1975. {
  1976. RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set BaudRate to %drn"), lpDCB->BaudRate));
  1977. bRet = SL_SetBaudRate( pHWHead, lpDCB->BaudRate );
  1978. }
  1979. if ( bRet && (lpDCB->ByteSize != pHWHead->dcb.ByteSize ))
  1980. {
  1981. RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set ByteSize to %drn"), lpDCB->ByteSize));
  1982. bRet = SL_SetByteSize( pHWHead, lpDCB->ByteSize );
  1983. }
  1984. if ( bRet && (lpDCB->Parity != pHWHead->dcb.Parity ))
  1985. {
  1986. RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set Parity to %drn"), lpDCB->Parity));
  1987. bRet = SL_SetParity( pHWHead, lpDCB->Parity );
  1988. }
  1989. if ( bRet && (lpDCB->StopBits != pHWHead->dcb.StopBits ))
  1990. {
  1991. RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set StopBits to %drn"), lpDCB->StopBits));
  1992. bRet = SL_SetStopBits( pHWHead, lpDCB->StopBits );
  1993. }
  1994. // Don't worry about fOutxCtsFlow.  It is a flag which
  1995. // will be examined every time we load the TX buffer.
  1996. // No special action required here.
  1997. }
  1998. if (bRet)
  1999. {
  2000. // Now that we have done the right thing, store this DCB
  2001. pHWHead->dcb = *lpDCB;
  2002. }
  2003. RETAILMSG(DEBUGMODE,(TEXT("-SL_SetDCB 0x%Xrn"), pHead));
  2004. return(bRet);
  2005. }
  2006. //
  2007. // @doc OEM
  2008. // @func    BOOL | SL_SetCommTimeouts | Sets new values for the
  2009. // CommTimeouts structure. routine gets a DCB from the MDD.  It
  2010. // must then compare this to the current DCB, and if any fields
  2011. // have changed take appropriate action.
  2012. // 
  2013. // @rdesc    ULONG
  2014. //
  2015. ULONG
  2016. SL_SetCommTimeouts(
  2017.                   PVOID   pHead,        // @parm    PVOID returned by HWInit.
  2018.                   LPCOMMTIMEOUTS   lpCommTimeouts // @parm Pointer to CommTimeout structure
  2019.                   )
  2020. {
  2021. PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
  2022. ULONG retval = 0;
  2023. RETAILMSG(DEBUGMODE,(TEXT("+SL_SetCommTimeout 0x%Xrn"), pHead));
  2024. // ShowSerialRegisters(pHead);
  2025. // OK, first check for any changes and act upon them
  2026. if ( lpCommTimeouts->WriteTotalTimeoutMultiplier !=
  2027. pHWHead->CommTimeouts.WriteTotalTimeoutMultiplier )
  2028. {
  2029. }
  2030. // Now that we have done the right thing, store this DCB
  2031. pHWHead->CommTimeouts = *lpCommTimeouts;
  2032. RETAILMSG(DEBUGMODE,(TEXT("-SL_SetCommTimeout 0x%Xrn"), pHead));
  2033. return(retval);
  2034. }
  2035. //
  2036. //  @doc OEM
  2037. //  @func    BOOL | SL_Ioctl | Device IO control routine.  
  2038. //  @parm DWORD | dwOpenData | value returned from COM_Open call
  2039. //    @parm DWORD | dwCode | io control code to be performed
  2040. //    @parm PBYTE | pBufIn | input data to the device
  2041. //    @parm DWORD | dwLenIn | number of bytes being passed in
  2042. //    @parm PBYTE | pBufOut | output data from the device
  2043. //    @parm DWORD | dwLenOut |maximum number of bytes to receive from device
  2044. //    @parm PDWORD | pdwActualOut | actual number of bytes received from device
  2045. //
  2046. //    @rdesc        Returns TRUE for success, FALSE for failure
  2047. //
  2048. //  @remark  The MDD will pass any unrecognized IOCTLs through to this function.
  2049. //
  2050. BOOL
  2051. SL_Ioctl(PVOID pHead, DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,
  2052.          PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
  2053. {
  2054. //    PSER_INFO pHWHead = (PSER_INFO)pHead;
  2055. PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
  2056.     DWORD dwErr = ERROR_SUCCESS;    
  2057.     BOOL  bRc = TRUE;
  2058.     
  2059.     switch (dwCode)
  2060. {
  2061.         //
  2062.         // Power Management
  2063.         //
  2064.         case IOCTL_POWER_CAPABILITIES: 
  2065.         {
  2066.             PPOWER_CAPABILITIES ppc;
  2067.             
  2068.             if ( !pdwActualOut || !pBufOut || (dwLenOut < sizeof(POWER_CAPABILITIES)))
  2069. {
  2070.                 bRc = FALSE;
  2071.                 dwErr = ERROR_INVALID_PARAMETER;
  2072.                 break;
  2073.             }
  2074.             
  2075.             ppc = (PPOWER_CAPABILITIES)pBufOut;
  2076.             
  2077.             memset(ppc, 0, sizeof(POWER_CAPABILITIES));
  2078. // ppc->DeviceDx = 0x11; // support D0, D4
  2079. ppc->DeviceDx = 0x11; // support D0-D2, D4 (no D3)
  2080.             // no wake
  2081.             // no inrush
  2082.             // Report our power consumption in uAmps rather than mWatts. 
  2083.             ppc->Flags = POWER_CAP_PREFIX_MICRO | POWER_CAP_UNIT_AMPS;
  2084.             
  2085.             // (UART @ 1.2 mA + IR Transmitter LED ON  @ 32 mA) = 33.2 mA = 33200 uA @ 200 MHz
  2086.             //                  IR Transmitter LED OFF @ 1.5 nA
  2087.             ppc->Power[D0] = 33200;
  2088.             
  2089.             *pdwActualOut = sizeof(POWER_CAPABILITIES);
  2090.         } 
  2091. break;
  2092.         case IOCTL_POWER_SET: 
  2093.         {
  2094.             CEDEVICE_POWER_STATE NewDx;
  2095.             
  2096.             if ( !pdwActualOut || !pBufOut || (dwLenOut < sizeof(CEDEVICE_POWER_STATE)))
  2097. {
  2098.                 bRc = FALSE;
  2099.                 dwErr = ERROR_INVALID_PARAMETER;
  2100.                 break;
  2101.             }
  2102.             
  2103.             NewDx = *(PCEDEVICE_POWER_STATE)pBufOut;
  2104.             if ( VALID_DX(NewDx))
  2105. {
  2106.                 // grab the CS since the normal Xxx_PowerXxx can not.
  2107.                 EnterCriticalSection( &pHWHead->RegCritSec );
  2108.                 switch ( NewDx )
  2109. {
  2110.                     case D0:
  2111.                         SerPowerOn(pHead);
  2112.                         break;
  2113.                     default:
  2114.                         SerPowerOff(pHead);
  2115.                         break;
  2116.                 }
  2117.                 // return our Dx
  2118.                 *(PCEDEVICE_POWER_STATE)pBufOut = pHWHead->Dx;
  2119.                     
  2120.                 RETAILMSG(1, (TEXT("IrDA: IOCTL_POWER_SET: D%u => D%u rn"),
  2121.                     NewDx, pHWHead->Dx));
  2122.                 
  2123.                 LeaveCriticalSection( &pHWHead->RegCritSec );
  2124.                 
  2125.                 *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
  2126.             }
  2127. else
  2128. {
  2129.                 bRc = FALSE;
  2130.                 dwErr = ERROR_INVALID_PARAMETER;
  2131.             }
  2132.             
  2133.         } 
  2134. break;
  2135.         case IOCTL_POWER_GET: 
  2136.             if ( !pdwActualOut || !pBufOut || (dwLenOut < sizeof(CEDEVICE_POWER_STATE)))
  2137. {
  2138.                 bRc = FALSE;
  2139.                 dwErr = ERROR_INVALID_PARAMETER;
  2140.                 break;
  2141.             }
  2142.             *(PCEDEVICE_POWER_STATE)pBufOut = pHWHead->Dx;
  2143.             DEBUGMSG(1, (TEXT("IrDA: IOCTL_POWER_GET: D%u rn"), pHWHead->Dx));
  2144.             *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
  2145.             
  2146. break;
  2147.         default:
  2148.             bRc = FALSE;
  2149.             DEBUGMSG (ZONE_FUNCTION, (TEXT(" Unsupported ioctl 0x%Xrn"), dwCode));
  2150.             break;            
  2151.     }
  2152.     
  2153.     return(bRc);
  2154. }