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

VxWorks

开发平台:

C/C++

  1. /* wdbTemplatektDrv.c - template packet driver for lightweight UDP/IP */
  2. /*
  3. modification history
  4. --------------------
  5. 01b,08jul97,dgp  doc: change WDB_COMM_UDPL_CUSTOM to WDB_COMM_CUSTOM (SPR 7831)
  6. 01a,23aug95,ms   written.
  7. */
  8. /*
  9. DESCRIPTION
  10. OVERVIEW
  11. --------
  12. This module is a template for drivers interfacing with the WDB agent's
  13. lightweight UDP/IP interpreter. It can be used as a starting point
  14. when writing new drivers. Such drivers are the lightweight equivalent
  15. of a network interface driver.
  16. These drivers, along with the lightweight UDP-IP interpreter, have two
  17. benefits over the stand combination of a netif driver + the full VxWorks
  18. networking stack; First, they can run in a much smaller amout of target
  19. memory because the lightweight UDP-IP interpreter is much smaller than
  20. the VxWorks network stack (about 800 bytes total). Second, they provide
  21. a communication path which is independant of the OS, and thus can be
  22. used to support an external mode (e.g., monitor style) debug agent.
  23. Throughout this file the word "template" is used in place of a real
  24. driver name. For example, if you were writing a lightweight driver
  25. for the lance ethernet chip, you would want to substitute "template"
  26. with "ln" throughout this file.
  27. PACKET READY CALLBACK
  28. ---------------------
  29. When the driver detects that a packet has arrived (either in its receiver
  30. ISR or in its poll input routine), it invokes a callback to pass the
  31. data to the debug agent. Right now the callback routine is called "udpRcv",
  32. however other callbacks may be added in the future. 
  33. The driver's wdbTemplateDevInit() routine should be passed the callback as
  34. a parameter and place it in the device data structure. That way the driver
  35. will continue to work if new callbacks are added later.
  36. MODES
  37. -----
  38. Ideally the driver should support both polled and interrupt mode, and be
  39. capable of switching modes dynamically. However this is not required.
  40. When the agent is not running, the driver will be placed in "interrupt mode"
  41. so that the agent can be activated as soon as a packet arrives.
  42. If your driver does not support an interrupt mode, you can simulate this
  43. mode by spawning a VxWorks task to poll the device at periodic intervals
  44. and simulate a receiver ISR when a packet arrives.
  45. For dynamically mode switchable drivers, be aware that the driver may be
  46. asked to switch modes in the middle of its input ISR. A driver's input ISR
  47. will look something like this:
  48.    doSomeStuff();
  49.    pPktDev->wdbDrvIf.stackRcv (pMbuf);   /@ invoke the callback @/
  50.    doMoreStuff();
  51. If this channel is used as a communication path to an external mode
  52. debug agent, then the agent's callback will lock interrupts, switch
  53. the device to polled mode, and use the device in polled mode for awhile.
  54. Later on the agent will unlock interrupts, switch the device back to
  55. interrupt mode, and return to the ISR.
  56. In particular, the callback can cause two mode switches, first to polled mode
  57. and then back to interrupt mode, before it returns.
  58. This may require careful ordering of the callback within the interrupt
  59. handler. For example, you may need to acknowledge the interrupt within
  60. the doSomeStuff() processing rather than the doMoreStuff() processing.
  61. USAGE
  62. -----
  63. The driver is typically only called only from usrWdb.c. The only directly
  64. callable routine in this module is wdbTemplatePktDevInit().
  65. You will need to modify usrWdb.c to allow your driver to be initialized
  66. by the debug agent.
  67. You will want to modify usrWdb.c to include your driver's header
  68. file, which should contain a definition of WDB_TEMPLATE_PKT_MTU.
  69. There is a default user-selectable macro called WDB_MTU, which must
  70. be no larger than WDB_TEMPLATE_PKT_MTU. Modify the begining of
  71. usrWdb.c to insure that this is the case by copying the way
  72. it is done for the other drivers.
  73. The routine wdbCommIfInit() also needs to be modified so that if your
  74. driver is selected as the WDB_COMM_TYPE, then your drivers init
  75. routine will be called. Search usrWdb.c for the macro "WDB_COMM_CUSTOM"
  76. and mimic that style of initialization for your driver.
  77. DATA BUFFERING
  78. --------------
  79. The drivers only need to handle one input packet at a time because
  80. the WDB protocol only supports one outstanding host-request at a time.
  81. If multiple input packets arrive, the driver can simply drop them.
  82. The driver then loans the input buffer to the WDB agent, and the agent
  83. invokes a driver callback when it is done with the buffer.
  84. For output, the agent will pass the driver a chain of mbufs, which
  85. the driver must send as a packet. When it is done with the mbufs,
  86. it calls wdbMbufChainFree() to free them.
  87. The header file wdbMbuflib.h provides the calls for allocating, freeing,
  88. and initializing mbufs for use with the lightweight UDP/IP interpreter.
  89. It ultimatly makes calls to the routines wdbMbufAlloc and wdbMbufFree, which
  90. are provided in source code in usrWdb.c.
  91. */
  92. #include "string.h"
  93. #include "errno.h"
  94. #include "sioLib.h"
  95. #include "intLib.h"
  96. #include "wdb/wdbMbufLib.h"
  97. #include "drv/wdb/wdbTemplatePktDrv.h"
  98. /* pseudo-macros */
  99. #define DRIVER_INIT_HARDWARE(pDev) {}
  100. #define DRIVER_MODE_SET(pDev, mode)
  101. #define DRIVER_PACKET_IS_READY(pDev) FALSE
  102. #define DRIVER_RESET_INPUT(pDev) {pDev->inputBusy=FALSE;}
  103. #define DRIVER_RESET_OUTPUT(pDev) {pDev->outputBusy=FALSE;}
  104. #define DRIVER_GET_INPUT_PACKET(pDev, pBuf) (50)
  105. #define DRIVER_DATA_FROM_MBUFS(pDev, pBuf) {}
  106. #define DRIVER_POLL_TX(pDev, pBuf) {}
  107. #define DRIVER_TX_START(pDev) {}
  108. #define DRIVER_DROP_PACKET(pDev) {}
  109. /* forward declarations */
  110. static STATUS wdbTemplatePoll (void *pDev);
  111. static STATUS wdbTemplateTx   (void *pDev, struct mbuf * pMbuf);
  112. static STATUS wdbTemplateModeSet (void *pDev, uint_t newMode);
  113. static void   wdbTemplateFree (void *pDev);
  114. /******************************************************************************
  115. *
  116. * wdbTemplatePktDevInit - initialize a template packet device.
  117. */
  118. void wdbTemplatePktDevInit
  119.     (
  120.     WDB_TEMPLATE_PKT_DEV *pPktDev, /* template device structure to init */
  121.     void (*stackRcv)() /* receive packet callback (udpRcv) */
  122.     )
  123.     {
  124.     /* initialize the wdbDrvIf field with driver info */
  125.     pPktDev->wdbDrvIf.mode = WDB_COMM_MODE_POLL | WDB_COMM_MODE_INT;
  126.     pPktDev->wdbDrvIf.mtu = WDB_TEMPLATE_PKT_MTU;
  127.     pPktDev->wdbDrvIf.stackRcv = stackRcv; /* udpRcv */
  128.     pPktDev->wdbDrvIf.devId = (WDB_TEMPLATE_PKT_DEV *)pPktDev;
  129.     pPktDev->wdbDrvIf.pollRtn = wdbTemplatePoll;
  130.     pPktDev->wdbDrvIf.pktTxRtn = wdbTemplateTx;
  131.     pPktDev->wdbDrvIf.modeSetRtn = wdbTemplateModeSet;
  132.     /* initialize the device specific fields in the driver structure */
  133.     pPktDev->inputBusy = FALSE;
  134.     pPktDev->outputBusy = FALSE;
  135.     /*
  136.      * Put your hardware initialization code here. It should initialze
  137.      * the device structure's register addresses and initialize
  138.      * the hardware.
  139.      * You can either connect the driver's ISR handler(s) here (in which
  140.      * case you should have the interrupt vector passed to this driver init
  141.      * routine), or just require the BSP to connect the driver interrupt
  142.      * handler in sysHwInit2() routine.
  143.      */
  144.     DRIVER_INIT_HARDWARE(pPktDev);
  145.     /* put the device in a quiescent state (setting polled mode is one way) */
  146.     wdbTemplateModeSet (pPktDev, WDB_COMM_MODE_POLL);
  147.     }
  148. /******************************************************************************
  149. *
  150. * wdbTemplateInt - template driver interrupt handler
  151. *
  152. * RETURNS: N/A
  153. */
  154. void wdbTemplateInt
  155.     (
  156.     WDB_TEMPLATE_PKT_DEV * pPktDev
  157.     )
  158.     {
  159.     struct mbuf * pMbuf;
  160.     int           packetSize;
  161.     /*
  162.      * The code below is for handling a packet-recieved interrupt.
  163.      * A real driver may also have to check for other interrupting
  164.      * conditions such as DMA errors, etc.
  165.      */
  166.     /* input buffer already in use - drop this packet */
  167.     if (pPktDev->inputBusy)
  168. {
  169.         DRIVER_DROP_PACKET(pPktDev);
  170. return;
  171. }
  172.     /*
  173.      * Fill the input buffer with the packet. Use an mbuf cluster to pass
  174.      * the packet on to the agent.
  175.      */
  176.     packetSize = DRIVER_GET_INPUT_PACKET (pPktDev, pPktDev->inBuf);
  177.     pMbuf = wdbMbufAlloc();
  178.     if (pMbuf == NULL)
  179. {
  180. DRIVER_DROP_PACKET(pPktDev);
  181. return;
  182. }
  183.     wdbMbufClusterInit (pMbuf, pPktDev->inBuf, packetSize, 
  184. (int (*)())wdbTemplateFree, (int)pPktDev);
  185.     pPktDev->inputBusy = TRUE;
  186.     (*pPktDev->wdbDrvIf.stackRcv) (pMbuf);  /* invoke callback */
  187.     }
  188. /******************************************************************************
  189. *
  190. * wdbTemplateTx - transmit a packet.
  191. *
  192. * The packet is realy a chain of mbufs. We may have to just queue up
  193. * this packet is we are already transmitting.
  194. *
  195. * RETURNS: OK or ERROR
  196. */
  197. static STATUS wdbTemplateTx
  198.     (
  199.     void * pDev,
  200.     struct mbuf * pMbuf
  201.     )
  202.     {
  203.     WDB_TEMPLATE_PKT_DEV *pPktDev = pDev;
  204.     int  lockKey;
  205.     /* if we are in polled mode, transmit the packet in a loop */
  206.     if (pPktDev->mode == WDB_COMM_MODE_POLL)
  207. {
  208. DRIVER_POLL_TX(pPktDev, pMbuf);
  209. return (OK);
  210. }
  211.     lockKey = intLock();
  212.     /* if the txmitter isn't cranking, queue the packet and start txmitting */
  213.     if (pPktDev->outputBusy == FALSE)
  214. {
  215. pPktDev->outputBusy = TRUE;
  216. DRIVER_DATA_FROM_MBUFS(pPktDev, pMbufs);
  217. DRIVER_TX_START(pPktDev);
  218. }
  219.     /* else just queue the packet */
  220.     else
  221. {
  222. DRIVER_DATA_FROM_MBUFS(pPktDev, pMbufs);
  223. }
  224.     intUnlock (lockKey);
  225.     wdbMbufChainFree (pMbuf);
  226.     return (OK);
  227.     }
  228. /******************************************************************************
  229. *
  230. * wdbTemplateFree - free the input buffer
  231. *
  232. * This is the callback used to let us know the agent is done with the
  233. * input buffer we loaded it.
  234. *
  235. * RETURNS: N/A
  236. */
  237. static void wdbTemplateFree
  238.     (
  239.     void * pDev
  240.     )
  241.     {
  242.     WDB_TEMPLATE_PKT_DEV * pPktDev = pDev;
  243.     pPktDev->inputBusy = FALSE;
  244.     }
  245. /******************************************************************************
  246. *
  247. * wdbTemplateModeSet - switch driver modes
  248. *
  249. * RETURNS: OK for a supported mode, else ERROR
  250. */
  251. static STATUS wdbTemplateModeSet
  252.     (
  253.     void * pDev,
  254.     uint_t newMode
  255.     )
  256.     {
  257.     WDB_TEMPLATE_PKT_DEV * pPktDev = pDev;
  258.     DRIVER_RESET_INPUT  (pPktDev);
  259.     DRIVER_RESET_OUTPUT (pPktDev);
  260.     if (newMode == WDB_COMM_MODE_INT)
  261. DRIVER_MODE_SET (pPktDev, WDB_COMM_MODE_INT);
  262.     else if (newMode == WDB_COMM_MODE_POLL)
  263. DRIVER_MODE_SET (pPktDev, WDB_COMM_MODE_POLL);
  264.     else
  265. return (ERROR);
  266.     return (ERROR);
  267.     }
  268. /******************************************************************************
  269. *
  270. * wdbTemplatePoll - poll for a packet
  271. *
  272. * This routine polls for a packet. If a packet has arrived it invokes
  273. * the agents callback.
  274. *
  275. * RETURNS: OK if a packet has arrived, else ERROR.
  276. */ 
  277. static STATUS wdbTemplatePoll
  278.     (
  279.     void * pDev
  280.     )
  281.     {
  282.     WDB_TEMPLATE_PKT_DEV * pPktDev = pDev;
  283.     struct mbuf * pMbuf;
  284.     int           packetSize;
  285.     if (DRIVER_PACKET_IS_READY(pPktDev))
  286. {
  287. /*
  288.  * Fill the input buffer with the packet. Use an mbuf cluster to pass
  289.  * the packet on to the agent.
  290.  */
  291. packetSize = DRIVER_GET_INPUT_PACKET (pPktDev, pPktDev->inBuf);
  292. pMbuf = wdbMbufAlloc();
  293. if (pMbuf == NULL)
  294.     {
  295.     DRIVER_RESET_INPUT(pPktDev);
  296.     return (ERROR);
  297.     }
  298. wdbMbufClusterInit (pMbuf, pPktDev->inBuf, packetSize, 
  299. (int (*)())wdbTemplateFree, (int)pPktDev);
  300. pPktDev->inputBusy = TRUE;
  301. (*pPktDev->wdbDrvIf.stackRcv) (pMbuf);  /* invoke callback */
  302. return (OK);
  303. }
  304.     return (ERROR);
  305.     }