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

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_SER.C
  11. Abstract:  
  12. Notes: 
  13. --*/
  14. #define EXAMINE_BOOTARGS
  15. #define DEBUGMODE 0
  16. #include <windows.h>
  17. #include <types.h>
  18. #include <ceddk.h>
  19. #include <memory.h>
  20. #include <serhw.h>
  21. #include <ser16550.h>
  22. #include <hw16550.h>
  23. #include <nkintr.h>
  24. #include <devload.h>
  25. #include <windev.h>
  26. #include <notify.h>
  27. #include <pm.h>
  28. #include "S2440.h"
  29. #define USERDBG        1
  30. #ifdef EXAMINE_BOOTARGS
  31. #include <bootarg.h>
  32. #include <oalintr.h>
  33. #include <pc.h>
  34. #endif
  35. #include <ser2440.h>
  36. #undef ZONE_INIT
  37. #include <serdbg.h>
  38. static BOOL IRDA;
  39. #define BAUD_TABLE_SIZE 23
  40. static const
  41. PAIRS   BaudPairs[BAUD_TABLE_SIZE] =    {
  42. {50,        2307},
  43. {75,        1538},
  44. {110,       1049},
  45. {135,       858},
  46. {150,       769},
  47. {300,       384},
  48. {600,       192},
  49. {1200,      96},
  50. {1800,      64},
  51. {2000,      58},
  52. {2400,      48},
  53. {3600,      32},
  54. {4800,      24},
  55. {7200,      16},
  56. {9600,      12},
  57. {12800,     9},
  58. {14400,     8},
  59. {19200,     6},
  60. {23040,     5},
  61. {28800,     4},
  62. {38400,     3},
  63. {57600,     2},
  64. {115200,    1}
  65. };
  66. static const LOOKUP_TBL  BaudTable = {BAUD_TABLE_SIZE, (PAIRS *) BaudPairs};
  67. // Miscellaneous internal routines.
  68. PUCHAR
  69. static
  70. Ser_InternalMapRegisterAddresses(ULONG HWAddress, ULONG Size)
  71. {
  72. PUCHAR              ioPortBase; 
  73. ULONG               inIoSpace      = 1;
  74. PHYSICAL_ADDRESS    ioPhysicalBase = { HWAddress, 0};
  75. RETAILMSG(DEBUGMODE, (TEXT("+ Ser_InternalMapRegisterAddresses : HalTranslateBusAddressrn")));
  76. if ( HalTranslateBusAddress(Isa, 0, ioPhysicalBase, &inIoSpace, &ioPhysicalBase))
  77. {
  78. DEBUGMSG(1, (TEXT("Ser_InternalMapRegisterAddresses : HalTranslateBusAddress - OKrn")));
  79. if ( !inIoSpace )
  80. {
  81. DEBUGMSG(1, (TEXT("Ser_InternalMapRegisterAddresses : ! IO Spacern")));
  82. if ( (ioPortBase = (PUCHAR)MmMapIoSpace(ioPhysicalBase, Size, FALSE)) == NULL )
  83. {
  84. // We may as well not continue
  85. DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("Error mapping I/O Portsrn")));
  86. return (NULL);
  87. }
  88. }
  89. else
  90. {
  91. DEBUGMSG(1, (TEXT("Ser_InternalMapRegisterAddresses : IO Spacern")));
  92. ioPortBase = (PUCHAR)ioPhysicalBase.LowPart;
  93. }
  94. }
  95. else
  96. {
  97. DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("Error translating I/O Ports.rn")));
  98. return (NULL);
  99. }
  100. RETAILMSG(DEBUGMODE, (TEXT("- Ser_InternalMapRegisterAddresses : %drn"),ioPortBase ));
  101. return (ioPortBase);
  102. }
  103. static
  104. BOOL
  105. SerSetIRBaudRate(
  106. PSER_INFO   pHWHead,
  107. ULONG baud     // @parm     UINT16 what is the baud rate
  108. )
  109. {
  110. PS2440_UART_INFO   pHWHead2   = (PS2440_UART_INFO)pHWHead;
  111. RETAILMSG(DEBUGMODE, (TEXT("IRDA : +SerSetIRBaudRatern")));    
  112. DEBUGMSG (ZONE_INIT|1, (TEXT("Serial set IR Baud %drn"), baud));
  113. if ( (pHWHead2->s2440SerReg->rUCON & CS_MASK) == CS_PCLK )
  114. {
  115. RETAILMSG (1, (TEXT("USE CS_PCLKrn")));    
  116. OUTREG(pHWHead2,rUBRDIV,( (int)(S2440PCLK/16.0/baud) -1 ));
  117. }
  118. else // if  ( (pHWHead2->s2440SerReg->rUCON & CS_MASK) == CS_UCLK )
  119. {
  120. RETAILMSG (1, (TEXT("USE CS_UCLKrn")));    
  121. OUTREG(pHWHead2,rUBRDIV,( (int)(S2440UCLK/16.0/baud) -1 ));
  122. }
  123. RETAILMSG(DEBUGMODE, (TEXT("IRDA : -SerSetIRBaudRatern")));
  124. return (TRUE);
  125. }
  126. /*
  127.  *  NOTE : The caller should have set pHWHead->fIRMode.  It is not
  128.  * set here, since power on/off may need to temporarily disable
  129.  * the intefaces without actually overwriting the current recorded
  130.  * mode.
  131.  */
  132. static
  133. void
  134. SerSetOutputMode(
  135.                 PSER_INFO   pHWHead,
  136.                 BOOL UseIR,     // @parm     BOOL Should we use IR interface
  137.                 BOOL Use9Pin    // @parm     BOOL Should we use Wire interface
  138.                 )
  139. {
  140. // If you support IR, here you need to set the interface to either IR mode
  141. // or normal serial. Note that it is possible for both BOOls to
  142. // be false (i.e. power down), but never for both to be TRUE.
  143. PS2440_UART_INFO   pHWHead2   = (PS2440_UART_INFO)pHWHead;
  144. RETAILMSG (DEBUGMODE, (TEXT("+SerSetOutputModern")));
  145. if(UseIR)  
  146. SETREG(pHWHead2,rULCON,SER2440_IRMODE_MASK);   // Infra-red mode enable.
  147. else
  148. CLEARREG(pHWHead2,rULCON,SER2440_IRMODE_MASK);   // Infra-red mode enable.
  149. RETAILMSG(DEBUGMODE, (TEXT("-SerSetOutputModern")));
  150. }
  151. /*++
  152. *******************************************************************************
  153. Routine:
  154.     Ser_GetRegistryData
  155. Description:
  156.     Take the registry path provided to COM_Init and use it to find this 
  157.     requested comm port's DeviceArrayIndex, teh IOPort Base Address, and the
  158.    Interrupt number.
  159.    
  160. Arguments:
  161.     LPCTSTR regKeyPath the registry path passed in to COM_Init.
  162. Return Value:
  163.     -1 if there is an error.
  164. *******************************************************************************
  165. --*/
  166. BOOL
  167. Ser_GetRegistryData(PSER_INFO pHWHead, LPCTSTR regKeyPath)
  168. {
  169. #define GCI_BUFFER_SIZE 256   
  170. LONG    regError;
  171. HKEY    hKey;
  172. DWORD   dwDataSize = GCI_BUFFER_SIZE;
  173. RETAILMSG(DEBUGMODE, (TEXT("Try to open %srn"), regKeyPath));
  174. // We've been handed the name of a key in the registry that was generated
  175. // on the fly by device.exe.  We're going to open that key and pull from it
  176. // a value that is the name of this serial port's real key.  That key
  177. // will have the DeviceArrayIndex that we're trying to find.  
  178. hKey = OpenDeviceKey(regKeyPath);
  179. if ( hKey == NULL )
  180. {
  181. DEBUGMSG(ZONE_INIT | ZONE_ERROR,(TEXT("Failed to open device keyrn")));
  182. return ( FALSE );        
  183. }
  184. // Okay, we're finally ready to try and load our registry data.
  185. dwDataSize = PC_REG_DEVINDEX_VAL_LEN;
  186. regError = RegQueryValueEx(
  187. hKey, 
  188. PC_REG_DEVINDEX_VAL_NAME, 
  189. NULL, 
  190. NULL,
  191. (LPBYTE)(&pHWHead->dwDevIndex), 
  192. &dwDataSize);
  193. if ( regError == ERROR_SUCCESS )
  194. {
  195. dwDataSize = PC_REG_IRQ_VAL_LEN;
  196. regError = RegQueryValueEx(
  197. hKey, 
  198. PC_REG_IRQ_VAL_NAME, 
  199. NULL, 
  200. NULL,
  201. (LPBYTE)(&pHWHead->dwIRQ), 
  202. &dwDataSize);
  203. }
  204. if ( regError == ERROR_SUCCESS )
  205. {
  206. dwDataSize = PC_REG_IOBASE_VAL_LEN;
  207. regError = RegQueryValueEx(
  208. hKey, 
  209. PC_REG_IOBASE_VAL_NAME, 
  210. NULL, 
  211. NULL,
  212. (LPBYTE)(&pHWHead->dwIOBase), 
  213. &dwDataSize);
  214. }
  215. if ( regError == ERROR_SUCCESS )
  216. {
  217. dwDataSize = PC_REG_IOLEN_VAL_LEN;
  218. regError = RegQueryValueEx(
  219. hKey, 
  220. PC_REG_IOLEN_VAL_NAME, 
  221. NULL, 
  222. NULL,
  223. (LPBYTE)(&pHWHead->dwIOLen), 
  224. &dwDataSize);
  225. }
  226. RegCloseKey (hKey);
  227. if ( regError != ERROR_SUCCESS )
  228. {
  229. RETAILMSG(DEBUGMODE, (TEXT("Failed to get serial registry values, Error 0x%Xrn"),regError));
  230. return ( FALSE );
  231. }
  232. RETAILMSG (DEBUGMODE,(TEXT("SerInit - Devindex %d, IRQ %d, IOB %X, IOLen %X rn"),
  233. pHWHead->dwDevIndex, pHWHead->dwIRQ, pHWHead->dwIOBase, pHWHead->dwIOLen));
  234. return ( TRUE ); 
  235. }
  236. /*
  237.  @doc OEM 
  238.  @func PVOID | SerInit | Initializes device identified by argument.
  239.  *  This routine sets information controlled by the user
  240.  *  such as Line control and baud rate. It can also initialize events and
  241.  *  interrupts, thereby indirectly managing initializing hardware buffers.
  242.  *  Exported only to driver, called only once per process.
  243.  *
  244.  @rdesc The return value is a PVOID to be passed back into the HW
  245.  dependent layer when HW functions are called.
  246.  */
  247. static
  248. PVOID
  249. SerInit(
  250. BOOL bIR,
  251.        ULONG   Identifier, // @parm Device identifier.
  252.        PVOID   pMddHead,   // @parm First argument to mdd callbacks.
  253.        PHWOBJ  pHWObj      // @parm Pointer to our own HW OBJ for this device
  254.        )
  255. {
  256. PSER_INFO pHWHead;
  257. #ifdef EXAMINE_BOOTARGS    
  258. PVOID *ppBootArgs     = NULL;  // Pointer to pointer to bootargs.
  259. PHYSICAL_ADDRESS PhysicalAddress = {0,0};
  260. #endif    
  261. // Note on defaults.  While the PC typcially considers COM1 to be at 
  262. // 3F8, irq4 and COM2 to be 2F8, irq3, NKPC uses COM1 internally for the
  263. // debugger.  So, when NK tells me to start "COM1" it really means the
  264. // first one that's available, which is what the PC calls COM2.  Confused?
  265. // The end result is that COM1 on NK is what the PC considers to be COM2.
  266. // But wait, there's more.  On a Puzzle, the debugger is on COM2 and the
  267. // COM1 for NK is ACTUALLY COM1.  So PCs need 2F8 for their port base
  268. // and Puzzles need 3F8.
  269. RETAILMSG(DEBUGMODE, (TEXT("SerInit - !!! rn")));
  270. // Allocate for our main data structure and one of it's fields.
  271. pHWHead = (PSER_INFO)LocalAlloc( LMEM_ZEROINIT|LMEM_FIXED, sizeof(SER_INFO) );
  272. if ( !pHWHead )
  273. return( NULL );
  274. if ( ! Ser_GetRegistryData(pHWHead, (LPCTSTR)Identifier) )
  275. {
  276. DEBUGMSG (ZONE_INIT|ZONE_ERROR, (TEXT("SerInit - Unable to read registry data.  Failing Init !!! rn")));
  277. goto ALLOCFAILED;
  278. }
  279. pHWHead->pBaseAddress = Ser_InternalMapRegisterAddresses(pHWHead->dwIOBase, pHWHead->dwIOLen);
  280. #ifdef EXAMINE_BOOTARGS        
  281. // Allocate a pointer to our bootargs since they may indicate that we don't have
  282. // access to the hardware resource.
  283. // First, map the bootargs pointer itself.  Note that I'm reading/writing
  284. // directly on the physical address.  I can do this since I know this is CEPC and 
  285. // know the adress is not in IO space.  For OEM platforms you would want to do
  286. // HalTranslateBusAddress first.
  287. PhysicalAddress.LowPart = BOOT_ARG_PTR_LOCATION & ~0x80000000;
  288. if ( ppBootArgs = MmMapIoSpace(PhysicalAddress, sizeof( PVOID ), TRUE ) )
  289. {
  290. DEBUGMSG (ZONE_INIT, (TEXT("SerInit - ppBootArgs (%X) at %Xrn"), PhysicalAddress.LowPart, ppBootArgs ));
  291. }
  292. else
  293. {
  294. DEBUGMSG (ZONE_INIT | ZONE_ERROR, (TEXT("SerInit - ppBootArgs failure at %Xrn"), PhysicalAddress.LowPart ));
  295. goto ALLOCFAILED;
  296. }
  297. // Now map the bootargs structure itself
  298. PhysicalAddress.LowPart = (DWORD) *ppBootArgs;
  299. if ( pHWHead->pBootArgs = MmMapIoSpace(PhysicalAddress, sizeof(BOOT_ARGS), TRUE ) )
  300. {
  301. DEBUGMSG (ZONE_INIT, (TEXT("SerInit - pBootArgs (%X) at %Xrn"), PhysicalAddress.LowPart, pHWHead->pBootArgs ));
  302. }
  303. else
  304. {
  305. DEBUGMSG (ZONE_INIT | ZONE_ERROR, (TEXT("SerInit - pBootArgs failure at %Xrn"), (DWORD)PhysicalAddress.LowPart));
  306. goto ALLOCFAILED;
  307. }
  308. // We no longer need ppBootArgs
  309. MmUnmapIoSpace( ppBootArgs, sizeof(PVOID) );
  310. #endif // EXAMINE_BOOTARGS
  311. pHWHead->pMddHead     = pMddHead;
  312. pHWHead->pHWObj = pHWObj;
  313. pHWHead->cOpenCount   = 0;
  314. RETAILMSG(DEBUGMODE,(TEXT("SerInit - IRQ %d = SYSINTR %drn"),
  315. pHWHead->dwIRQ, pHWHead->pHWObj->dwIntID));
  316. // Set up our Comm Properties data    
  317. pHWHead->CommProp.wPacketLength       = 0xffff;
  318. pHWHead->CommProp.wPacketVersion     = 0xffff;
  319. pHWHead->CommProp.dwServiceMask      = SP_SERIALCOMM;
  320. pHWHead->CommProp.dwReserved1         = 0;
  321. pHWHead->CommProp.dwMaxTxQueue        = 16;
  322. pHWHead->CommProp.dwMaxRxQueue        = 16;
  323. pHWHead->CommProp.dwMaxBaud       = BAUD_115200;
  324. pHWHead->CommProp.dwProvSubType      = PST_RS232;
  325. pHWHead->CommProp.dwProvCapabilities =
  326. PCF_DTRDSR | PCF_RLSD | PCF_RTSCTS |
  327. PCF_SETXCHAR |
  328. PCF_INTTIMEOUTS |
  329. PCF_PARITY_CHECK |
  330. PCF_SPECIALCHARS |
  331. PCF_TOTALTIMEOUTS |
  332. PCF_XONXOFF;
  333. pHWHead->CommProp.dwSettableBaud      =
  334. BAUD_075 | BAUD_110 | BAUD_150 | BAUD_300 | BAUD_600 |
  335. BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
  336. BAUD_7200 | BAUD_9600 | BAUD_14400 |
  337. BAUD_19200 | BAUD_38400 | BAUD_56K | BAUD_128K |
  338. BAUD_115200 | BAUD_57600 | BAUD_USER;
  339. pHWHead->CommProp.dwSettableParams    =
  340. SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY |
  341. SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;
  342. pHWHead->CommProp.wSettableData       =
  343. DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
  344. pHWHead->CommProp.wSettableStopParity =
  345. STOPBITS_10 | STOPBITS_20 |
  346. PARITY_NONE | PARITY_ODD | PARITY_EVEN | PARITY_SPACE |
  347. PARITY_MARK;
  348. pHWHead->fIRMode = bIR;
  349. pHWHead->s2440COM.UseIrDA = bIR;
  350. #ifdef EXAMINE_BOOTARGS
  351. // Don't actually init the hardware if it is being used for debugging
  352. if ( ((pHWHead->pBootArgs->ucComPort == 1) && (pHWHead->dwIOBase == COM1_BASE)) ||
  353. ((pHWHead->pBootArgs->ucComPort == 2) && (pHWHead->dwIOBase == COM2_BASE)) || 
  354. ((pHWHead->pBootArgs->ucComPort == 3) && (pHWHead->dwIOBase == COM3_BASE)) ||
  355. ((pHWHead->pBootArgs->ucComPort == 4) && (pHWHead->dwIOBase == COM4_BASE)) ) {
  356. DEBUGMSG (ZONE_INIT|ZONE_ERROR, (TEXT("rnSerInit - Skipping hardware init of debug portrnrn")));        
  357. } else
  358. #endif
  359. {
  360. DEBUGMSG (ZONE_INIT|USERDBG, (TEXT("SerInit - Init 16550 datarn")));
  361. SL_Init( pHWHead, pHWHead->pBaseAddress, 1,
  362. EvaluateEventFlag, pMddHead, (PLOOKUP_TBL)&BaudTable);
  363. DEBUGMSG (ZONE_INIT,
  364. (TEXT("SerInit - Disabling UART Powerrn")));
  365. SerSetOutputMode(pHWHead, FALSE, FALSE );    
  366. }
  367. return (pHWHead);
  368. ALLOCFAILED:
  369. if ( pHWHead->pBaseAddress )
  370. VirtualFree(pHWHead->pBaseAddress, 0, MEM_RELEASE);
  371. if ( ppBootArgs )
  372. MmUnmapIoSpace( ppBootArgs, sizeof( PVOID ) );
  373. if ( pHWHead->pBootArgs )
  374. MmUnmapIoSpace( pHWHead->pBootArgs, sizeof(BOOT_ARGS) );
  375. LocalFree(pHWHead);
  376. return (NULL);
  377. }
  378. PVOID
  379. SerInitSerial(
  380.        ULONG   Identifier, // @parm Device identifier.
  381.        PVOID   pMddHead,   // @parm First argument to mdd callbacks.
  382.        PHWOBJ  pHWObj      // @parm Pointer to our own HW OBJ for this device
  383. )
  384. {
  385. return (SerInit(FALSE, Identifier, pMddHead, pHWObj));
  386. }
  387. PVOID
  388. SerInitIR(
  389.        ULONG   Identifier, // @parm Device identifier.
  390.        PVOID   pMddHead,   // @parm First argument to mdd callbacks.
  391.        PHWOBJ  pHWObj      // @parm Pointer to our own HW OBJ for this device
  392. )
  393. {
  394. return (SerInit(TRUE, Identifier, pMddHead, pHWObj));
  395. }
  396. /*
  397.  @doc OEM
  398.  @func ULONG | SerClose | This routine closes the device identified by the PVOID returned by SerInit.
  399.  *  Not exported to users, only to driver.
  400.  *
  401.  @rdesc The return value is 0.
  402.  */
  403. static
  404. ULONG
  405. SerClose(
  406.         PVOID   pHead   // @parm PVOID returned by SerInit.
  407.         )
  408. {
  409. PSER_INFO   pHWHead = (PSER_INFO)pHead;
  410. ULONG  uTries;
  411. RETAILMSG (DEBUGMODE,(TEXT("+SerClosern")));
  412. if ( pHWHead->cOpenCount )
  413. {
  414. DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose, closing devicern")));
  415. pHWHead->cOpenCount--;
  416. // while we are still transmitting, sleep.
  417. uTries = 0;
  418. while((pHWHead->s2440COM.s2440SerReg->rUFSTAT & SER2440_FIFOSTAT_MASK) & (uTries++ < 100)) // TxFifo not empty..
  419. {
  420. DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose, TX in progress.rn")));            
  421. Sleep(10);
  422. }
  423. // When the device is closed, we power it down.
  424. DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose - Powering down UARTrn")));
  425. pHWHead->fIRMode  = FALSE;
  426. SerSetOutputMode(pHWHead, FALSE, FALSE );
  427. DEBUGMSG (ZONE_CLOSE, (TEXT("SerClose - Calling SL_Closern")));
  428. SL_Close( pHWHead );
  429. }
  430. RETAILMSG(DEBUGMODE,(TEXT("-SerClosern")));
  431. return (0);
  432. }
  433. /*
  434.  @doc OEM 
  435.  @func PVOID | SerDeinit | Deinitializes device identified by argument.
  436.  *  This routine frees any memory allocated by SerInit.
  437.  *
  438.  */
  439. static
  440. BOOL
  441. SerDeinit(PVOID   pHead)   // @parm PVOID returned by SerInit.
  442. {
  443. PSER_INFO   pHWHead = (PSER_INFO)pHead;
  444. RETAILMSG(DEBUGMODE,(TEXT("SerDeinit rn")));
  445. if ( !pHWHead )
  446. return (FALSE);
  447. // Make sure device is closed before doing DeInit
  448. if ( pHWHead->cOpenCount )
  449. SerClose( pHead );
  450. SL_Deinit( pHead );
  451. if ( pHWHead->pBaseAddress )
  452. VirtualFree(pHWHead->pBaseAddress, 0, MEM_RELEASE);
  453. if ( pHWHead->pBootArgs )
  454. MmUnmapIoSpace( pHWHead->pBootArgs, sizeof(BOOT_ARGS) );
  455. // Free the HWObj
  456. LocalFree(pHWHead->pHWObj);
  457. // And now free the SER_INFO structure.
  458. LocalFree(pHWHead);
  459. return (TRUE);
  460. }
  461. /*
  462.  @doc OEM
  463.  @func VOID | SerGetCommProperties | Retrieves Comm Properties.
  464.  *
  465.  @rdesc None.
  466.  */
  467. static
  468. VOID
  469. SerGetCommProperties(
  470.                     PVOID   pHead,      // @parm PVOID returned by SerInit. 
  471.                     LPCOMMPROP  pCommProp   // @parm Pointer to receive COMMPROP structure. 
  472.                     )
  473. {
  474. PSER_INFO   pHWHead = (PSER_INFO)pHead;
  475. RETAILMSG(DEBUGMODE,(TEXT("+SerGetCommPropertiesrn")));
  476. *pCommProp = pHWHead->CommProp;
  477. return;
  478. }
  479. /*
  480.  @doc OEM
  481.  @func VOID | SerSetBaudRate |
  482.  * This routine sets the baud rate of the device.
  483.  *  Not exported to users, only to driver.
  484.  *
  485.  @rdesc None.
  486.  */
  487. static
  488. BOOL
  489. SerSetBaudRate(
  490.               PVOID   pHead,  // @parm     PVOID returned by SerInit
  491.               ULONG   BaudRate    // @parm     ULONG representing decimal baud rate.
  492.               )
  493. {
  494. PSER_INFO   pHWHead = (PSER_INFO)pHead;
  495. RETAILMSG(DEBUGMODE,(TEXT("IRDA : SerSetBaudRate rn")));
  496. // If we are running in IR mode, try to set the IR baud
  497. // first, since it supports a subset of the rates supported
  498. // by the UART.  If we fail setting the IR rate, then
  499. // return an error and leave the UART alone.
  500. if ( IRDA )
  501. {
  502. if ( ! SerSetIRBaudRate( pHWHead, BaudRate ) )
  503. {
  504. DEBUGMSG (ZONE_ERROR, 
  505. (TEXT("Unsupported IR BaudRatern")));
  506. // We should return an error, but vtbl doesn't expect one
  507. return (FALSE); 
  508. }
  509. }
  510. // Now set buadrate on the UART
  511. return ( SL_SetBaudRate( pHead, BaudRate ) );    
  512. }
  513. /*
  514.  @doc OEM
  515.  @func BOOL | SerPowerOff |
  516.  *  Called by driver to turn off power to serial port.
  517.  *  Not exported to users, only to driver.
  518.  *
  519.  @rdesc This routine returns a status.
  520.  */
  521. BOOL
  522. SerPowerOff(PVOID   pHead)       // @parm PVOID returned by SerInit.
  523. {
  524. PSER_INFO   pHWHead = (PSER_INFO)pHead;
  525. RETAILMSG(DEBUGMODE,(TEXT("SerPowerOffrn")));
  526. SerClose( pHWHead );
  527. // First, power down the UART
  528. SL_PowerOff( pHWHead );
  529. // And then disable our IR and 9 Pin interface
  530. SerSetOutputMode( pHWHead, FALSE, FALSE );
  531. return (TRUE);
  532. }
  533. /*
  534.  @doc OEM
  535.  @func BOOL | SerPowerOn |
  536.  *  Called by driver to turn on power to serial port.
  537.  *  Not exported to users, only to driver.
  538.  *
  539.  @rdesc This routine returns a status.
  540.  */
  541. BOOL
  542. SerPowerOn(PVOID   pHead)       // @parm PVOID returned by SerInit.
  543. {
  544. PSER_INFO   pHWHead = (PSER_INFO)pHead;
  545. RETAILMSG(DEBUGMODE,(TEXT("SerPowerOnrn")));
  546. // First, power up the UART
  547. SL_PowerOn( pHWHead );
  548. // And then enable our IR interface (if needed)
  549. SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
  550. return (TRUE);
  551. }
  552. /*
  553.  @doc OEM
  554.  @func BOOL | SerEnableIR | This routine enables ir.
  555.  *  Not exported to users, only to driver.
  556.  *
  557.  @rdesc Returns TRUE if successful, FALSEotherwise.
  558.  */
  559. static
  560. BOOL
  561. SerEnableIR(
  562.            PVOID   pHead, // @parm PVOID returned by Serinit.
  563.            ULONG   BaudRate  // @parm PVOID returned by HWinit.
  564.            )
  565. {
  566. PSER_INFO   pHWHead = (PSER_INFO)pHead;
  567. RETAILMSG(DEBUGMODE,(TEXT("SerEnableIRrn")));
  568. pHWHead->fIRMode  = TRUE;
  569. SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
  570. return (TRUE);
  571. }
  572. /*
  573.  @doc OEM
  574.  @func BOOL | SerDisableIR | This routine disable the ir.
  575.  *  Not exported to users, only to driver.
  576.  *
  577.  @rdesc Returns TRUE if successful, FALSEotherwise.
  578.  */
  579. static
  580. BOOL
  581. SerDisableIR(PVOID   pHead) // @parm PVOID returned by Serinit.
  582. {
  583. PSER_INFO   pHWHead = (PSER_INFO)pHead;
  584. RETAILMSG(DEBUGMODE,(TEXT("SerDisableIRrn")));
  585. pHWHead->fIRMode  = FALSE;
  586. SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
  587. return (TRUE);
  588. }
  589. /*
  590.  @doc OEM
  591.  @func BOOL | SerEnableIR | This routine enables ir.
  592.  *  Not exported to users, only to driver.
  593.  *
  594.  @rdesc Returns TRUE if successful, FALSEotherwise.
  595.  */
  596. static
  597. BOOL
  598. SerEnableSerial(
  599.            PVOID   pHead, // @parm PVOID returned by Serinit.
  600.            ULONG   BaudRate  // @parm PVOID returned by HWinit.
  601.            )
  602. {
  603. PSER_INFO   pHWHead = (PSER_INFO)pHead;
  604. RETAILMSG(DEBUGMODE,(TEXT("SerEnableSerialrn")));
  605. pHWHead->fIRMode  = FALSE;
  606. SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
  607. return (TRUE);
  608. }
  609. /*
  610.  @doc OEM
  611.  @func BOOL | SerDisableIR | This routine disable the ir.
  612.  *  Not exported to users, only to driver.
  613.  *
  614.  @rdesc Returns TRUE if successful, FALSEotherwise.
  615.  */
  616. static
  617. BOOL
  618. SerDisableSerial(PVOID   pHead) // @parm PVOID returned by Serinit.
  619. {
  620. PSER_INFO   pHWHead = (PSER_INFO)pHead;
  621. RETAILMSG(DEBUGMODE,(TEXT("SerDisableSerialrn")));
  622. pHWHead->fIRMode  = TRUE;
  623. SerSetOutputMode( pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );
  624. return (TRUE);
  625. }
  626. /*
  627.  @doc OEM
  628.  @func BOOL | SerOpen | This routine is called when the port is opened.
  629.  *  Not exported to users, only to driver.
  630.  *
  631.  @rdesc Returns TRUE if successful, FALSEotherwise.
  632.  */
  633. static
  634. BOOL
  635. SerOpen(PVOID   pHead) // @parm PVOID returned by Serinit.
  636. {
  637. PSER_INFO   pHWHead = (PSER_INFO)pHead;
  638. // Disallow multiple simultaneous opens
  639. if ( pHWHead->cOpenCount )
  640. return (FALSE);
  641. #ifdef EXAMINE_BOOTARGS
  642. RETAILMSG(DEBUGMODE, (TEXT("SerOpen - Bootargs ComPort %xrn"), pHWHead->pBootArgs->ucComPort));
  643. // If the port is in use as a debugger port, don't allow opens.
  644. if ( ((pHWHead->pBootArgs->ucComPort == 1) && (pHWHead->dwIOBase == COM1_BASE)) ||
  645. ((pHWHead->pBootArgs->ucComPort == 2) && (pHWHead->dwIOBase == COM2_BASE)) || 
  646. ((pHWHead->pBootArgs->ucComPort == 3) && (pHWHead->dwIOBase == COM3_BASE)) ||
  647. ((pHWHead->pBootArgs->ucComPort == 4) && (pHWHead->dwIOBase == COM4_BASE)) )
  648. {
  649. RETAILMSG (DEBUGMODE, (TEXT("SerOpen - Fail open of debug portrn")));        
  650. return (FALSE);        
  651. }
  652. #endif
  653. pHWHead->cOpenCount++;
  654. if ( pHWHead->fIRMode == TRUE )
  655. RETAILMSG(DEBUGMODE,(TEXT("Use IrDA rn")));
  656. else
  657. RETAILMSG(DEBUGMODE,(TEXT("Use Serail rn")));
  658. SerSetOutputMode(pHWHead, pHWHead->fIRMode, !pHWHead->fIRMode );  
  659. // NOTE: - If we wanted to support 16450s, we'll could dynamically
  660. // identify them here.
  661. // Init SER2440 info
  662. RETAILMSG(DEBUGMODE, (TEXT("SerOpen - Calling SL_Openrn")));
  663. SL_Open( pHWHead );
  664. RETAILMSG(DEBUGMODE, (TEXT("SerOpen - Return TRUErn")));
  665. return (TRUE);
  666. }
  667. const
  668. HW_VTBL IoVTbl = {
  669. SerInitSerial,
  670. SL_PostInit,
  671. SerDeinit,
  672. SerOpen,
  673. SerClose,
  674. SL_GetInterruptType,
  675. SL_RxIntr,
  676. SL_TxIntrEx,
  677. SL_ModemIntr,
  678. SL_LineIntr,
  679. SL_GetRxBufferSize,
  680. SerPowerOff,
  681. SerPowerOn,
  682. SL_ClearDTR,
  683. SL_SetDTR,
  684. SL_ClearRTS,
  685. SL_SetRTS,
  686. SerEnableSerial,
  687. SerDisableSerial,
  688. SL_ClearBreak,
  689. SL_SetBreak,
  690. SL_XmitComChar,
  691. SL_GetStatus,
  692. SL_Reset,
  693. SL_GetModemStatus,
  694. SerGetCommProperties,
  695. SL_PurgeComm,
  696. SL_SetDCB,
  697. SL_SetCommTimeouts,
  698. };
  699. extern const HW_VTBL SerCardIoVTbl;
  700. const
  701. HW_VTBL IrVTbl = {
  702. SerInitIR,
  703. SL_PostInit,
  704. SerDeinit,
  705. SerOpen,
  706. SerClose,
  707. SL_GetInterruptType,
  708. SL_RxIntr,
  709. SL_TxIntrEx,
  710. SL_ModemIntr,
  711. SL_LineIntr,
  712. SL_GetRxBufferSize,
  713. SerPowerOff,
  714. SerPowerOn,
  715. SL_ClearDTR,
  716. SL_SetDTR,
  717. SL_ClearRTS,
  718. SL_SetRTS,
  719. SerEnableIR,
  720. SerDisableIR,
  721. SL_ClearBreak,
  722. SL_SetBreak,
  723. SL_XmitComChar,
  724. SL_GetStatus,
  725. SL_Reset,
  726. SL_GetModemStatus,
  727. SerGetCommProperties,
  728. SL_PurgeComm,
  729. SL_SetDCB,
  730. SL_SetCommTimeouts,
  731. };
  732. extern const HW_VTBL SerCardIrVTbl;
  733. const HWOBJ IoObj = {
  734. THREAD_AT_INIT,
  735. SYSINTR_SERIAL,
  736. (PHW_VTBL) &IoVTbl
  737. };
  738. const HWOBJ IrObj = {
  739. THREAD_AT_INIT,
  740. SYSINTR_IR,
  741. (PHW_VTBL) &IrVTbl
  742. };
  743. typedef HWOBJ const *PCHWOBJ;
  744. const PCHWOBJ HWObjects[] = {
  745. &IoObj,
  746. &IrObj
  747. };
  748. // GetSerialObj : The purpose of this function is to allow multiple PDDs to be
  749. // linked with a single MDD creating a multiport driver.  In such a driver, the
  750. // MDD must be able to determine the correct vtbl and associated parameters for
  751. // each PDD.  Immediately prior to calling HWInit, the MDD calls GetSerialObject
  752. // to get the correct function pointers and parameters.
  753. //
  754. PHWOBJ
  755. GetSerialObject(DWORD DeviceArrayIndex)
  756. {
  757. PHWOBJ pSerObj;
  758. RETAILMSG(DEBUGMODE,(TEXT("IRDA : GetSerialObjectrn")));
  759. IRDA = DeviceArrayIndex;
  760. // Now return this structure to the MDD.
  761. if ( DeviceArrayIndex == 0 )
  762. pSerObj = (PHWOBJ)(&IoObj);
  763. else
  764. pSerObj = (PHWOBJ)(&IrObj);
  765. return (pSerObj);
  766. }