Esempio n. 1
0
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;
    }
}
Esempio n. 2
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;
}