wdbPipePktDrv.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:19k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* wdbPipePktDrv.c - pipe packet driver for lightweight UDP/IP */
  2. /* Copyright 1998-2002 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01q,15apr02,hbh  Removed call to excJobAdd() to support System Mode Debugging
  7.  on Windows simulator (SPR# 23866) and fix SPR# 26247.
  8. 01p,21nov01,jmp  added intLock()/intUnlock() around NT system call.
  9. 01o,19oct01,hbh  Opened transmit pipe with L_NONBLOCK flag to avoid process
  10.                  lock (SPR #34107).
  11.  Freed allocated buffer if excJobAdd() fails.
  12.  Fixed passing of right # of parameters to excJobAdd(). 
  13.  Got rid of compilation warnings.
  14. 01n,16mar99,dbt  In wdbPipeInt() routine, call wdbPipeFlush() only if some
  15.                  data have been received (SPR #25734).
  16. 01m,24nov98,cym  moving interrupt handling to task level
  17. 01l,06oct98,jmp  doc : cleanup.
  18. 01k,27aug98,fle  doc : fixed a typo in file header and removed dash
  19.                  underscores in library description
  20. 01j,06aug98,pdm  used wd timer instead of poll task (SIMHPPA only)
  21. 01i,19may98,cym  changed forward for wdbPipeInt for SIMNT.
  22. 01h,19may98,dbt  test if the pipe is used by another simulator before using
  23.  it. 
  24.  Test if the kernel is initialized (with taskIdCurrent) 
  25.  before running intConnect() or taskCreate() routines.
  26.  Disable pipe interrupts when we enter polling mode.
  27.  Removed build warnings.
  28. 01g,27apr98,dbt  no longer unlink the pipe if it already exists.
  29.  added copyright.
  30. 01f,09apr98,pdn  used select while polling the fd so we don't block.
  31. 01e,08apr98,pdn  used poll mode for HP Sim.
  32. 01d,20mar98,cym  changed for vxSim NT.
  33. 01c,20mar98,pdn  fixed wdbPipeInt() to return if packet size can not be
  34.                  determent.
  35. 01b,12mar98,pdn  fixed to work with system mode (poll.)
  36. 01a,11mar98,pdn  written.
  37. */
  38. /*
  39. DESCRIPTION
  40. OVERVIEW
  41. This module is a pipe for drivers interfacing with the WDB agent's
  42. lightweight UDP/IP interpreter. It can be used as a starting point
  43. when writing new drivers. Such drivers are the lightweight equivalent
  44. of a network interface driver.
  45. These drivers, along with the lightweight UDP-IP interpreter, have two
  46. benefits over the stand combination of a netif driver + the full VxWorks
  47. networking stack; First, they can run in a much smaller amout of target
  48. memory because the lightweight UDP-IP interpreter is much smaller than
  49. the VxWorks network stack (about 800 bytes total). Second, they provide
  50. a communication path which is independant of the OS, and thus can be
  51. used to support an external mode (e.g., monitor style) debug agent.
  52. Throughout this file the word "pipe" is used in place of a real
  53. driver name. For example, if you were writing a lightweight driver
  54. for the lance ethernet chip, you would want to substitute "pipe"
  55. with "ln" throughout this file.
  56. PACKET READY CALLBACK
  57. When the driver detects that a packet has arrived (either in its receiver
  58. ISR or in its poll input routine), it invokes a callback to pass the
  59. data to the debug agent. Right now the callback routine is called "udpRcv",
  60. however other callbacks may be added in the future. 
  61. The driver's wdbPipeDevInit() routine should be passed the callback as
  62. a parameter and place it in the device data structure. That way the driver
  63. will continue to work if new callbacks are added later.
  64. MODES
  65. Ideally the driver should support both polled and interrupt mode, and be
  66. capable of switching modes dynamically. However this is not required.
  67. When the agent is not running, the driver will be placed in "interrupt mode"
  68. so that the agent can be activated as soon as a packet arrives.
  69. If your driver does not support an interrupt mode, you can simulate this
  70. mode by spawning a VxWorks task to poll the device at periodic intervals
  71. and simulate a receiver ISR when a packet arrives.
  72. For dynamically mode switchable drivers, be aware that the driver may be
  73. asked to switch modes in the middle of its input ISR. A driver's input ISR
  74. will look something like this:
  75. .CS
  76.    doSomeStuff();
  77.    pPktDev->wdbDrvIf.stackRcv (pMbuf);   /@ invoke the callback @/
  78.    doMoreStuff();
  79. .CE
  80. If this channel is used as a communication path to an external mode
  81. debug agent, then the agent's callback will lock interrupts, switch
  82. the device to polled mode, and use the device in polled mode for awhile.
  83. Later on the agent will unlock interrupts, switch the device back to
  84. interrupt mode, and return to the ISR.
  85. In particular, the callback can cause two mode switches, first to polled mode
  86. and then back to interrupt mode, before it returns.
  87. This may require careful ordering of the callback within the interrupt
  88. handler. For example, you may need to acknowledge the interrupt within
  89. the doSomeStuff() processing rather than the doMoreStuff() processing.
  90. USAGE
  91. The driver is typically only called only from usrWdb.c. The only directly
  92. callable routine in this module is wdbPipePktDevInit().
  93. You will need to modify usrWdb.c to allow your driver to be initialized
  94. by the debug agent.
  95. You will want to modify usrWdb.c to include your driver's header
  96. file, which should contain a definition of WDB_PIPE_PKT_MTU.
  97. There is a default user-selectable macro called WDB_MTU, which must
  98. be no larger than WDB_PIPE_PKT_MTU. Modify the begining of
  99. usrWdb.c to insure that this is the case by copying the way
  100. it is done for the other drivers.
  101. The routine wdbCommIfInit() also needs to be modified so that if your
  102. driver is selected as the WDB_COMM_TYPE, then your drivers init
  103. routine will be called. Search usrWdb.c for the macro "WDB_COMM_CUSTOM"
  104. and mimic that style of initialization for your driver.
  105. DATA BUFFERING
  106. The drivers only need to handle one input packet at a time because
  107. the WDB protocol only supports one outstanding host-request at a time.
  108. If multiple input packets arrive, the driver can simply drop them.
  109. The driver then loans the input buffer to the WDB agent, and the agent
  110. invokes a driver callback when it is done with the buffer.
  111. For output, the agent will pass the driver a chain of mbufs, which
  112. the driver must send as a packet. When it is done with the mbufs,
  113. it calls wdbMbufChainFree() to free them.
  114. The header file wdbMbuflib.h provides the calls for allocating, freeing,
  115. and initializing mbufs for use with the lightweight UDP/IP interpreter.
  116. It ultimatly makes calls to the routines wdbMbufAlloc and wdbMbufFree, which
  117. are provided in source code in usrWdb.c.
  118. */
  119. /* includes */
  120. #include "vxWorks.h"
  121. #if (CPU_FAMILY==SIMHPPA) || (CPU_FAMILY==SIMSPARCSOLARIS) || 
  122.     (CPU_FAMILY==SIMNT)
  123. #include "taskLib.h"
  124. #include "wdLib.h"
  125. #include <fcntl.h>
  126. #include <stdio.h>
  127. #include "string.h"
  128. #include "errno.h"
  129. #include "sioLib.h"
  130. #include "intLib.h"
  131. #include "iv.h"
  132. #include "simLib.h"
  133. #include "wdb/wdbMbufLib.h"
  134. #include "drv/wdb/wdbPipePktDrv.h"
  135. #if CPU != SIMNT
  136. #include "u_Lib.h"
  137. #endif /* CPU != SIMNT */
  138. /* externals */
  139. #undef READ
  140. #undef WRITE
  141. #if CPU == SIMNT
  142. extern void simMailSlotInit(void *inBuf,int *busyFlag, int *writeFd,
  143.     void (* intHandler)(),int intArg);
  144. extern void simDelay (int);
  145. extern int mailslotWrite (int hFile, char * szMessage, int len);
  146. extern int mailslotConnect (char * szSlotName, int timeout);
  147. extern int mailslotClose (int hSlot);
  148. #define TGTSVR_MAIL_SLOT "\\.\mailslot\tgtsvr.1"
  149. extern int simLastMailSize;
  150. extern int simInIntHandle;
  151. int polledPackets = 0;
  152. int pollingInt = 0;
  153. #else /* CPU != SIMNT */
  154. extern int UNLINK (char *);
  155. extern int MKFIFO (char *, int);
  156. extern int OPEN (char *, int);
  157. extern int READ (int, char *, int);
  158. extern int WRITE (int, char*, int);
  159. extern int GETUID (void);
  160. extern int SELECT (int, fd_set *, fd_set *, fd_set *, struct timeval *);
  161. #endif /*  CPU == SIMNT */ 
  162. /* pseudo-macros */
  163. #if CPU == SIMSPARCSOLARIS
  164. #define DRIVER_MODE_SET(pDev, mode) wdbPipeDrvModeSet (pDev, mode)
  165. #else /* CPU != SIMSPARCSOLARIS */
  166. #define DRIVER_MODE_SET(pDev, mode)
  167. #endif /* CPU == SIMSPARCSOLARIS */
  168. #define DRIVER_RESET_INPUT(pDev) {pDev->inputBusy=FALSE;}
  169. #define DRIVER_RESET_OUTPUT(pDev) {pDev->outputBusy=FALSE;}
  170. #define DRIVER_POLL_TX(pDev, pBuf) {}
  171. #define DRIVER_DROP_PACKET(pDev) {}
  172. /* forward declarations */
  173. LOCAL STATUS wdbPipePoll (void *pDev);
  174. LOCAL STATUS wdbPipeTx   (void *pDev, struct mbuf * pMbuf);
  175. LOCAL STATUS wdbPipeModeSet (void *pDev, uint_t newMode);
  176. LOCAL void   wdbPipeFree (void *pDev);
  177. #if CPU == SIMNT
  178. LOCAL STATUS wdbPipeInt  (WDB_PIPE_PKT_DEV * pPktDev,int byteRead);
  179. #else /* CPU != SIMNT */
  180. LOCAL void   wdbPipeFlush (int pipeFd);
  181. LOCAL STATUS wdbPipeInt  (WDB_PIPE_PKT_DEV * pPktDev);
  182. #if CPU == SIMHPPA
  183. LOCAL void   wdbPipeInputChk (WDB_PIPE_PKT_DEV * pPktDev);
  184. LOCAL WDOG_ID wdPipeId = NULL;
  185. #define WD_TIMEOUT 2
  186. #else /* CPU != SIMHPPA */
  187. LOCAL void  wdbPipeDrvModeSet (WDB_PIPE_PKT_DEV * pPktDev, uint_t newMode);
  188. #endif /* CPU == SIMHPPA */
  189. #endif /* CPU == SIMNT */
  190. /******************************************************************************
  191. *
  192. * wdbPipePktDevInit - initialize a pipe packet device.
  193. */
  194. STATUS wdbPipePktDevInit
  195.     (
  196.     WDB_PIPE_PKT_DEV * pPktDev, /* pipe device structure to init */
  197.     void (*stackRcv)() /* receive packet callback (udpRcv) */
  198.     )
  199.     {
  200. #if CPU != SIMNT    
  201.     char h2tPipe[64] = {0};
  202.     char t2hPipe[64] = {0};
  203.     int rc;
  204. #else
  205.     int lvl;
  206. #endif /* CPU != SIMNT */
  207.     /* initialize the wdbDrvIf field with driver info */
  208.     pPktDev->wdbDrvIf.mode = WDB_COMM_MODE_POLL | WDB_COMM_MODE_INT;
  209.     pPktDev->wdbDrvIf.mtu = WDB_PIPE_PKT_MTU;
  210.     pPktDev->wdbDrvIf.stackRcv = stackRcv; /* udpRcv */
  211.     pPktDev->wdbDrvIf.devId = (WDB_PIPE_PKT_DEV *)pPktDev;
  212.     pPktDev->wdbDrvIf.pollRtn = wdbPipePoll;
  213.     pPktDev->wdbDrvIf.pktTxRtn = wdbPipeTx;
  214.     pPktDev->wdbDrvIf.modeSetRtn = wdbPipeModeSet;
  215.     /* initialize the device specific fields in the driver structure */
  216.     pPktDev->inputBusy = FALSE;
  217.     pPktDev->outputBusy = FALSE;
  218. #if CPU != SIMNT
  219.     {
  220.     struct unix_stat buf;
  221.     /*
  222.      * Initialize the named pipe, and connect the driver interrupt
  223.      * handler.
  224.      */
  225.     sprintf (h2tPipe, "/tmp/vxsim_h2t_%d", GETUID());
  226.     sprintf (t2hPipe, "/tmp/vxsim_t2h_%d", GETUID());
  227.     /* create the named pipes if they don't already exist */
  228.     if (u_stat (h2tPipe, (char*)&buf) < 0)
  229. {
  230. rc = UNLINK (h2tPipe);
  231. rc = MKFIFO (h2tPipe, 0600);
  232. }
  233.     if (u_stat (t2hPipe, (char*)&buf) < 0)
  234. {
  235. rc = UNLINK (t2hPipe);
  236. rc = MKFIFO (t2hPipe, 0600);
  237. }
  238.     rc = pPktDev->h2t_fd = OPEN (h2tPipe, L_RDWR|L_NDELAY);
  239.     /* test if the pipe is already in used by another simulator */
  240.     if (u_lockf (rc, F_TLOCK, 0) != 0)
  241. {
  242. if (_func_printErr != NULL)
  243.     _func_printErr ("wdbPipePktDevInit: pipe is already used by another simulatorn");
  244. return (ERROR);
  245. }
  246.     /* 
  247.      * SPR 34107 : use NONBLOCK flag to avoid the simulator to lock on the
  248.      * next write if fifo stream is full.
  249.      */
  250.      
  251.     rc = pPktDev->t2h_fd = OPEN (t2hPipe, L_RDWR|L_NONBLOCK);
  252.     /* flush reception pipe */
  253.     wdbPipeFlush (pPktDev->h2t_fd);
  254.     /* 
  255.      * Connect interrupt or spawn the task (for HPPA) only if the OS is 
  256.      * initialized.
  257.      */
  258.     if (taskIdCurrent)
  259. {
  260. #if CPU == SIMHPPA
  261. /* named pipe on HP host does not generate SIGIO. */
  262.         if (wdPipeId == NULL)
  263.             wdPipeId = wdCreate();
  264.         wdStart (wdPipeId, WD_TIMEOUT, (FUNCPTR) wdbPipeInputChk, (int)pPktDev);
  265. #else /* CPU != SIMHPPA */
  266. /* setting up interrupt. */
  267. s_fdint (pPktDev->h2t_fd, 1);
  268. intConnect (FD_TO_IVEC (pPktDev->h2t_fd), 
  269. (void (*)())wdbPipeInt, (int)pPktDev);
  270. #endif /* CPU == SIMHPPA */
  271. }
  272.     }
  273. #else /* CPU != SIMNT */
  274.     /* Initialize the mailslot. */
  275.     pPktDev->t2h_fd = 0;
  276.     lvl = intLock(); /* lock windows system call */
  277.     simMailSlotInit(pPktDev->inBuf,
  278.     &(pPktDev->inputBusy),
  279.     &(pPktDev->t2h_fd),
  280.     (void (*)())&wdbPipeInt, 
  281.     (int)pPktDev);
  282.     
  283.     intUnlock (lvl); /* unlock windows system call */
  284. #endif /* CPU != SIMNT */
  285.     return (OK);
  286.     }
  287. #if CPU == SIMHPPA
  288. /******************************************************************************
  289. *
  290. * wdbPipeInputChk - fake an input ISR when a packet arrives
  291. */
  292. static void wdbPipeInputChk
  293.     (
  294.     WDB_PIPE_PKT_DEV * pDev
  295.     )
  296.     {
  297.     int key;
  298.     fd_set readFds;
  299.     struct timeval timeout;
  300.     timeout.tv_sec = 0;
  301.     timeout.tv_usec = 0;
  302.     FD_ZERO (&readFds);
  303.     FD_SET (pDev->h2t_fd, &readFds);
  304.     if (SELECT (FD_SETSIZE, &readFds, (fd_set *)NULL,
  305.             (fd_set *)NULL, &timeout) > 0)
  306.         {
  307.         key = intLock();
  308.         wdbPipeInt (pDev);
  309.         intUnlock (key);
  310.         }
  311.     wdStart (wdPipeId, WD_TIMEOUT, (FUNCPTR) wdbPipeInputChk, (int)pDev);
  312.     }
  313. #endif /* CPU == SIMHPPA */
  314. /******************************************************************************
  315. *
  316. * wdbPipeInt - pipe driver interrupt handler
  317. *
  318. * RETURNS: N/A
  319. */
  320. static STATUS wdbPipeInt
  321.     (
  322.     WDB_PIPE_PKT_DEV * pPktDev
  323. #if CPU==SIMNT
  324.     ,
  325.     int byteRead
  326. #endif
  327.     )
  328.     {
  329. #if CPU!=SIMNT
  330.     int  byteRead;
  331.     short  packetSize = 0;
  332.     char  szPacketSize [sizeof(short)] = {0};
  333. #endif
  334.     struct  mbuf * pMbuf;
  335. #if CPU==SIMNT
  336.     if ( polledPackets && !pollingInt )
  337.         {
  338.         polledPackets--;
  339. return(ERROR);
  340.         }
  341. #endif
  342.         
  343.     /*
  344.      * The code below is for handling a packet-recieved interrupt.
  345.      * A real driver may also have to check for other interrupting
  346.      * conditions such as DMA errors, etc.
  347.      */
  348. #if CPU != SIMNT /* SIMNT Fake device does all of this */
  349.     /* input buffer already in use - drop this packet */
  350.     if (pPktDev->inputBusy)
  351. {
  352.         wdbPipeFlush (pPktDev->h2t_fd);
  353.         DRIVER_DROP_PACKET(pPktDev);
  354. return FALSE;
  355. }
  356.     /* 
  357.      * get the packet size
  358.      */
  359.     
  360.     byteRead = READ (pPktDev->h2t_fd, szPacketSize, sizeof(short));
  361.     if (byteRead < sizeof(short))
  362.         {
  363. /*
  364.  * Flush the pipe only if we have received something. This is
  365.  * usefull for polling mode if a packet was received between
  366.  * READ() call and this test.
  367.  */
  368.     
  369. if (byteRead > 0)
  370.     wdbPipeFlush (pPktDev->h2t_fd);
  371.         return FALSE;
  372.         }
  373.     packetSize = * (short *) szPacketSize;
  374.     if (packetSize > WDB_PIPE_PKT_MTU) 
  375.         {
  376.         wdbPipeFlush (pPktDev->h2t_fd);
  377.         return FALSE;
  378.         }
  379.     /*
  380.      * Fill the input buffer with the packet. Use an mbuf cluster to pass
  381.      * the packet on to the agent.
  382.      */
  383.     byteRead = READ (pPktDev->h2t_fd, pPktDev->inBuf, packetSize);
  384.     if (byteRead != packetSize)
  385.         {
  386.         wdbPipeFlush (pPktDev->h2t_fd);
  387.         return FALSE;
  388.         }
  389. #endif /* CPU != SIMNT */
  390.     pMbuf = wdbMbufAlloc();
  391.     if (pMbuf == NULL)
  392. {
  393. DRIVER_DROP_PACKET(pPktDev);
  394. return FALSE;
  395. }
  396.     wdbMbufClusterInit (pMbuf, pPktDev->inBuf, byteRead, 
  397. (int (*)())wdbPipeFree, (int)pPktDev);
  398.     pPktDev->inputBusy = TRUE;
  399.     (*pPktDev->wdbDrvIf.stackRcv) (pMbuf);  /* invoke callback */
  400.     return TRUE;
  401.     }
  402. /******************************************************************************
  403. *
  404. * wdbPipeTx - transmit a packet.
  405. *
  406. * The packet is realy a chain of mbufs. We may have to just queue up
  407. * this packet is we are already transmitting.
  408. *
  409. * RETURNS: OK or ERROR
  410. */
  411. static STATUS wdbPipeTx
  412.     (
  413.     void  * pDev,
  414.     struct mbuf * pMbuf
  415.     )
  416.     {
  417.     WDB_PIPE_PKT_DEV *  pPktDev = pDev;
  418.     int  lockKey;
  419.     struct mbuf *  pFirstMbuf = pMbuf;
  420.     char  data [WDB_PIPE_PKT_MTU + sizeof(short)];
  421.     int            len;
  422.     int  byteWritten = -1;
  423.     /* if we are in polled mode, transmit the packet in a loop */
  424.     if (pPktDev->mode == WDB_COMM_MODE_POLL)
  425. {
  426. DRIVER_POLL_TX(pPktDev, pMbuf);
  427. return (OK);
  428. }
  429.     lockKey = intLock();
  430.     /* if the txmitter isn't cranking, queue the packet and start txmitting */
  431.     if (pPktDev->outputBusy == FALSE)
  432. {
  433. pPktDev->outputBusy = TRUE;
  434. #if CPU==SIMNT /* SIMNT doesn't need to prepend length */ 
  435. len = 0;
  436. #else
  437.         len = 2;
  438. #endif
  439.         while (pMbuf != NULL)
  440.             {
  441.             bcopy (mtod (pMbuf, char *), &data[len], pMbuf->m_len);
  442.             len += pMbuf->m_len;
  443.             pMbuf = pMbuf->m_next;
  444.             }
  445.         wdbMbufChainFree (pFirstMbuf);
  446. #if CPU != SIMNT
  447.         * (short *) &data [0]  = (short) len - 2; 
  448.         byteWritten = WRITE (pPktDev->t2h_fd, data, len);
  449. #else
  450.         if(pPktDev->t2h_fd)
  451.             {
  452.             byteWritten = mailslotWrite (pPktDev->t2h_fd, data, len);
  453.             }
  454.         if(byteWritten == -2)
  455.             {
  456.             mailslotClose( pPktDev->t2h_fd );
  457.             pPktDev->t2h_fd = mailslotConnect(TGTSVR_MAIL_SLOT,2);
  458.             if (pPktDev->t2h_fd == -1 )
  459.                 {
  460.         pPktDev->outputBusy = FALSE;
  461.                 intUnlock (lockKey);
  462.                 return(ERROR);
  463.                 }
  464.             else
  465.                 {
  466.                 byteWritten = mailslotWrite (pPktDev->t2h_fd, data, len);
  467.                 }
  468.             }
  469. #endif /* CPU != SIMNT */
  470.         /* Write has failed, treat the error for all arch */
  471.         if(byteWritten == -1)
  472.             {
  473.     pPktDev->outputBusy = FALSE;
  474.             intUnlock (lockKey);
  475.             return(ERROR);
  476.             }
  477. pPktDev->outputBusy = FALSE;
  478. }
  479.     intUnlock (lockKey);
  480.     return (OK);
  481.     }
  482. /******************************************************************************
  483. *
  484. * wdbPipeFree - free the input buffer
  485. *
  486. * This is the callback used to let us know the agent is done with the
  487. * input buffer we loaded it.
  488. *
  489. * RETURNS: N/A
  490. */
  491. static void wdbPipeFree
  492.     (
  493.     void * pDev
  494.     )
  495.     {
  496.     WDB_PIPE_PKT_DEV * pPktDev = pDev;
  497.     pPktDev->inputBusy = FALSE;
  498.     }
  499. /******************************************************************************
  500. *
  501. * wdbPipeModeSet - switch driver modes
  502. *
  503. * RETURNS: OK for a supported mode, else ERROR
  504. */
  505. static STATUS wdbPipeModeSet
  506.     (
  507.     void * pDev,
  508.     uint_t newMode
  509.     )
  510.     {
  511.     WDB_PIPE_PKT_DEV * pPktDev = pDev;
  512.     DRIVER_RESET_INPUT  (pPktDev);
  513.     DRIVER_RESET_OUTPUT (pPktDev);
  514.     if (newMode == WDB_COMM_MODE_INT) 
  515. DRIVER_MODE_SET (pPktDev, WDB_COMM_MODE_INT);
  516.     else if (newMode == WDB_COMM_MODE_POLL)
  517. DRIVER_MODE_SET (pPktDev, WDB_COMM_MODE_POLL);
  518.     else
  519. return (ERROR);
  520.     return (OK);
  521.     }
  522. /******************************************************************************
  523. *
  524. * wdbPipePoll - poll for a packet
  525. *
  526. * This routine polls for a packet. If a packet has arrived it invokes
  527. * the agents callback.
  528. *
  529. * RETURNS: OK if a packet has arrived, else ERROR.
  530. */ 
  531. static STATUS wdbPipePoll
  532.     (
  533.     void * pDev
  534.     )
  535.     {
  536.     WDB_PIPE_PKT_DEV * pPktDev = (WDB_PIPE_PKT_DEV *) pDev;
  537. #if CPU == SIMNT
  538.     if(pPktDev->inputBusy)
  539.         {
  540.         pollingInt = 1;
  541.         polledPackets++;
  542. wdbPipeInt(pPktDev,simLastMailSize);
  543.         pollingInt = 0;
  544.         return( 0 );
  545.         }
  546.     simDelay(1);
  547.     return(ERROR);
  548. #else
  549.     if (wdbPipeInt (pPktDev))
  550.         return (OK);
  551.     else 
  552.         return (ERROR);
  553. #endif /* CPU == SIMNT */
  554.     }
  555. #if CPU != SIMNT
  556. #if CPU != SIMHPPA
  557. /******************************************************************************
  558. *
  559. * wdbPipeDrvModeSet - switch driver modes
  560. *
  561. * RETURNS: N/A
  562. */
  563. static void wdbPipeDrvModeSet
  564.     (
  565.     WDB_PIPE_PKT_DEV * pPktDev,
  566.     uint_t newMode
  567.     )
  568.     {
  569.     if (newMode == WDB_COMM_MODE_INT) 
  570. {
  571. s_fdint (pPktDev->h2t_fd, 1);
  572. /*
  573.  * XXX - DBT flush the pipe before entering interrupt mode. If the
  574.  * pipe is not empty, it won't generate any interrupt when a packet
  575.  * is received.
  576.  */
  577. wdbPipeFlush (pPktDev->h2t_fd);
  578. }
  579.     else /* poll mode */
  580. s_fdint (pPktDev->h2t_fd, 0);
  581.     }
  582. #endif /* CPU != SIMHPPA */
  583. /******************************************************************************
  584. *
  585. * wdbPipeFlush - flush pipe receive bufer
  586. */
  587. static void wdbPipeFlush
  588.     (
  589.     int pipeFd /* pipe file desc */
  590.     )
  591.     {
  592.     char tmpBuf [WDB_PIPE_PKT_MTU];
  593.     int  nBytes;
  594.     do
  595. {
  596. nBytes = u_read (pipeFd, tmpBuf, WDB_PIPE_PKT_MTU);
  597. }
  598.     while (nBytes > 0);
  599.     }
  600. #endif /* CPU != SIMNT */
  601. #endif /* CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS || ... */