templateSio.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:45k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* templateSio.c - template serial driver */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. /*
  4. TODO - Remove the template modification history and begin a new history
  5. starting with version 01a and growing the history upward with
  6. each revision.
  7. modification history
  8. --------------------
  9. 01o,30may02,dat  mismatch argument warning from diab
  10. 01n,05apr02,dat  Poll mode cannot make any callbacks
  11. 01m,08dec01,dat  compiler warnings
  12. 01l,24sep01,dat  Update for new IOCTL codes/callbacks, new adaptor type
  13.  macros
  14. 01k,07mar01,dat  36080, new driver components, renamed TEMPLATE_REG_READ/WRITE
  15.  to be TEMPLATE_READ/WRITE
  16. 01j,11may98,dat  change Open/Hup handling slightly. SPR 21198
  17. 01i,23sep97,dat  added TEMPLATE_REG_READ, TEMPLATE_REG_WRITE
  18. 01h,10sep97,dat  added opt declarations for SIO_HUP, SIO_OPEN
  19. 01g,10aug97,dat  fixed bugs in ver 01f
  20. 01f,01jul97,db  added ioctl commands used in modem control(SPR 7637,1037).
  21. 01e,16apr97,dat  fixed baud rate calc for SIO_BAUD_GET, SPR 8405.
  22. 01d,06mar97,dat  doc cleanup
  23. 01c,16dec96,dat  added templateOptSet() hardware options template
  24. 01b,16oct96,dat  added templateDevInit2(), and templateIntrMode variable.
  25. 01a,01aug95,ms   written.
  26. */
  27. /*
  28. .SH TODO
  29.  - Replace the documentation for this template driver with documentation
  30. for the driver being written.  
  31.  - Begin with an overview of the complete device.  Indicate if the new driver
  32. only implements a sub-section of the whole device or not.
  33.  - Describe all of the operating modes of the device, and indicate which
  34. ones this driver implements.
  35.  - Document the device initialization steps to be used in the BSP to create
  36. and initialize the device.  Document all the macros that
  37. can be used to customize the driver to a particular hardware environment.
  38.  - Document anything that will help the user to understand how this device
  39. works and interacts with this driver.
  40. .SH TEMPLATE OVERVIEW
  41. This is a template serial driver. It can be used as a starting point
  42. when writing new drivers for VxWorks version 5.4 or later.
  43. These drivers support new functionality not found in the older style
  44. serial drivers. First, they provide an interface for setting hardware
  45. options; e.g., the number of stop bits, data bits, parity, etc.
  46. Second, they provide an interface for polled communication which
  47. can be used to provided external mode debugging (i.e., ROM monitor
  48. style debugging) over a serial line. Currently only asynchronous mode
  49. drivers are supported.
  50. Throughout this file the word "template" is used in place of a real
  51. device name, which by convention uses the first letter of the
  52. manufacturers name followed by the part number. For example, the
  53. Zilog 8530 serial device would have a data structure called a
  54. Z8530_CHAN, rather than TEMPLATE_CHAN.
  55. .SH CALLBACKS
  56. Servicing a "transmitter ready" interrupt involves making a callback to a
  57. higher level library in order to get a character to transmit.
  58. By default, this driver installs dummy callback routines which do
  59. nothing. A higher layer library that wants to use this driver (e.g., ttyDrv)
  60. will install its own callback routines using the SIO_INSTALL_CALLBACK
  61. ioctl command. (See below).
  62. The prototype for the transmit data callback SIO_CALLBACK_GET_TX_CHAR is:
  63. .CS
  64.     int sioTxCharGet
  65. (
  66. void * arg,      /@ callback argument @/
  67. char * pChar      /@ ptr to data location @/
  68. )
  69. .CE
  70. This callback routine should fetch the next character to send and store it
  71. in the location pointed to by pChar.  It returns OK to indicate that a
  72. character is ready and should be sent.  It returns ERROR to indicate that
  73. no character was available and the transmitter can be placed in an idle state.
  74. Likewise, a receiver interrupt handler makes a callback to pass the
  75. character to the higher layer library.  It will be called by the driver
  76. for each character received.  This routine should capture the data and pass
  77. it along to other layers and eventually to the user.
  78. The prototype for the receive data callback SIO_CALLBACK_PUT_RCV_CHAR is:
  79. .CS
  80.     void sioRxCharPut
  81. (
  82. void * arg,      /@ callback argument @/
  83. char data      /@ data byte @/
  84. )
  85. .CE
  86. A new error handling callback has been added SIO_CALLBACK_ERROR. This driver
  87. should use this callback to inform the higher layer about error conditions.
  88. The prototype for this callback is:
  89. .CS
  90.     void sioErrorRtn
  91. (
  92. void * arg,      /@ callback argument @/
  93. int code,      /@ error code @/
  94. void * pData,      /@ opt dev specific data @/
  95. int dataSize         /@ opt size of data in bytes @/
  96. )
  97. .CE
  98. The available error codes for this callback are:
  99. .CS
  100.     SIO_ERROR_FRAMING  /@ (1) Framing error @/
  101.     SIO_ERROR_PARITY  /@ (2) Parity error @/
  102.     SIO_ERROR_OFLOW  /@ (3) data overflow @/
  103.     SIO_ERROR_UFLOW  /@ (4) data underflow @/
  104.     SIO_ERROR_CONNECT  /@ (5) connection made @/
  105.     SIO_ERROR_DISCONNECT /@ (6) connection lost @/
  106.     SIO_ERROR_NO_CLK  /@ (7) clock lost @/
  107.     SIO_ERROR_UNKNWN  /@ (8) other errors @/
  108. .CE
  109. For engineering purposes, the driver may return device specific data in
  110. the form of a data buffer. The argument pData is the location of the buffer
  111. and dataSize is its size, in bytes.  The data is not guaranteed to be static
  112. so it should be copied to a static buffer for safekeeping.
  113. .SH MODES
  114. Ideally the driver should support both polled and interrupt modes, and be
  115. capable of switching modes dynamically. However this is not required.
  116. VxWorks will be able to support a tty device on this driver even if
  117. the driver only supports interrupt mode.
  118. Polled mode is provided solely for WDB system mode usage.  Users can use
  119. the polled mode interface directly, but there is no clear reason for doing so.
  120. Normal access to SIO devices through ttyDrv only uses interrupt mode.
  121. For dynamically switchable drivers, be aware that the driver may be
  122. asked to switch modes in the middle of its input ISR. A driver's input ISR
  123. will look something like this:
  124.    inChar = *pDev->dr;          /@ read a char from data register @/
  125.    *pDev->cr = GOT_IT;          /@ acknowledge the interrupt @/
  126.    pDev->putRcvChar (...);      /@ give the character to the higher layer @/
  127. If this channel is used as a communication path to an external mode
  128. debug agent, and if the character received is a special "end of packet"
  129. character, then the agent's callback will lock interrupts, switch
  130. the device to polled mode, and use the device in polled mode for awhile.
  131. Later on the agent will unlock interrupts, switch the device back to
  132. interrupt mode, and return to the ISR.
  133. In particular, the callback can cause two mode switches, first to polled mode
  134. and then back to interrupt mode, before it returns.
  135. This may require careful ordering of the callback within the interrupt
  136. handler. For example, you may need to acknowledge the interrupt before
  137. invoking the callback.
  138. .SH USAGE
  139. The driver is typically called only by the BSP. The directly callable
  140. routines in this module are templateSioCreate(), templateSioDestroy().
  141. .SH BSP
  142. By convention all the BSP-specific serial initialization is performed in
  143. a file called sysSerial.c, which is #include'ed by sysLib.c.
  144. This driver can be customized by redefining the macros SYS_SIO_READ8 and
  145. SYS_SIO_WRITE8.  These two macros are used for all accesses to the
  146. actual chip.  If not defined, the source code will assume a simple memory
  147. mapped device using byte read/write access to all registers.
  148. The macros SYS_SIO_INT_CONNECT, SYS_SIO_INT_DISCONNECT, SYS_SIO_INT_ENABLE,
  149. and SYS_SIO_PROBE can be redefined by the BSP to perform basic low level
  150. routines with the same calling sequence as intConnect(), intConnect(),
  151. intEnable(), and vxMemProbe().
  152. .SH TESTING
  153. The interrupt driven interface can be tested in the usual way; VxWorks
  154. prints to the serial console when it comes up, so seeing the usual VxWorks
  155. output on power-up shows that the driver is basically working.
  156. The VxWorks portkit test can be used to perform a more strenuous test.
  157. The polled interface should be easy enough to verify - you should be able
  158. to call the channels SIO_MODE_SET ioctl to put it in polled mode.  Note
  159. that the usual print tools won't work with a serial channel in polled mode.
  160. Some agent has to perform a polling loop to handle input/output on a
  161. character by character basis.  It is not automatic.  The WDB agent
  162. performs its own polling loop when it switches the WDB serial line into
  163. polled mode. 
  164. The dynamic mode switching can be verified using the tornado tools.
  165. Reconfigure the agent to use the WDB_COMM_UDLP_SLIP communication path (see
  166. the Configuration section in the VxWorks run-time Guide for details).
  167. Start VxWorks, and connect the tgtsvr to the agent using the wdbserial
  168. backend (see the Tornado Users Guide for details).
  169. Start the wtxtcl shell as follows:
  170. % wtxtcl
  171. From the tcl prompt, attach to the target server:
  172. wtxtcl.ex> wtxToolAttach <tgtsvr name>
  173. Tell the agent to switch to external mode, and verify the reply is OK (0).
  174. wtxtcl.ex>wtxAgentModeSet 2
  175. 0
  176. Ask the agent to suspend the system (the request will reach the agent in
  177. interrupt mode, but the reply will be sent in polled mode):
  178. wtxtcl.ex>wtxContextSuspend 0 0
  179. 0
  180. At this point the target will be suspended. The console should apprear
  181. frozen (if the board has a console device), and you will not be able to
  182. "ping" the target's network interface.
  183. Resume the target:
  184. wtxtcl.ex>wtxContextResume 0 0
  185. 0
  186. The target should now be running again, so you should be able to type into
  187. the console (if the board has a console device) and ping the targets network
  188. interface from the host.
  189. .SH INCLUDE FILES:
  190. drv/sio/templateSio.h sioLib.h
  191. */
  192. #include "vxWorks.h"
  193. #include "intLib.h"
  194. #include "errnoLib.h"
  195. #include "iosLib.h"  /* For S_iosLib_DEVICE_NOT_FOUND */
  196. #include "cacheLib.h"
  197. #include "stdlib.h" /* malloc/free */
  198. #include "stdio.h" /* for printf */
  199. #include "vxLib.h" /* for vxMemProbe */
  200. #include "drv/sio/templateSio.h"
  201. /* device and channel structures */
  202. /* TODO - Define a driver specific extended SIO_CHAN structure */
  203. typedef struct
  204.     {
  205.     /* SIO_CHAN *MUST* be first */
  206.     SIO_CHAN sio; /* standard SIO_CHAN element */
  207.     UINT32 ioBase;
  208.     UINT32 vecBase;
  209.     UINT32 intLevel;
  210.     /* callbacks */
  211.     STATUS      (*getTxChar) (void *, char *);
  212.     void        (*putRcvChar) (void *, char);
  213.     void        (*errorRtn) (void *, int, void *, int);
  214.     void * getTxArg;
  215.     void * putRcvArg;
  216.     void * errorArg;
  217.     /* misc */
  218.     int intConnect; /* intConnect done flag */
  219.     int baudFreq; /* current baud rate */
  220.     int         mode;           /* current mode (interrupt or poll) */
  221.     int         clkFreq;       /* input clock frequency */
  222.     uint_t options; /* Hardware options */
  223.     int scanMode; /* keyboard mapping mode */
  224.     } TEMPLATE_CHAN;
  225. /* channel control register (write) definitions */
  226. /* TODO - These are just made up bit defines for a mythical device! */
  227. #define TEMPLATE_RESET_CHIP 0x07 /* reset all */
  228. #define TEMPLATE_RESET_TX 0x01 /* reset the transmitter */
  229. #define TEMPLATE_RESET_ERR 0x02 /* reset error condition */
  230. #define TEMPLATE_RESET_INT 0x04 /* acknoledge the interrupt */
  231. #define TEMPLATE_INT_ENABLE 0x08 /* enable interrupts */
  232. #define TEMPLATE_TX_ENABLE 0x10 /* enable interrupts */
  233. #define TEMPLATE_RX_ENABLE 0x20 /* enable interrupts */
  234. /* channel status register (read) definitions */
  235. #define TEMPLATE_CR_OKAY 0x00 /* no error conditions */
  236. #define TEMPLATE_CR_TX_READY 0x01 /* txmitter ready for another char */
  237. #define TEMPLATE_CR_TX_ERROR 0x04 /* txmitter int enable */
  238. #define TEMPLATE_CR_RX_AVAIL 0x10 /* character has arrived */
  239. #define TEMPLATE_CR_RX_ERROR 0x40 /* receiver error */
  240. /* channel modem status register definitions */
  241. #define TEMPLATE_MSR_RTS 0x1 /* RTS signal asserted */
  242. #define TEMPLATE_MSR_DTR 0x2 /* DTR signal asserted */
  243. #define TEMPLATE_MSR_DSR 0x4 /* DSR signal asserted */
  244. #define TEMPLATE_MSR_CTS 0x8 /* CTS signal asserted */
  245. #define TEMPLATE_MSR_CD 0x10 /* CD signal asserted */
  246. /* input and output signals */
  247. #define TEMPLATE_ISIG_MASK (SIO_MODEM_CTS|SIO_MODEM_DSR|SIO_MODEM_CD)
  248. #define TEMPLATE_OSIG_MASK (SIO_MODEM_RTS|SIO_MODEM_DTR)
  249. /* channel modem control register definitions */
  250. #define TEMPLATE_MC_RTS 0x1 /* enable RTS */
  251. #define TEMPLATE_MC_DTR 0x2 /* enable DTR */
  252. #define TEMPLATE_BAUD_MIN 75
  253. #define TEMPLATE_BAUD_MAX 38400
  254. /* Hardware abstraction macros */
  255. /* Macros from BSP */
  256. #define SYS_SIO_READ8(addr, pData) 
  257. (*pData = *(UINT8 *)(addr))
  258. #define SYS_SIO_WRITE8(addr, data) 
  259. (*(UINT8 *)addr = data)
  260. #define SYS_SIO_INT_CONNECT(vec, rtn, arg) 
  261. intConnect ((VOIDFUNCPTR *)vec, (VOIDFUNCPTR)rtn, (int)arg)
  262. #define SYS_SIO_INT_DISCONNECT(vec, rtn, arg) 
  263. intConnect ((VOIDFUNCPTR *)vec, NULL, 0)
  264. #define SYS_SIO_INT_ENABLE(level) 
  265. intEnable (level)
  266. #define SYS_SIO_PROBE(addr, mode, size, pData) 
  267. vxMemProbe (addr, mode, size, pData)
  268. /* #define CACHE_PIPE_FLUSH() */
  269. /* Local driver abstractions, following bus/adaptor model */
  270. #define TEMPLATE_SIO_READ8(pChan, reg, result) 
  271. SYS_SIO_READ8(((pChan->ioBase) + reg),result)
  272. #define TEMPLATE_SIO_WRITE8(pChan, reg, data) 
  273. SYS_SIO_WRITE8(((pChan->ioBase) + reg),data)
  274. #define TEMPLATE_SIO_INT_CONNECT(pChan, vec, rtn, arg) 
  275. do { 
  276. SYS_SIO_INT_CONNECT((pChan->vecBase) + vec, rtn, arg); 
  277. SYS_SIO_INT_ENABLE(pChan->intLevel); 
  278. } while (0)
  279. #define TEMPLATE_INT_DISCONNECT(pChan, vec, rtn, arg) 
  280. SYS_SIO_INT_DISCONNECT(((pChan)->vecBase + vec), rtn, arg)
  281. /* Do NOT disable interrupt level for disconnect */
  282. #define TEMPLATE_PROBE(pChan, offset, dir, size, ptr) 
  283. SYS_SIO_PROBE((char *)((pChan)->ioBase + offset), dir, size, ptr)
  284. #define TEMPLATE_PIPE_FLUSH(pChan) 
  285. CACHE_PIPE_FLUSH()
  286. /* forward static declarations */
  287. LOCAL int templateTxStartup (SIO_CHAN * pSioChan);
  288. LOCAL int templateCallbackInstall (SIO_CHAN *pSioChan, int callbackType,
  289. STATUS (*callback)(void *,...), void *callbackArg);
  290. LOCAL int templatePollOutput (SIO_CHAN *pSioChan, char outChar);
  291. LOCAL int templatePollInput (SIO_CHAN *pSioChan, char *thisChar);
  292. LOCAL int templateIoctl (SIO_CHAN *pSioChan, int request, void *arg);
  293. LOCAL STATUS dummyTxCallback (void *, char *);
  294. LOCAL void dummyRxCallback (void *, char);
  295. LOCAL void dummyErrCallback (void *, int, void *, int);
  296. LOCAL void templateSioIntTx (TEMPLATE_CHAN * pChan);
  297. LOCAL void templateSioIntRcv (TEMPLATE_CHAN * pChan);
  298. LOCAL void templateSioIntErr (TEMPLATE_CHAN * pChan);
  299. LOCAL STATUS templateProbe (TEMPLATE_CHAN *);
  300. LOCAL STATUS templateVerify (TEMPLATE_CHAN *);
  301. LOCAL int templateMstatGet (TEMPLATE_CHAN *);
  302. LOCAL int templateMstatSetClr (TEMPLATE_CHAN *, UINT bits, BOOL setFlag);
  303. /* local variables */
  304. LOCAL SIO_DRV_FUNCS templateSioDrvFuncs =
  305.     {
  306.     templateIoctl,
  307.     templateTxStartup,
  308.     templateCallbackInstall,
  309.     templatePollInput,
  310.     templatePollOutput
  311.     };
  312. /******************************************************************************
  313. *
  314. * templateSioCreate - create a TEMPLATE_CHAN instance
  315. *
  316. * This routine initializes the driver
  317. * function pointers and then resets the chip to a quiescent state.
  318. *
  319. * RETURNS: N/A
  320. */
  321. SIO_CHAN * templateSioCreate
  322.     (
  323.     UINT32 ioBase,
  324.     UINT32 vecBase,
  325.     UINT32 level,
  326.     UINT32 clkFreq
  327.     )
  328.     {
  329.     TEMPLATE_CHAN * pChan;
  330.     pChan = (TEMPLATE_CHAN *) malloc (sizeof (TEMPLATE_CHAN));
  331.     if (pChan != NULL)
  332. {
  333. pChan->sio.pDrvFuncs = &templateSioDrvFuncs;
  334. pChan->ioBase = ioBase;
  335. pChan->vecBase = vecBase;
  336. pChan->intLevel = level;
  337. pChan->clkFreq = clkFreq;
  338. /* install dummy driver callbacks */
  339. pChan->getTxChar    = dummyTxCallback;
  340. pChan->putRcvChar   = dummyRxCallback;
  341. pChan->errorRtn     = dummyErrCallback;
  342. pChan->intConnect    = FALSE; /* int's not connected yet */
  343. if (templateProbe (pChan) == OK)
  344.     {
  345.     TEMPLATE_SIO_WRITE8(pChan,
  346. TEMPLATE_CSR_ID, TEMPLATE_RESET_CHIP);
  347.     /* setting polled mode is one way to make the device quiet */
  348.     templateIoctl (&pChan->sio, SIO_MODE_SET, (void *)SIO_MODE_POLL);
  349.     }
  350. else
  351.     {
  352.     /* Whoops, device is not there! */
  353.     free ((char *)pChan);
  354.     errnoSet (S_iosLib_DEVICE_NOT_FOUND);
  355.     return NULL;
  356.     }
  357. }
  358.     return &pChan->sio;
  359.     }
  360. /******************************************************************************
  361. *
  362. * templateSioDestroy - destroy a TEMPLATE_CHAN instance
  363. *
  364. * This function is used to destroy an instance of a TEMPLATE_CHAN object.
  365. *
  366. * RETURNS: OK upon success, or ERROR on failure or if the object is not a
  367. * valid TEMPLATE_CHAN object.
  368. */
  369. STATUS templateSioDestroy
  370.     (
  371.     SIO_CHAN * pSioChan
  372.     )
  373.     {
  374.     TEMPLATE_CHAN * pChan = (TEMPLATE_CHAN *)pSioChan;
  375.     /*
  376.      * Verify that it is a valid TEMPLATE_CHAN device, before doing
  377.      * anything.
  378.      */
  379.     if (templateVerify(pChan) == OK)
  380. {
  381. if (pChan->intConnect == TRUE)
  382.     {
  383.     TEMPLATE_INT_DISCONNECT(pChan,TEMPLATE_RXINT_ID,
  384.     templateSioIntRcv, (void *)pChan);
  385.     TEMPLATE_INT_DISCONNECT(pChan, TEMPLATE_TXINT_ID,
  386.     templateSioIntTx, (void *)pChan);
  387.     TEMPLATE_INT_DISCONNECT(pChan, TEMPLATE_ERRINT_ID,
  388.     templateSioIntErr, (void *)pChan);
  389.     }
  390. free (pChan);
  391. return OK;
  392. }
  393.     return ERROR;
  394.     }
  395. /******************************************************************************
  396. *
  397. * templateSioIntRcv - handle a channel's receive-character interrupt
  398. *
  399. * RETURNS: N/A
  400. */ 
  401. LOCAL void templateSioIntRcv
  402.     (
  403.     TEMPLATE_CHAN * pChan /* channel generating the interrupt */
  404.     )
  405.     {
  406.     char   inChar;  /* rcvr data */
  407.     char   crData = 0; /* rcvr status */
  408.     STATUS status = OK;
  409.     /*
  410.      * TODO - 
  411.      *
  412.      * Get status and data from the device. Determine if valid data is ready
  413.      * or not.
  414.      *
  415.      * For PCI devices, do an immediate return if device is not asserting
  416.      * an interrupt.
  417.      */
  418.     TEMPLATE_SIO_READ8(pChan, TEMPLATE_CSR_ID, &crData);
  419.     /* Check for error conditions */
  420.     if (crData & TEMPLATE_CR_OKAY)
  421. {
  422. TEMPLATE_SIO_READ8(pChan, TEMPLATE_DATA_ID, &inChar);
  423. #if 0 /* Keyboard emulation code */
  424. /*
  425.  * TODO - For a keyboard type device we would map the raw scan code
  426.  * to ASCII, or other mapping.  Do that here.
  427.  */
  428. if (pChan->scanMode == SIO_KYBD_MODE_ASCII)
  429.     inChar = templateAsciiTbl[(UINT8)inChar];
  430. #endif
  431. }
  432.     else
  433. {
  434. /*
  435.  * TODO - Determine precise error condition and perform
  436.  * recovery actions.
  437.  */
  438. status = ERROR;
  439. }
  440.     /*
  441.      * TODO -  Typically, acknowledge the interrupt as soon as possible.
  442.      * Usually before passing data or error conditions upstream.
  443.      */
  444.     TEMPLATE_SIO_WRITE8(pChan,
  445. TEMPLATE_CSR_ID, TEMPLATE_RESET_INT); /* ack interrupt*/
  446.     if (status == ERROR)
  447. {
  448. /* send error notification upstream */
  449. (*pChan->errorRtn) (pChan->errorArg, SIO_ERROR_UNKNWN, NULL, 0);
  450. }
  451.     else
  452. {
  453. /* send data character upstream */
  454. (*pChan->putRcvChar) (pChan->putRcvArg, inChar);
  455. }
  456.     }
  457. /******************************************************************************
  458. *
  459. * templateSioIntTx - handle a channels transmitter-ready interrupt
  460. *
  461. * RETURNS: N/A
  462. */ 
  463. LOCAL void templateSioIntTx
  464.     (
  465.     TEMPLATE_CHAN * pChan /* channel generating the interrupt */
  466.     )
  467.     {
  468.     char outChar;
  469.     char crData = 0;
  470.     BOOL txReady = TRUE;
  471.     int errorCode = SIO_ERROR_NONE;
  472.     /*
  473.      * TODO - Check the Tx status
  474.      *
  475.      * For PCI devices, do an immediate return if device is not asserting
  476.      * an interrupt.
  477.      */
  478.     TEMPLATE_PIPE_FLUSH(pChan);
  479.     TEMPLATE_SIO_READ8(pChan, TEMPLATE_CSR_ID, &crData);
  480.     /* TODO - Check for error conditions */
  481.     if (crData & TEMPLATE_CR_TX_ERROR)
  482. {
  483. /*
  484.  * TODO - Typically you should determine the precise error condition
  485.  * and perform all recovery operations here.
  486.  */
  487. TEMPLATE_SIO_WRITE8 (pChan, TEMPLATE_CSR_ID, TEMPLATE_RESET_TX);
  488. errorCode = SIO_ERROR_UNKNWN;
  489. txReady = TRUE; /* set to false if xmitter is not ready now */
  490. }
  491.     /*
  492.      * If transmitter is okay and ready to send, lets see if there is a
  493.      * data character ready to be sent.
  494.      *
  495.      * If there's a character to transmit then write it out, else reset (idle)
  496.      * the transmitter. For chips with output FIFO's it is more efficient
  497.      * to fill the entire FIFO here.
  498.      */
  499.     if (txReady)
  500. {
  501. if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
  502.     {
  503.     /* TODO - Output data to device.  */
  504.     TEMPLATE_SIO_WRITE8(pChan, TEMPLATE_DATA_ID, outChar);
  505.     /*
  506.      * TODO - If a device error occurs at this point, then
  507.      * isolate the precise error type and try to recover.
  508.      */
  509.     }
  510. else
  511.     {
  512.     /*
  513.      * TODO - There is no more data to send.
  514.      *
  515.      * Put XMTR in an idle state. Higher layer
  516.      * will call TxStartup entry to resume xmit operations.
  517.      */
  518.     TEMPLATE_SIO_WRITE8(pChan, TEMPLATE_CSR_ID, TEMPLATE_RESET_TX);
  519.     }
  520. }
  521.     /*
  522.      * TODO - If needed, you should acknowledge or reset the interrupt source
  523.      * as soon as possible, usually before passing any error conditions
  524.      * upstream.
  525.      */
  526.     TEMPLATE_SIO_WRITE8(pChan, TEMPLATE_CSR_ID, TEMPLATE_RESET_INT);
  527.     /* Pass any errorCodes upstream.  */
  528.     if (errorCode != SIO_ERROR_NONE)
  529. {
  530. (*pChan->errorRtn) (pChan->errorArg, errorCode, NULL, 0);
  531. }
  532.     }
  533. /******************************************************************************
  534. *
  535. * templateSioIntErr - handle a channels error interrupt
  536. *
  537. * RETURNS: N/A
  538. */ 
  539. LOCAL void templateSioIntErr
  540.     (
  541.     TEMPLATE_CHAN * pChan /* channel generating the interrupt */
  542.     )
  543.     {
  544.     int errorCode = SIO_ERROR_NONE;
  545.     char controlReg;
  546.     TEMPLATE_PIPE_FLUSH(pChan);
  547.     TEMPLATE_SIO_READ8 (pChan, TEMPLATE_CSR_ID, &controlReg);
  548.     /*
  549.      * TODO - Determine the precise error condition and perform recovery
  550.      * operations.
  551.      *
  552.      * For PCI devices, do an immediate return if device is not asserting
  553.      * an interrupt.
  554.      */
  555.     /*
  556.      * TODO - If needed, you should acknowledge or reset the interrupt source
  557.      * as soon as possible, usually before passing any error conditions
  558.      * upstream.
  559.      */
  560.     TEMPLATE_SIO_WRITE8(pChan, TEMPLATE_CSR_ID, TEMPLATE_RESET_INT);
  561.     if (errorCode != SIO_ERROR_NONE)
  562. (*pChan->errorRtn) (pChan->errorArg, errorCode, NULL, 0);
  563.     }
  564. /******************************************************************************
  565. *
  566. * templateTxStartup - start the interrupt transmitter
  567. *
  568. * This routine exits to inform the device to start transmitting data again.
  569. * The actual data will be obtained by calling the TxCharGet callback routine.
  570. *
  571. * This routine is usually just the same as the tx interrupt routine.  This
  572. * routine runs at task level context and does not have to be interrupt safe.
  573. *
  574. * RETURNS: OK on success, ENOSYS if the device is polled-only, or
  575. * EIO on hardware error.
  576. */
  577. LOCAL int templateTxStartup
  578.     (
  579.     SIO_CHAN * pSioChan                 /* channel to start */
  580.     )
  581.     {
  582.     TEMPLATE_CHAN * pChan = (TEMPLATE_CHAN *)pSioChan;
  583.     /* This routine should only be called while in interrupt mode */
  584.     if (pChan->mode == SIO_MODE_INT)
  585.         {
  586.         if (pChan->options & CLOCAL)
  587.             {
  588.             /* TODO - No modem control - start immediately */
  589.             }
  590.         else
  591.             {
  592.     /*
  593.      * TODO - Modem controls are active. 
  594.      *
  595.      * If CTS is high, we can start immediately so just enable
  596.      * the TX interrupt.
  597.      *
  598.      * If CTS is low, then we cannot send now.  The driver
  599.      * should be set up to generate a TX interrupt when the CTS
  600.      * line returns to the active state.
  601.      */
  602.             }
  603.         /*
  604.  * TODO - Enable the correct interrupts. A TX interrupt should either
  605.  * occur immediately, or later when CTS becomes active.  That will start
  606.  * the flow of data.
  607.  *
  608.  * There are two usual methods here.  The first is to just enable
  609.  * TX interrupts, which should cause an immediate TX interrupt, which
  610.  * will begin fetching and sending characters.
  611.  *
  612.  * The second method is to call the getTxChara callback here, put
  613.  * the data to the transmitter directly, and then to enable TX
  614.  * interrupts to fetch and send additional characters.
  615.  */
  616. TEMPLATE_SIO_WRITE8(pChan, TEMPLATE_CSR_ID, TEMPLATE_TX_ENABLE);
  617.         }
  618.     else
  619. return ENOSYS;   /* Not valid for polled mode operation */
  620.     return (OK);
  621.     }
  622. /******************************************************************************
  623. *
  624. * templateCallbackInstall - install ISR callbacks to get/put chars
  625. *
  626. * This driver allows interrupt callbacks for transmitting characters
  627. * and receiving characters. In general, drivers may support other
  628. * types of callbacks too.
  629. *
  630. * RETURNS: OK on success, or ENOSYS for an unsupported callback type.
  631. */ 
  632. LOCAL int templateCallbackInstall
  633.     (
  634.     SIO_CHAN * pSioChan,               /* channel */
  635.     int callbackType,           /* type of callback */
  636.     STATUS (*callback)(void *,...),  /* callback */
  637.     void *      callbackArg             /* parameter to callback */
  638.     )
  639.     {
  640.     TEMPLATE_CHAN * pChan = (TEMPLATE_CHAN *)pSioChan;
  641.     switch (callbackType)
  642. {
  643. case SIO_CALLBACK_GET_TX_CHAR:
  644.     pChan->getTxChar = (STATUS (*)(void *, char *))callback;
  645.     pChan->getTxArg = callbackArg;
  646.     return (OK);
  647. case SIO_CALLBACK_PUT_RCV_CHAR:
  648.     pChan->putRcvChar = (void (*)(void *, char))callback;
  649.     pChan->putRcvArg = callbackArg;
  650.     return (OK);
  651. case SIO_CALLBACK_ERROR:
  652.     pChan->errorRtn = (void (*)(void *, int, void *, int))callback;
  653.     pChan->errorArg = callbackArg;
  654.     return (OK);
  655. default:
  656.     return (ENOSYS);
  657. }
  658.     }
  659. /*******************************************************************************
  660. *
  661. * templatePollOutput - output a character in polled mode
  662. *
  663. * Polled mode operation takes place without any kernel or other OS
  664. * services available.  Use extreme care to insure that this code does not
  665. * call any kernel services.  Polled mode is only for WDB system mode use.
  666. * Kernel services, semaphores, tasks, etc, are not available during WDB
  667. * system mode.
  668. *
  669. * RETURNS: OK if a character arrived, EIO on device error, EAGAIN
  670. * if the output buffer if full. ENOSYS if the device is
  671. * interrupt-only.
  672. */
  673. LOCAL int templatePollOutput
  674.     (
  675.     SIO_CHAN * pSioChan,
  676.     char outChar
  677.     )
  678.     {
  679.     TEMPLATE_CHAN * pChan = (TEMPLATE_CHAN *)pSioChan;
  680.     UINT8 status;
  681.     /* is the transmitter ready to accept a character? */
  682.     TEMPLATE_PIPE_FLUSH(pChan);
  683.     TEMPLATE_SIO_READ8(pChan, TEMPLATE_CSR_ID, &status);
  684.     /* TODO - determine if transmitter is ready */
  685.     if ((status & TEMPLATE_CR_TX_READY) == 0x00)
  686. {
  687. /* device is busy, try again later */
  688. return (EAGAIN);
  689. }
  690.     /* TODO - Check for TX errors */
  691.     if (status & TEMPLATE_CR_TX_ERROR)
  692. {
  693. /* TODO - decode specific error condition and handle it */
  694. /* Do not make error callback, just return EIO */
  695. return EIO;
  696. }
  697.     else
  698. {
  699. /* TODO - transmit the character */
  700. TEMPLATE_SIO_WRITE8(pChan, TEMPLATE_DATA_ID, outChar);
  701. }
  702.     return (OK);
  703.     }
  704. /******************************************************************************
  705. *
  706. * templatePollInput - poll the device for input
  707. *
  708. * Polled mode operation takes place without any kernel or other OS
  709. * services available.  Use extreme care to insure that this code does not
  710. * call any kernel services.  Polled mode is only for WDB system mode use.
  711. * Kernel services, semaphores, tasks, etc, are not available during WDB
  712. * system mode.
  713. *
  714. * RETURNS: OK if a character arrived, EIO on device error, EAGAIN
  715. * if the input buffer if empty, ENOSYS if the device is
  716. * interrupt-only.
  717. */
  718. LOCAL int templatePollInput
  719.     (
  720.     SIO_CHAN * pSioChan,
  721.     char * thisChar
  722.     )
  723.     {
  724.     TEMPLATE_CHAN * pChan = (TEMPLATE_CHAN *)pSioChan;
  725.     UINT8 status;
  726.     /* Read RX device status */
  727.     TEMPLATE_PIPE_FLUSH(pChan);
  728.     TEMPLATE_SIO_READ8(pChan, TEMPLATE_CSR_ID, &status);
  729.     /* TODO - Check if receive data is available */
  730.     if ((status & TEMPLATE_CR_RX_AVAIL) == 0x00)
  731. {
  732. return EAGAIN; /* no input available at this time */
  733. }
  734.     /* TODO - Check for receive error conditions */
  735.     if (status & TEMPLATE_CR_RX_ERROR)
  736. {
  737. /* TODO - Decode and handle the specific error condition */
  738. /* Do NOT call the error callback routine, just return EIO */
  739. return EIO;
  740. }
  741.     /* TODO - read character, store it, and return OK  */
  742.     TEMPLATE_SIO_READ8(pChan, TEMPLATE_DATA_ID, thisChar);
  743.     return (OK);
  744.     }
  745. /******************************************************************************
  746. *
  747. * templateModeSet - toggle between interrupt and polled mode
  748. *
  749. * RETURNS: OK on success, EIO on unsupported mode.
  750. */
  751. LOCAL int templateModeSet
  752.     (
  753.     TEMPLATE_CHAN * pChan, /* channel */
  754.     uint_t     newMode           /* new mode */
  755.     )
  756.     {
  757.     UINT8 temp;
  758.     if ((newMode != SIO_MODE_POLL) && (newMode != SIO_MODE_INT))
  759. return (EIO);
  760.     TEMPLATE_PIPE_FLUSH(pChan);
  761.     if (pChan->mode == SIO_MODE_INT)
  762. {
  763. /* TODO - switch device to interrupt mode */
  764. if (pChan->intConnect == FALSE)
  765.     {
  766.     TEMPLATE_SIO_INT_CONNECT(pChan,TEMPLATE_RXINT_ID,
  767.     templateSioIntRcv, (void *)pChan);
  768.     TEMPLATE_SIO_INT_CONNECT(pChan, TEMPLATE_TXINT_ID,
  769.     templateSioIntTx, (void *)pChan);
  770.     TEMPLATE_SIO_INT_CONNECT(pChan, TEMPLATE_ERRINT_ID,
  771.     templateSioIntErr, (void *)pChan);
  772.     pChan->intConnect = TRUE;
  773.     }
  774. TEMPLATE_SIO_READ8(pChan, TEMPLATE_CSR_ID, &temp);
  775. temp |= TEMPLATE_INT_ENABLE;
  776. TEMPLATE_SIO_WRITE8(pChan, TEMPLATE_CSR_ID, temp);
  777. }
  778.     else
  779. {
  780. /* TODO - switch device to polled mode */
  781. TEMPLATE_SIO_READ8(pChan, TEMPLATE_CSR_ID, &temp);
  782. temp &= ~TEMPLATE_INT_ENABLE;
  783. TEMPLATE_SIO_WRITE8(pChan, TEMPLATE_CSR_ID, temp);
  784. }
  785.     /* activate  the new mode */
  786.     pChan->mode = newMode;
  787.     return (OK);
  788.     }
  789. /*******************************************************************************
  790. *
  791. * templateHup - hang up the modem control lines 
  792. *
  793. * Resets the RTS and DTR signals.
  794. *
  795. * RETURNS: OK always.
  796. */
  797. LOCAL STATUS templateHup
  798.     (
  799.     TEMPLATE_CHAN * pChan  /* pointer to channel */
  800.     )
  801.     {
  802.     /*
  803.      * TODO - Use global intLock if lockout time will be very short. If not,
  804.      * use a device specific lockout that will not damage overall system
  805.      * latency.
  806.      */
  807.     templateMstatSetClr (pChan,(SIO_MODEM_RTS|SIO_MODEM_DTR), FALSE);
  808.     return (OK);
  809.     }    
  810. /*******************************************************************************
  811. *
  812. * templateOpen - Set the modem control lines 
  813. *
  814. * Set the modem control lines(RTS, DTR) TRUE if not already set.  
  815. *
  816. * RETURNS: OK
  817. */
  818. LOCAL STATUS templateOpen
  819.     (
  820.     TEMPLATE_CHAN * pChan  /* pointer to channel */
  821.     )
  822.     {
  823.     /*
  824.      * TODO - Use global intLock if lockout time will be very short. If not,
  825.      * use a device specific lockout that will not damage overall system
  826.      * latency.
  827.      */
  828.     templateMstatSetClr (pChan, (SIO_MODEM_RTS|SIO_MODEM_DTR), TRUE);
  829.     return (OK);
  830.     }
  831. /******************************************************************************
  832. *
  833. * templateOptSet - set hardware options
  834. *
  835. * This routine sets up the hardware according to the specified option
  836. * argument.  If the hardware cannot support a particular option value, then
  837. * it should ignore that portion of the request.
  838. *
  839. * RETURNS: OK upon success, or EIO for invalid arguments.
  840. */
  841. LOCAL int templateOptSet
  842.     (
  843.     TEMPLATE_CHAN * pChan, /* channel */
  844.     uint_t     newOpts           /* new options */
  845.     )
  846.     {
  847.     int dataBits = 8;
  848.     int stopBits = 1;
  849.     BOOL hdweFlowCtrl=TRUE;
  850.     BOOL rcvrEnable = TRUE;
  851.     int  lvl;
  852.     if (pChan == NULL || newOpts & 0xffffff00)
  853. return EIO;
  854.     /* do nothing if options already set */
  855.     if (pChan->options == newOpts)
  856. return OK;
  857.     /* ignore requests for unsupported options */
  858.     /* decode individual request elements */
  859.     switch (newOpts & CSIZE)
  860. {
  861. case CS5:
  862.     dataBits = 5; break;
  863. case CS6:
  864.     dataBits = 6; break;
  865. case CS7:
  866.     dataBits = 7; break;
  867. default:
  868. case CS8:
  869.     dataBits = 8; break;
  870. }
  871.     if (newOpts & STOPB)
  872. stopBits = 2;
  873.     else
  874. stopBits = 1;
  875.     switch (newOpts & (PARENB|PARODD))
  876. {
  877. case PARENB|PARODD:
  878.     /* enable odd parity */
  879.     break;
  880. case PARENB:
  881.     /* enable even parity */
  882.     break;
  883. case PARODD:
  884.     /* invalid mode, not normally used. */
  885.     break;
  886. default:
  887. case 0:
  888.     /* no parity */; break;
  889. }
  890.     if (newOpts & CLOCAL)
  891. {
  892. /* clocal disables hardware flow control */
  893. hdweFlowCtrl = FALSE;
  894. }
  895.     if ((newOpts & CREAD) == 0)
  896. rcvrEnable = FALSE;
  897.     lvl = intLock ();
  898.     /*
  899.      * TODO - Reset the device according to dataBits, stopBits, hdweFlowCtrl,
  900.      * rcvrEnable, and parity selections.
  901.      */
  902.     
  903.     intUnlock (lvl);
  904.     /*
  905.      * TODO - Be sure that pChan->options reflects the actual
  906.      * hardware settings.  If 5 data bits were requested, but unsupported,
  907.      * then be sure pChan->options reflects the actual number of data bits
  908.      * currently selected.
  909.      */
  910.     pChan->options = newOpts;
  911.     return (OK);
  912.     }
  913. /*******************************************************************************
  914. *
  915. * templateIoctl - special device control
  916. *
  917. * This routine handles the IOCTL messages from the user. It supports commands 
  918. * to get/set baud rate, mode(INT,POLL), hardware options(parity, number of 
  919. * data bits) and modem control(RTS/CTS and DTR/DSR handshakes).
  920. * The ioctl commands SIO_HUP and SIO_OPEN are used to implement the HUPCL(hang
  921. * up on last close) function.
  922. *
  923. * As on a UNIX system, requesting a baud rate of zero is translated into
  924. * a hangup request.  The DTR and RTS lines are dropped.  This should cause
  925. * a connected modem to drop the connection.  The SIO_HUP command will only
  926. * hangup if the HUPCL option is active.  The SIO_OPEN function will raise
  927. * DTR and RTS lines whenever it is called. Use the BAUD_RATE=0 function
  928. * to hangup when HUPCL is not active.
  929. *
  930. * The CLOCAL option will disable hardware flow control.  When selected,
  931. * hardware flow control is not used.  When not selected hardware flow control
  932. * is based on the RTS/CTS signals.  CTS is the clear to send input
  933. * from the other end.  It must be true for this end to begin sending new
  934. * characters.  In most drivers, the RTS signal will be assumed to be connected
  935. * to the opposite end's CTS signal and can be used to control output from
  936. * the other end.  Raising RTS asserts CTS at the other end and the other end
  937. * can send data.  Lowering RTS de-asserts CTS and the other end will stop
  938. * sending data. (This is non-EIA defined use of RTS).
  939. *
  940. * RETURNS: OK on success, ENOSYS on unsupported request, EIO on failed
  941. * request.
  942. */
  943. LOCAL int templateIoctl
  944.     (
  945.     SIO_CHAN * pSioChan, /* device to control */
  946.     int request, /* request code */
  947.     void * someArg /* some argument */
  948.     )
  949.     {
  950.     TEMPLATE_CHAN *pChan = (TEMPLATE_CHAN *) pSioChan;
  951.     int     oldLevel; /* current interrupt level mask */
  952.     int     baudConstant;
  953.     int     arg = (int)someArg;
  954.     TEMPLATE_PIPE_FLUSH(pChan);
  955.     switch (request)
  956. {
  957. case SIO_BAUD_SET:
  958.     /*
  959.      * like unix, a baud request for 0 is really a request to
  960.      * hangup.
  961.      */
  962.     if (arg == 0)
  963. return (templateHup (pChan));
  964.     /*
  965.      * Set the baud rate. Return EIO for an invalid baud rate, or
  966.      * OK on success.
  967.      */
  968.     if (arg < TEMPLATE_BAUD_MIN || arg > TEMPLATE_BAUD_MAX)
  969.         {
  970. return (EIO);
  971.         }
  972.     /* TODO - Calculate the baud rate constant for the new baud rate */
  973.     baudConstant = pChan->clkFreq / arg / 16; /* DUMMY CODE */
  974.     /* disable interrupts during chip access */
  975.     oldLevel = intLock ();
  976.     TEMPLATE_SIO_WRITE8(pChan, TEMPLATE_BAUD_ID, baudConstant);
  977.     intUnlock (oldLevel);
  978.     pChan->baudFreq = arg;
  979.     return (OK);
  980. case SIO_BAUD_GET:
  981.     *(int *)someArg = pChan->baudFreq;
  982.     return (OK);
  983. case SIO_MODE_SET:
  984.     /*
  985.      * Set the mode (e.g., to interrupt or polled). Return OK
  986.      * or EIO for an unknown or unsupported mode.
  987.      */
  988.     return (templateModeSet (pChan, arg));
  989. case SIO_MODE_GET:
  990.     /* Get the current mode and return OK.  */
  991.     *(int *)someArg = pChan->mode;
  992.     return (OK);
  993. case SIO_AVAIL_MODES_GET:
  994.     /* TODO - set the available modes and return OK.  */
  995.     *(int *)someArg = SIO_MODE_INT | SIO_MODE_POLL;
  996.     return (OK);
  997. case SIO_HW_OPTS_SET:
  998.     /*
  999.      * Optional command to set the hardware options (as defined
  1000.      * in sioLib.h).
  1001.      * Return OK, or ENOSYS if this command is not implemented.
  1002.      * Note: several hardware options are specified at once.
  1003.      * This routine should set as many as it can and then return
  1004.      * OK. The SIO_HW_OPTS_GET is used to find out which options
  1005.      * were actually set.
  1006.      */
  1007.     return (templateOptSet (pChan, arg));
  1008. case SIO_HW_OPTS_GET:
  1009.     /*
  1010.      * Optional command to get the hardware options (as defined
  1011.      * in sioLib.h). Return OK or ENOSYS if this command is not
  1012.      * implemented.  Note: if this command is unimplemented, it
  1013.      * will be assumed that the driver options are CREAD | CS8
  1014.      * (e.g., eight data bits, one stop bit, no parity, ints enabled).
  1015.      */
  1016.     *(int *)someArg = pChan->options;
  1017.     return (OK);
  1018.         case SIO_HUP:
  1019.             /* check if hupcl option is enabled */
  1020.             if (pChan->options & HUPCL) 
  1021.                 return (templateHup (pChan));
  1022.             return (OK);
  1023.         case SIO_OPEN:
  1024.     return (templateOpen (pChan)); /* always open */
  1025. #if 1 /* TODO - optional modem control line support */
  1026. /*
  1027.  * These new ioctl commands are for monitoring and setting the
  1028.  * state of the modem control lines under user control. The
  1029.  * return values from these calls inform the user about which
  1030.  * control lines are inputs and which are outputs. Basically
  1031.  * this lets the user know if the device is wired for DTE or
  1032.  * DCE configuration.  It also informs the user if any signals
  1033.  * are missing altogether.
  1034.  */
  1035. case SIO_MSTAT_GET:
  1036.     return templateMstatGet(pChan);
  1037. case SIO_MCTRL_BITS_SET:
  1038.     return templateMstatSetClr (pChan, arg, TRUE);
  1039. case SIO_MCTRL_BITS_CLR:
  1040.     return templateMstatSetClr (pChan, arg, FALSE);
  1041. /*
  1042.  * The ISIG and OSIG masks tell the user which signals are actually
  1043.  * outputs and which aren't. In our case here, we assume the device
  1044.  * is DTE mapped with DTR and RTS as outputs. DSR and CTS as inputs.
  1045.  * This template driver doesn't support RI.
  1046.  */
  1047. case SIO_MCTRL_OSIG_MASK:
  1048.     *(int *)someArg = TEMPLATE_OSIG_MASK;
  1049.     break;
  1050. case SIO_MCTRL_ISIG_MASK:
  1051.     *(int *)someArg = TEMPLATE_ISIG_MASK;
  1052.     break;
  1053. #endif /* optional Modem control line support */
  1054. #if 1 /* TODO - optional keyboard scan code support */
  1055. /*
  1056.  * The following new ioctl commands are meant only for keyboard
  1057.  * input devices to use.  These allow the user to specify and
  1058.  * examine the type of keyboard character mapping to use.  The
  1059.  * possible types are NONE (raw scan codes), ASCII (default ascii
  1060.  * mappings, and UNICODE for standard 16 bit unicode mappings.
  1061.  *
  1062.  * Our template driver supports only raw and ascii modes.
  1063.  */
  1064. case SIO_KYBD_MODE_SET:
  1065.     switch (arg)
  1066. {
  1067. case SIO_KYBD_MODE_RAW:
  1068. case SIO_KYBD_MODE_ASCII:
  1069.     break;
  1070. case SIO_KYBD_MODE_UNICODE:
  1071.     return ENOSYS; /* template doesn't support unicode */
  1072. }
  1073.     pChan->scanMode = arg;
  1074.     return OK;
  1075. case SIO_KYBD_MODE_GET:
  1076.     *(int *)someArg = pChan->scanMode;
  1077.     return OK;
  1078. #endif /* optional keyboard scan code support */
  1079. default:
  1080.     return ENOSYS;
  1081. }
  1082.     return OK;
  1083.     }
  1084. /*******************************************************************************
  1085. *
  1086. * dummyTxCallback - dummy Tx callback routine
  1087. *
  1088. * RETURNS: ERROR.
  1089. */
  1090. LOCAL STATUS dummyTxCallback
  1091.     (
  1092.     void * callbackArg, /* argument registered with callback */
  1093.     char * pChara  /* ptr to data location */
  1094.     )
  1095.     {
  1096.     static BOOL doit = TRUE;
  1097.     /*
  1098.      * TODO - Until an upstream module connects to this device, there
  1099.      * is no data available to send.  We should only be concerned
  1100.      * if this callback is being called repeatedly and often. That
  1101.      * could indicate an interrupt servicing problem of some kind.
  1102.      */
  1103.     if (doit)
  1104. {
  1105. printf ("Dummy txCallback: 0x%x 0x%xn",
  1106. (int)callbackArg, (int)pChara);
  1107. doit = FALSE;
  1108. }
  1109.     return (ERROR);
  1110.     }
  1111. /*******************************************************************************
  1112. *
  1113. * dummyRxCallback - dummy Rx callback routine
  1114. *
  1115. * RETURNS: N/A.
  1116. * ARGSUSED
  1117. */
  1118. LOCAL void dummyRxCallback
  1119.     (
  1120.     void * callbackArg, /* argument registered with callback */
  1121.     char data  /* receive data */
  1122.     )
  1123.     {
  1124.     static BOOL doit = TRUE;
  1125.     /*
  1126.      * TODO - Device is transferring data, but there is no
  1127.      * upstream module connected to receive it.  Lets log
  1128.      * a message about incoming data being lost.  Buts lets
  1129.      * do this only once we don't want a 'flood' of logged
  1130.      * messages.
  1131.      */
  1132.     if (doit)
  1133. {
  1134. printf ("Dummy rxCallback: 0x%x 0x%xn",
  1135. (int)callbackArg, (int)data);
  1136. doit = FALSE;
  1137. }
  1138.     return;
  1139.     }
  1140. /*******************************************************************************
  1141. *
  1142. * dummyErrCallback - dummy Error callback routine
  1143. *
  1144. * There should be an sioLib module to provide dummyCallbacks for all SIO
  1145. * drivers to use.
  1146. *
  1147. * RETURNS: N/A.
  1148. * ARGSUSED
  1149. */
  1150. LOCAL void dummyErrCallback
  1151.     (
  1152.     void * callbackArg, /* argument registered with callback */
  1153.     int errorCode,  /* error code */
  1154.     void * pData, /* ptr to device specific data */
  1155.     int size /* size of device specific data */
  1156.     )
  1157.     {
  1158.     static BOOL doit = TRUE;
  1159.     /* TODO -  We could log the reported error (once). */
  1160.     if (doit)
  1161. {
  1162. printf ("Dummy errorCallback: 0x%x 0x%x 0x%x %dn",
  1163. (int)callbackArg, errorCode, (int)pData, size);
  1164. doit = FALSE;
  1165. }
  1166.     return;
  1167.     }
  1168. /*******************************************************************************
  1169. *
  1170. * templateProbe - probe for device 
  1171. *
  1172. * Try to determine if device is present.  Do not reconfigure device if it
  1173. * is there.  This should be a passive probe that does not interfere with
  1174. * the device.
  1175. *
  1176. * RETURNS:
  1177. * Returns OK if device adaptor is there, ERROR if not there.
  1178. */
  1179. LOCAL STATUS templateProbe
  1180.     (
  1181.     TEMPLATE_CHAN * pChan /* channel to probe */
  1182.     )
  1183.     {
  1184.     char testData;
  1185.     /*
  1186.      * TODO - Probe device registers to see if they are there and if they
  1187.      * are the proper type of device.  Look for specific bits that are
  1188.      * always 0 or 1.  Don't attempt any operations with side effects
  1189.      * that might clear interrupt status or flags.  For High Availability
  1190.      * situations, some other CPU may be controlling this device. We do
  1191.      * not want to interfere with those operations.
  1192.      */
  1193.     TEMPLATE_PROBE (pChan, TEMPLATE_CSR_ID, VX_READ, 1, &testData);
  1194.     /* TODO - Is this really the right type device ? */
  1195.     return OK;
  1196.     }
  1197. /*******************************************************************************
  1198. *
  1199. * templateVerify - verify template chan structure
  1200. *
  1201. * Given a pointer to what should be a TEMPLATE_CHAN, verify that it really
  1202. * is a TEMPLATE_CHAN structure.
  1203. *
  1204. * This routine should not be called at every level with every routine.  It is
  1205. * primarily provided for use with the xxxDestroy routine.  Performance will be
  1206. * a problem if every pointer is checked for validity with every use.
  1207. *
  1208. * RETURNS:
  1209. * Returns OK if pointer is valid, ERROR if not.
  1210. */
  1211. LOCAL STATUS templateVerify
  1212.     (
  1213.     TEMPLATE_CHAN * pChan /* pointer to be verified */
  1214.     )
  1215.     {
  1216.     /*
  1217.      * TODO - Examine the structure. Look for magic cookies or flag bits.
  1218.      * Anything that would confirm this pointer as being a valid
  1219.      * TEMPLATE_CHAN pointer.
  1220.      */
  1221.     if (pChan == NULL)
  1222. return ERROR;
  1223.     return OK;
  1224.     }
  1225. #if 1 /* TODO - Optional modem control line support */
  1226. /*******************************************************************************
  1227. *
  1228. * templateMstatGet - read device modem control line status
  1229. *
  1230. * Read the device modem control lines and map them to the standard
  1231. * modem signal bits.
  1232. *
  1233. * RETURNS:
  1234. * Returns the modem control line status bits.
  1235. */
  1236. LOCAL int templateMstatGet
  1237.     (
  1238.     TEMPLATE_CHAN *pChan
  1239.     )
  1240.     {
  1241.     UINT8 rawStatus;
  1242.     int result = 0;
  1243.     TEMPLATE_SIO_READ8 (pChan, TEMPLATE_MSR_ID, &rawStatus);
  1244.     /* Now map device status bits, to standard status bits */
  1245.     if (rawStatus & TEMPLATE_MSR_CD)
  1246. result |= SIO_MODEM_CD;
  1247.     if (rawStatus & TEMPLATE_MSR_DTR)
  1248. result |= SIO_MODEM_DTR;
  1249.     if (rawStatus & TEMPLATE_MSR_DSR)
  1250. result |= SIO_MODEM_DSR;
  1251.     if (rawStatus & TEMPLATE_MSR_RTS)
  1252. result |= SIO_MODEM_RTS;
  1253.     if (rawStatus & TEMPLATE_MSR_CTS)
  1254. result |= SIO_MODEM_CTS;
  1255.     return result;
  1256.     }
  1257. /*******************************************************************************
  1258. *
  1259. * templateMstatSetClear - set/clear modem control lines
  1260. *
  1261. * This routine allows the user to set or clear individual modem control
  1262. * lines.  Of course, only the output lines can actually be changed.
  1263. *
  1264. * RETURNS:
  1265. * OK, or EIO upon detecting a hardware fault.
  1266. */
  1267. LOCAL int templateMstatSetClr
  1268.     (
  1269.     TEMPLATE_CHAN *pChan,
  1270.     UINT bits, /* bits to change */
  1271.     BOOL setFlag /* TRUE = set, FALSE = clear */
  1272.     )
  1273.     {
  1274.     UINT8 rawStatus;
  1275.     UINT8 rawMask = 0;
  1276.     /* Read current modem status */
  1277.     TEMPLATE_SIO_READ8 (pChan, TEMPLATE_MSR_ID, &rawStatus);
  1278.     /* ignore input only bits */
  1279.     bits &= TEMPLATE_OSIG_MASK;
  1280.     /* Now map standard bits to device specific bits */
  1281.     if (bits & SIO_MODEM_DTR)
  1282. rawMask |= TEMPLATE_MSR_DTR;
  1283.     if (bits & SIO_MODEM_RTS)
  1284. rawMask |= TEMPLATE_MSR_RTS;
  1285.     /* Update device with new output signals */
  1286.     if (setFlag)
  1287. rawStatus |= rawMask; /* set new bits */
  1288.     else
  1289. rawStatus &= ~rawMask; /* clear bits */
  1290.     TEMPLATE_SIO_WRITE8 (pChan, TEMPLATE_MSR_ID, rawStatus);
  1291.     return OK;
  1292.     }
  1293. #endif /* optional modem control line support */