/* wdbTrace32PktDrv.c - TRACE32 packet driver for lightweight UDP/IP */ /* modification history -------------------- 05.03.98 DIE written for ARM 12.11.00 DIE modified for Tornado II */ /* DESCRIPTION This is the Packet driver for a TRACE32 target server - target debug agent connection. */ #include "string.h" #include "errno.h" #include "sioLib.h" #include "intLib.h" #include "wdb/wdbMbufLib.h" #include "wdb/wdbUdpLib.h" #include "wdbTrace32PktDrv.h" /* pseudo-macros */ #define DRIVER_INIT_HARDWARE(x) t32_driver_init_hardware(x) #define DRIVER_MODE_SET(pDev, mode) #define DRIVER_PACKET_IS_READY(x) t32_driver_packet_is_ready(x) #define DRIVER_RESET_INPUT(x) t32_driver_reset_input(x) #define DRIVER_RESET_OUTPUT(pDev) {pDev->outputBusy=FALSE;} #define DRIVER_GET_INPUT_PACKET(x,y) t32_driver_get_input_packet(x,y) #define DRIVER_DATA_FROM_MBUFS(x,y) t32_driver_data_from_mbufs(x,y) #define DRIVER_POLL_TX(x,y) t32_driver_poll_tx(x,y) #define DRIVER_TX_START(x) t32_driver_tx_start(x) /* forward declarations */ static STATUS wdbTrace32Poll (void *pDev); static STATUS wdbTrace32Tx (void *pDev, struct mbuf * pMbuf); static STATUS wdbTrace32ModeSet (void *pDev, uint_t newMode); static void wdbTrace32Free (void *pDev); void t32_driver_init_hardware (WDB_TRACE32_PKT_DEV *pdev); STATUS t32_driver_packet_is_ready (WDB_TRACE32_PKT_DEV *pdev); int t32_driver_get_input_packet (WDB_TRACE32_PKT_DEV *pdev, char *pBuf); void t32_driver_reset_input (WDB_TRACE32_PKT_DEV *pdev); void t32_driver_poll_tx (WDB_TRACE32_PKT_DEV *pDev, struct mbuf *pMbuf); void t32_driver_data_from_mbufs (WDB_TRACE32_PKT_DEV *pDev, struct mbuf *pMbuf); void t32_driver_tx_start (WDB_TRACE32_PKT_DEV *pDev); WDB_TRACE32_PKT_DEV sPktDev; volatile u_long T32INCHARS = 0; volatile u_long T32OUTCHARS = 0; volatile char T32INBUF [WDB_TRACE32_PKT_MTU]; volatile char T32OUTBUF [WDB_TRACE32_PKT_MTU]; /****************************************************************************** * * wdbCommDevInit - initialize a Trace32 packet device. */ extern uint_t wdbCommMtu; STATUS wdbCommDevInit (WDB_COMM_IF* pCommIf, char** ppIn, char** ppOut) { static WDB_TRACE32_PKT_DEV wdbTrace32PktDev; /* Trace32 packet device */ /* update input & output buffer pointers */ *ppIn = (char*) T32INBUF; *ppOut = (char*) T32OUTBUF; /* update communication interface mtu */ wdbCommMtu = WDB_TRACE32_PKT_MTU; /* Trace32 packet driver - supports task or external agent */ wdbTrace32PktDevInit (&wdbTrace32PktDev, udpRcv); udpCommIfInit (pCommIf, &wdbTrace32PktDev.wdbDrvIf); /* put the device in a quiescent state (setting polled mode is one way) */ if (pCommIf->modeSet) pCommIf->modeSet (pCommIf->commId, WDB_COMM_MODE_POLL); else wdbTrace32ModeSet (&wdbTrace32PktDev, WDB_COMM_MODE_POLL); return SUCCESS; } void wdbTrace32PktDevInit ( WDB_TRACE32_PKT_DEV *pPktDev, /* Trace32 device structure to init */ void (*stackRcv)() /* receive packet callback (udpRcv) */ ) { /* initialize the wdbDrvIf field with driver info */ pPktDev->wdbDrvIf.mode = WDB_COMM_MODE_POLL | WDB_COMM_MODE_INT; pPktDev->wdbDrvIf.mtu = WDB_TRACE32_PKT_MTU; pPktDev->wdbDrvIf.stackRcv = stackRcv; /* udpRcv */ pPktDev->wdbDrvIf.devId = (WDB_TRACE32_PKT_DEV *)pPktDev; pPktDev->wdbDrvIf.pollRtn = wdbTrace32Poll; pPktDev->wdbDrvIf.pktTxRtn = wdbTrace32Tx; pPktDev->wdbDrvIf.modeSetRtn = wdbTrace32ModeSet; /* initialize the device specific fields in the driver structure */ pPktDev->inputBusy = FALSE; pPktDev->outputBusy = FALSE; DRIVER_INIT_HARDWARE(pPktDev); sPktDev = *pPktDev; } /****************************************************************************** * * wdbTrace32Tx - transmit a packet. * * The packet is realy a chain of mbufs. We may have to just queue up * this packet is we are already transmitting. * * RETURNS: OK or ERROR */ static STATUS wdbTrace32Tx ( void * pDev, struct mbuf * pMbuf ) { WDB_TRACE32_PKT_DEV *pPktDev = pDev; int lockKey; lockKey = intLock(); DRIVER_POLL_TX(pPktDev, pMbuf); pPktDev->outputBusy = TRUE; DRIVER_DATA_FROM_MBUFS(pPktDev, pMbuf); DRIVER_TX_START(pPktDev); intUnlock (lockKey); wdbMbufChainFree (pMbuf); return (OK); } /****************************************************************************** * * wdbTrace32Free - free the input buffer * * This is the callback used to let us know the agent is done with the * input buffer we loaded it. * * RETURNS: N/A */ static void wdbTrace32Free ( void * pDev ) { WDB_TRACE32_PKT_DEV * pPktDev = pDev; DRIVER_RESET_INPUT (pPktDev); } /****************************************************************************** * * wdbTrace32ModeSet - switch driver modes * * RETURNS: OK for a supported mode, else ERROR */ static STATUS wdbTrace32ModeSet ( void * pDev, uint_t newMode ) { WDB_TRACE32_PKT_DEV * pPktDev = pDev; DRIVER_RESET_INPUT (pPktDev); DRIVER_RESET_OUTPUT (pPktDev); if (newMode == WDB_COMM_MODE_INT) DRIVER_MODE_SET (pPktDev, WDB_COMM_MODE_INT); else if (newMode == WDB_COMM_MODE_POLL) DRIVER_MODE_SET (pPktDev, WDB_COMM_MODE_POLL); else return (ERROR); return (OK); } /****************************************************************************** * * wdbTrace32Poll - poll for a packet * * This routine polls for a packet. If a packet has arrived it invokes * the agents callback. * * RETURNS: OK if a packet has arrived, else ERROR. */ static STATUS wdbTrace32Poll ( void * pDev ) { WDB_TRACE32_PKT_DEV * pPktDev = pDev; struct mbuf * pMbuf; int packetSize; if (!pDev) pPktDev = & sPktDev; if (DRIVER_PACKET_IS_READY(pPktDev)) { /* * Fill the input buffer with the packet. Use an mbuf cluster to pass * the packet on to the agent. */ packetSize = DRIVER_GET_INPUT_PACKET (pPktDev, pPktDev->inBuf); pMbuf = wdbMbufAlloc(); if (pMbuf == NULL) { DRIVER_RESET_INPUT(pPktDev); return (ERROR); } wdbMbufClusterInit (pMbuf, pPktDev->inBuf, packetSize, \ (int (*)())wdbTrace32Free, (int)pPktDev); pPktDev->inputBusy = TRUE; (*pPktDev->wdbDrvIf.stackRcv) (pMbuf); /* invoke callback */ return (OK); } else taskDelay (20); return (ERROR); } /*** TRACE32 driver functions ***/ char devOutBuf [WDB_TRACE32_PKT_MTU]; u_long devOutLen; void t32_poll_extern (void) { wdbTrace32Poll (0); } void t32_driver_init_hardware (WDB_TRACE32_PKT_DEV *pdev) { T32INCHARS = T32OUTCHARS = 0; } STATUS t32_driver_packet_is_ready (WDB_TRACE32_PKT_DEV *pdev) { if (T32INCHARS) return TRUE; else return FALSE; } int t32_driver_get_input_packet (WDB_TRACE32_PKT_DEV *pdev, char *pBuf) { int size; bcopy ((const char*) T32INBUF, pBuf, T32INCHARS); size = T32INCHARS; T32INCHARS = 0; return size; } void t32_driver_reset_input (WDB_TRACE32_PKT_DEV *pDev) { pDev->inputBusy=FALSE; /* T32INCHARS = 0; */ } void t32_driver_poll_tx (WDB_TRACE32_PKT_DEV *pDev, struct mbuf *pMbuf) { while (T32OUTCHARS) taskDelay(20); pDev->outputBusy = FALSE; } void t32_driver_data_from_mbufs (WDB_TRACE32_PKT_DEV *pDev, struct mbuf *pMbuf) { char* source; devOutLen = 0; while (pMbuf) { source = mtod (pMbuf, char*); bcopy (source, devOutBuf + devOutLen, pMbuf->m_len); devOutLen += pMbuf->m_len; pMbuf = pMbuf->m_next; } } STATUS vxSemGive ( void * semId ); void **t32WriteSyncSem = 0; void t32_driver_tx_start (WDB_TRACE32_PKT_DEV *pDev) { bcopy (devOutBuf, (char*) T32OUTBUF, devOutLen); T32OUTCHARS = devOutLen; /* vxSemGive (*t32WriteSyncSem); */ /* wdbModeSet (WDB_MODE_EXTERN); */ /* to avoid semaphore waiting in udp */ }