static int SerparWrite(DriverCall *dc) { te_status status; int nwritten = 0; static TxState txstate; /* * is this a new packet? */ if (dc->dc_context == NULL) { /* * yes - initialise TxEngine */ Angel_TxEngineInit(&config, &dc->dc_packet, &txstate.state); txstate.index = 0; dc->dc_context = &txstate; } /* * fill the buffer using the Tx Engine */ do { status = Angel_TxEngine(&dc->dc_packet, &txstate.state, &txstate.writebuf[txstate.index]); if (status != TS_IDLE) txstate.index++; } while (status == TS_IN_PKT && txstate.index < MAXWRITESIZE); #ifdef DO_TRACE { unsigned int i = 0; while (i < txstate.index) { printf(">%02X ", txstate.writebuf[i]); if (!(++i % 16)) putc('\n', stdout); } if (i % 16) putc('\n', stdout); } #endif /* * the data are ready, all we need now is to send them out * in a form that Angel can swallow. */ #ifdef COMPILING_ON_WINDOWS if (WriteParallel(txstate.writebuf, txstate.index) == COM_OK) { nwritten = txstate.index; if (pfnProgressCallback != NULL) { progressInfo.nWritten += nwritten; (*pfnProgressCallback)(&progressInfo); } } else { MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP); return -1; /* SJ - This really needs to return a value, which is picked up in */ /* DevSW_Read as meaning stop debugger but don't kill. */ } #else nwritten = Unix_WriteParallel(txstate.writebuf, txstate.index); #endif if (nwritten < 0) nwritten = 0; #ifdef DO_TRACE printf("SerparWrite: wrote %d out of %d bytes\n", nwritten, txstate.index); #endif /* * has the whole packet gone? */ if (nwritten == (int)txstate.index && (status == TS_DONE_PKT || status == TS_IDLE)) /* * yes it has */ return 1; else { /* * if some data are left, shuffle them * to the start of the buffer */ if (nwritten != (int)txstate.index && nwritten != 0) { txstate.index -= nwritten; (void)memmove((char *) txstate.writebuf, (char *) (txstate.writebuf + nwritten), txstate.index); } else if (nwritten == (int)txstate.index) txstate.index = 0; return 0; } }
/* * Function: serpkt_fill_tx_ring * Purpose: Fill ups a transmit ring buffer from the Tx engine * * Pre-conditions: Interrupts should be disabled * * Params: * Input: devid device ID of the driver * * In/Out: ring the ring buffer to be filled * * Returns: Nothing */ static void serpkt_fill_tx_ring(const DeviceID devid, RingBuffer * const ring) { volatile unsigned int *const status = angel_DeviceStatus + devid; unsigned int eod = *status & SER_TX_EOD; /* not bool -- it's a bitmask */ /* * loop while data left to send and the buffer has space left */ while ((eod == 0) && !ringBufFull(ring)) { te_status tx_status; unsigned char new_ch; unsigned int s; /* * This task is running as AngelCallback priority so it can * be interrupted. If a heartbeat arrives which needs to write * an acknowledge, the interrupting heartbeat task will never * terminate (because we're busy); the result is deadlock. * * Interim Solution: Don't let the interrupt happen! */ /* s = Angel_EnableInterruptsFromSVC(); */ tx_status = Angel_TxEngine(SerEngine(devid)->tx_packet, SerEngine(devid)->te_state, &new_ch); /* Angel_RestoreInterruptsFromSVC(s); */ switch (tx_status) { case TS_DONE_PKT: eod = TRUE; spk_tx_numpackets++; /* and FALL THROUGH TO */ case TS_IN_PKT: #if DEBUG == 1 { static int count = 0; LogInfo(LOG_WIRE, (">%02X ", new_ch)); if (++count > 16) { LogInfo(LOG_WIRE, ("\n")); count = 0; } } #endif ringBufPutChar(ring, new_ch); spk_tx_numbytes++; break; case TS_IDLE: LogWarning(LOG_SERPKT, ( "TS_IDLE in fill_ring\n")); break; default: LogError(LOG_SERPKT, ( "Unknown status in fill_ring\n")); break; } } if (eod) *status |= SER_TX_EOD; /* * if ring buffer was empty when we started filling it, then * we need to kick start the first character */ if ((*status & SER_TX_KICKSTART) != 0) { *status |= SER_TX_DATA; *status &= ~SER_TX_KICKSTART; SerCtrl(devid)->control_tx(devid); SerCtrl(devid)->kick_start(devid); } }
static int SerialWrite(DriverCall *dc) { int nwritten = 0; te_status testatus = TS_IN_PKT; if (dc->dc_context == NULL) { Angel_TxEngineInit(&config, &(dc->dc_packet), &(wstate.txstate)); wstate.wbindex = 0; dc->dc_context = &wstate; } while ((testatus == TS_IN_PKT) && (wstate.wbindex < MAXWRITESIZE)) { /* send the raw data through the tx engine to escape and encapsulate */ testatus = Angel_TxEngine(&(dc->dc_packet), &(wstate.txstate), &(wstate.writebuf)[wstate.wbindex]); if (testatus != TS_IDLE) wstate.wbindex++; } if (testatus == TS_IDLE) { #ifdef DEBUG printf("SerialWrite: testatus is TS_IDLE during preprocessing\n"); #endif } #ifdef DO_TRACE { int i = 0; while (i<wstate.wbindex) { printf(">%02X ",wstate.writebuf[i]); if (!(++i % 16)) printf("\n"); } if (i % 16) printf("\n"); } #endif #ifdef COMPILING_ON_WINDOWS if (WriteSerial(wstate.writebuf, wstate.wbindex) == COM_OK) { nwritten = wstate.wbindex; if (pfnProgressCallback != NULL) { progressInfo.nWritten += nwritten; (*pfnProgressCallback)(&progressInfo); } } else { MessageBox(GetFocus(), "Write error\n", "Angel", MB_OK | MB_ICONSTOP); return -1; /* SJ - This really needs to return a value, which is picked up in */ /* DevSW_Read as meaning stop debugger but don't kill. */ } #else nwritten = Unix_WriteSerial(wstate.writebuf, wstate.wbindex); if (nwritten < 0) { nwritten=0; } #endif #ifdef DEBUG if (nwritten > 0) printf("Wrote %#04x bytes\n", nwritten); #endif if ((unsigned) nwritten == wstate.wbindex && (testatus == TS_DONE_PKT || testatus == TS_IDLE)) { /* finished sending the packet */ #ifdef DEBUG printf("SerialWrite: calling Angel_TxEngineInit after sending packet (len=%i)\n",wstate.wbindex); #endif testatus = TS_IN_PKT; wstate.wbindex = 0; return 1; } else { #ifdef DEBUG printf("SerialWrite: Wrote part of packet wbindex=%i, nwritten=%i\n", wstate.wbindex, nwritten); #endif /* * still some data left to send shuffle whats left down and reset * the ptr */ memmove((char *) wstate.writebuf, (char *) (wstate.writebuf+nwritten), wstate.wbindex-nwritten); wstate.wbindex -= nwritten; return 0; } return -1; }