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

VxWorks

开发平台:

C/C++

  1. /* wdbVioDrv.c - virtual tty I/O driver for the WDB agent */
  2. /* Copyright 1994-2001 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01j,18oct01,jhw  Fixed documentation build errors.
  7. 01i,26feb99,jmp  canceled fixed for SPR #23898, reinstate the outputDone
  8.  mechanism.
  9. 01h,27jan99,dbt  modified event dequeue routine to never send NULL size VIO
  10.                  events (SPR #23898). Fixed the close routine (SPR #24654).
  11. 01g,09aug96,ms   close now waits for output complete (SPR 6211).
  12. 01f,24oct95,ms   don't send up more data than wdbCommMtu (SPR #5228).
  13. 01e,14oct95,jdi  doc: cleanup.
  14. 01d,01jun95,ms  fixed vioInput
  15. 01c,24may95,ms  keep calling tyITx until it returns ERROR.
  16. 01b,19may95,ms   one device, multiplexed on open().
  17. 01a,08nov94,ms   written.
  18. */
  19. /*
  20. DESCRIPTION
  21. This library provides a psuedo-tty driver for use with the WDB debug
  22. agent.  I/O is performed on a virtual I/O device just like it is on
  23. a VxWorks serial device.  The difference is that the data is not
  24. moved over a physical serial channel, but rather over a virtual
  25. channel created between the WDB debug agent and the Tornado host
  26. tools.
  27. The driver is installed with wdbVioDrv().  Individual virtual I/O channels
  28. are created by opening the device (see wdbVioDrv for details).  The
  29. virtual I/O channels are defined as follows:
  30. .TS
  31. tab(|);
  32. lf3 lf3
  33. l   l.
  34. Channel | Usage
  35. _
  36. 0 | Virtual console
  37. 1-0xffffff | Dynamically created on the host
  38. >= 0x1000000 | User defined
  39. .TE
  40. Once data is written to a virtual I/O channel on the target, it is sent
  41. to the host-based target server.  The target server allows this data to be
  42. sent to another host tool, redirected to the "virtual console," or
  43. redirected to a file.  For details see the
  44. .I Tornado User's Guide.
  45. */
  46. #include "vxWorks.h"
  47. #include "ioLib.h"
  48. #include "iosLib.h"
  49. #include "tyLib.h"
  50. #include "stdlib.h"
  51. #include "stdio.h"
  52. #include "intLib.h"
  53. #include "rngLib.h"
  54. #include "taskLib.h"
  55. #include "wdb/wdb.h"
  56. #include "wdb/wdbLibP.h"
  57. #include "wdb/wdbEvtLib.h"
  58. #include "wdb/wdbVioLib.h"
  59. #include "wdb/wdbLibP.h"
  60. #define INBUF_SIZE 512
  61. #define OUTBUF_SIZE 512
  62. #define MAX_VIO_XFER_SIZE 512
  63. #define MAX_FLUSH_TRIES 60
  64. typedef struct
  65.     {
  66.     DEV_HDR devHdr; /* device header */
  67.     char        buf[MAX_VIO_XFER_SIZE]; /* temporary buffer */
  68.     } VIO_DEV;
  69. typedef struct
  70.     {
  71.     TY_DEV tyDev; /* input/output buffers, etc */
  72.     WDB_VIO_NODE vioNode; /* VIO device list node */
  73.     WDB_EVT_NODE eventNode; /* RPC event list node */
  74.     VIO_DEV * pVioDev; /* device handle */
  75.     BOOL outputDone; /* done with output */
  76.     BOOL vioChannelIsClosed; /* VIO channel is closed */
  77.     } VIO_CHANNEL_DESC;
  78. static int vioDrvNum;           /* driver number assigned to this driver */
  79. /* forward declarations */
  80. static int     vioOpen  (VIO_DEV *pDev, char * name, int mode);
  81. static STATUS  vioClose  (VIO_CHANNEL_DESC *pChannelDesc);
  82. static STATUS  vioIoctl  (VIO_CHANNEL_DESC *pChannelDesc, int request,
  83. int arg);
  84. static void    vioStartup  (VIO_CHANNEL_DESC *pChannelDesc);
  85. static int     vioInput  (WDB_VIO_NODE *pNode, char *pData,
  86. uint_t nBytes);
  87. static void    vioWriteEventGet  (void * pChannelDesc, WDB_EVT_DATA *pEvtData);
  88. static void    vioWriteEventDeq  (void * pChannelDesc);
  89. /*******************************************************************************
  90. *
  91. * wdbVioDrv - initialize the tty driver for a WDB agent
  92. *
  93. * This routine initializes the VxWorks virtual I/O driver and creates
  94. * a virtual I/O device of the specified name.
  95. *
  96. * This routine should be called exactly once, before any reads, writes, or
  97. * opens.  Normally, it is called by usrRoot() in usrConfig.c,
  98. * and the device name created is "/vio".
  99. *
  100. * After this routine has been called, individual virtual I/O channels
  101. * can be open by appending the channel number to the virtual I/O
  102. * device name.  For example, to get a file descriptor for virtual I/O
  103. * channel 0x1000017, call open() as follows:
  104. * .CS
  105. *     fd = open ("/vio/0x1000017", O_RDWR, 0)
  106. * .CE
  107. *
  108. * RETURNS: OK, or ERROR if the driver cannot be installed.
  109. */
  110. STATUS wdbVioDrv
  111.     (
  112.     char *name
  113.     )
  114.     {
  115.     static VIO_DEV vioDev; /* virtual I/O device */
  116.     /* check if driver already installed */
  117.     if (vioDrvNum > 0)
  118. return (OK);
  119.     vioDrvNum = iosDrvInstall (vioOpen, (FUNCPTR) NULL, vioOpen,
  120.                                 (FUNCPTR) vioClose, tyRead, tyWrite, vioIoctl);
  121.     if (vioDrvNum <= 0)
  122.         return (ERROR);
  123.     /* Add the device to the I/O systems device list */
  124.     return (iosDevAdd (&vioDev.devHdr, name, vioDrvNum));
  125.     }
  126. /*******************************************************************************
  127. *
  128. * vioOpen - open a virtual I/O channel
  129. *
  130. * RETURNS: vioDv handle
  131. */
  132. static int vioOpen
  133.     (
  134.     VIO_DEV * pDev,
  135.     char * name,
  136.     int mode
  137.     )
  138.     {
  139.     VIO_CHANNEL_DESC * pChannelDesc;
  140.     int channel;
  141.     /* parse the channel number from the name */
  142.     if (name[0]=='/')
  143. name = &name[1];
  144.     channel = (int) strtol (name, (char **)NULL, 10);
  145.     if ((channel == 0) && (name[0] != '0'))
  146. return (ERROR);
  147.     /* create a channel descriptor */
  148.     pChannelDesc = (VIO_CHANNEL_DESC *) malloc (sizeof (VIO_CHANNEL_DESC));
  149.     if (pChannelDesc == NULL)
  150. return (ERROR);
  151.     /* initialize the channel descriptor */
  152.     if (tyDevInit (&pChannelDesc->tyDev, INBUF_SIZE, OUTBUF_SIZE,
  153.                     (FUNCPTR)vioStartup) != OK)
  154.         return (ERROR);
  155.     wdbEventNodeInit (&pChannelDesc->eventNode, vioWriteEventGet,
  156. vioWriteEventDeq, (void *)pChannelDesc);
  157.     pChannelDesc->pVioDev  = pDev;
  158.     pChannelDesc->vioNode.channel  = channel;
  159.     pChannelDesc->vioNode.pVioDev  = &pChannelDesc->vioNode;
  160.     pChannelDesc->vioNode.inputRtn  = vioInput;
  161.     pChannelDesc->vioChannelIsClosed  = FALSE;
  162.     if (wdbVioChannelRegister (&pChannelDesc->vioNode) == ERROR)
  163. return (ERROR);
  164.     return ((int) pChannelDesc);
  165.     }
  166. /******************************************************************************
  167. *
  168. * vioClose - close a VIO channel
  169. */ 
  170. static STATUS vioClose
  171.     (
  172.     VIO_CHANNEL_DESC * pChannelDesc /* chanel to close */
  173.     )
  174.     {
  175.     int numTries;
  176.     /* unregister VIO channel to prevent further input from host */
  177.     wdbVioChannelUnregister (&pChannelDesc->vioNode);
  178.     /*
  179.      * Dequeue the event node to prevent further output to the host.
  180.      * But first try waiting a bit to allow pending data to be flushed.
  181.      */
  182.     for (numTries = 0; numTries < MAX_FLUSH_TRIES; numTries++)
  183. if (pChannelDesc->eventNode.onQueue == TRUE)
  184.     taskDelay (1);
  185.     /* indicate that the VIO channel is closed */
  186.     pChannelDesc->vioChannelIsClosed = TRUE;
  187.     /* dequeue the event node */
  188.     wdbEventDeq (&pChannelDesc->eventNode);
  189.     /* free all the malloc'ed memory */
  190.     rngDelete (pChannelDesc->tyDev.wrtBuf);
  191.     rngDelete (pChannelDesc->tyDev.rdBuf);
  192.     free (pChannelDesc);
  193.     return (OK);
  194.     }
  195. /*******************************************************************************
  196. *
  197. * vioIoctl - special device control
  198. *
  199. * This routine passes all requests to tyIoctl().
  200. *
  201. * RETURNS: whatever tyIoctl() returns.
  202. */
  203. static STATUS vioIoctl
  204.     (
  205.     VIO_CHANNEL_DESC * pChannelDesc, /* device to control */
  206.     int  request, /* request code */
  207.     int  arg /* some argument */
  208.     )
  209.     {
  210.     STATUS status;
  211.     switch (request)
  212.         {
  213.         default:
  214.             status = tyIoctl (&pChannelDesc->tyDev, request, arg);
  215.             break;
  216.         }
  217.     return (status);
  218.     }
  219. /*******************************************************************************
  220. *
  221. * vioStartup - transmitter startup routine
  222. *
  223. * Call interrupt level character output routine.
  224. *
  225. * RETURNS: N/A
  226. */
  227. static void vioStartup
  228.     (
  229.     VIO_CHANNEL_DESC *pChannelDesc /* ty device to start up */
  230.     )
  231.     {
  232.     wdbEventPost (&pChannelDesc->eventNode);
  233.     }
  234. /******************************************************************************
  235. *
  236. * vioWriteEventGet - retrieve the WDB_VIO_WRITE event data
  237. */
  238. static void vioWriteEventGet
  239.     (
  240.     void *    arg,
  241.     WDB_EVT_DATA * pEvtData
  242.     )
  243.     {
  244.     uint_t nBytes;
  245.     VIO_CHANNEL_DESC * pChannelDesc;
  246.     uint_t lockKey;
  247.     char * outBuf;
  248.     int maxBytes;
  249.     pChannelDesc = (VIO_CHANNEL_DESC *)arg;
  250.     pChannelDesc->outputDone = FALSE;
  251.     /* if the VIO channel is closed, return */
  252.     if (pChannelDesc->vioChannelIsClosed)
  253.      return;
  254.     outBuf = pChannelDesc->pVioDev->buf;
  255.     maxBytes = wdbCommMtu - 90;
  256.     if (maxBytes > MAX_VIO_XFER_SIZE)
  257. maxBytes = MAX_VIO_XFER_SIZE;
  258.     for (nBytes = 0; nBytes < maxBytes; nBytes++)
  259. {
  260. lockKey = intLock();
  261. if (tyITx (&pChannelDesc->tyDev, &outBuf[nBytes]) == ERROR)
  262.     {
  263.     pChannelDesc->outputDone = TRUE;
  264.     intUnlock (lockKey);
  265.     break;
  266.     }
  267. intUnlock (lockKey);
  268. }
  269.     pEvtData->evtType = WDB_EVT_VIO_WRITE;
  270.     pEvtData->eventInfo.vioWriteInfo.destination =
  271. (TGT_ADDR_T)pChannelDesc->vioNode.channel;
  272.     pEvtData->eventInfo.vioWriteInfo.numBytes   = nBytes;
  273.     pEvtData->eventInfo.vioWriteInfo.source = outBuf;
  274.     }
  275. /******************************************************************************
  276. *
  277. * vioWriteEventDeq - delete the WDB_VIO_WRITE event
  278. */
  279. static void vioWriteEventDeq
  280.     (
  281.     void * arg
  282.     )
  283.     {
  284.     uint_t lockKey;
  285.     VIO_CHANNEL_DESC * pChannelDesc = (VIO_CHANNEL_DESC *)arg;
  286.     /* if the VIO channel is closed, return */
  287.     if (pChannelDesc->vioChannelIsClosed)
  288.      return;
  289.     /* any data remaining? if so, post the event */
  290.     lockKey = intLock();
  291.     if (pChannelDesc->outputDone == FALSE)
  292. wdbEventPost (&pChannelDesc->eventNode);
  293.     intUnlock (lockKey);
  294.     }
  295. /******************************************************************************
  296. *
  297. * vioInput - handle incoming VIO packets
  298. */
  299. static int vioInput
  300.     (
  301.     WDB_VIO_NODE * pVioNode,
  302.     char * pData,
  303.     uint_t maxBytes
  304.     )
  305.     {
  306.     int nBytes;
  307.     uint_t lockKey;
  308.     TY_DEV * pTyDev;
  309. #undef OFFSET
  310. #define OFFSET(type, field) ((int)&((type *)0)->field)
  311.     pTyDev = (TY_DEV *)((int)pVioNode - OFFSET (VIO_CHANNEL_DESC, vioNode)
  312. + OFFSET (VIO_CHANNEL_DESC, tyDev));
  313.     for (nBytes = 0; nBytes < maxBytes; nBytes++)
  314. {
  315.         lockKey = intLock();
  316. if (wdbIsNowExternal())
  317.     intCnt++; /* fake an ISR context */
  318. if (tyIRd (pTyDev, pData[nBytes]) == ERROR)
  319.     {
  320.     intUnlock (lockKey);
  321.     break;
  322.     }
  323. if (wdbIsNowExternal())
  324.     intCnt--; /* fake an ISR exit */
  325. intUnlock (lockKey);
  326. }
  327.     return (nBytes);
  328.     }