예제 #1
0
파일: devsw.c 프로젝트: RodneyBates/M3Devel
/*
 *  Function: enqueue_packet
 *   Purpose: move a newly read packet onto the appropriate queue
 *              of read packets
 *
 *    Params:
 *      In/Out: ds      State structure with new packet
 *
 *   Returns: Nothing
 */
static void enqueue_packet(DevSWState *ds)
{
    struct data_packet *dp = &ds->ds_activeread.dc_packet;
    Packet *packet = ds->ds_nextreadpacket;

    /*
     * transfer the length
     */
    packet->pk_length = dp->len;

    /*
     * take this packet out of the incoming slot
     */
    ds->ds_nextreadpacket = NULL;

    /*
     * try to put it on the correct input queue
     */
    if (illegalDevChanID(dp->type))
    {
        /* this shouldn't happen */
        WARN("Illegal type for Rx packet");
        DevSW_FreePacket(packet);
    }
    else
        Adp_addToQueue(&ds->ds_readqueue[dp->type], packet);
}
예제 #2
0
파일: devsw.c 프로젝트: RodneyBates/M3Devel
AdpErrs DevSW_Close (DeviceDescr *device, const DevChanID type)
{
    DevSWState *ds = (DevSWState *)(device->SwitcherState);
    Packet *pk;

    if ((ds->ds_opendevchans & (1 << type)) == 0)
        return adp_device_not_open;

    ds->ds_opendevchans &= ~(1 << type);

    /*
     * if this is the last close for this channel, then inform the driver
     */
    if (ds->ds_opendevchans == 0)
        device->DeviceClose();

    /*
     * release all packets of the appropriate type
     */
    for (pk = Adp_removeFromQueue(&(ds->ds_readqueue[type]));
         pk != NULL;
         pk = Adp_removeFromQueue(&(ds->ds_readqueue[type])))
        DevSW_FreePacket(pk);

    /* Free memory */
    free ((char *) device->SwitcherState);
    device->SwitcherState = 0x0;

    /* that's all */
    return adp_ok;
}
예제 #3
0
/*
 *  Function: FireCallback
 *   Purpose: Pass received packet along to the callback routine for
 *              the appropriate channel
 *
 *    Params:
 *       Input: packet  The received packet.
 *
 *   Returns: Nothing
 *
 * Post-conditions: The Target-to-Host sequence number for the channel
 *                      will have been incremented.
 */
static void FireCallback(Packet *packet)
{
    ChannelID chan;
    struct Channel *ch;

    /*
     * is this a sensible channel number?
     */
    chan = *(packet->pk_buffer);
    if (invalidChannelID(chan))
    {
        printf("ERROR: invalid ChannelID received from target\n");

        /*
         * free the packet's resources, 'cause no-one else will
         */
        DevSW_FreePacket(packet);
        return;
    }

    /*
     * looks OK - increment sequence number, and pass packet to callback
     */
    ch = channels + chan;
    (ch->callback)(packet, ch->callback_state);
}
예제 #4
0
static AdpErrs check_seq(unsigned char msg_home, unsigned char msg_oppo) {
  Packet *tmp_pkt;

  UNUSED(msg_oppo);
  /*
   * check if we have got an ack for anything and if so remove it from the
   * queue
   */
  if (msg_home == (unsigned char)(OppoSeq + 1)) {
    /*
     * arrived in sequence can increment our opposing seq number and remove
     * the relevant packet from our queue
     * check that the packet we're going to remove really is the right one
     */
    tmp_pkt = writeQueueRoot;
    while ((tmp_pkt->pk_next != NULL) &&
           (tmp_pkt->pk_next->pk_buffer[CF_HOME_SEQ_BYTE_POS]
            != OppoSeq)){
      tmp_pkt = tmp_pkt->pk_next;
    }
    OppoSeq++;
    if (tmp_pkt->pk_next == NULL) {
#ifdef DEBUG
      printf("trying to remove a non existant packet\n");
#endif
      return adp_bad_packet;
    }
    else {
      Packet *tmp = tmp_pkt->pk_next;
#ifdef RET_DEBUG
      printf("removing a packet from the root queue\n");
#endif
      tmp_pkt->pk_next = tmp_pkt->pk_next->pk_next;
      /* remove the appropriate packet */
      DevSW_FreePacket(tmp);
    return adp_ok;
    }
  }
  else if (msg_home < (unsigned char) (OppoSeq+1)){
    /* already received this message */
#ifdef RET_DEBUG
    printf("sequence numbers low\n");
#endif
    return adp_seq_low;
  }
  else {  /* we've missed something */
#ifdef RET_DEBUG
    printf("sequence numbers high\n");
#endif
    return adp_seq_high;
  }
}
예제 #5
0
void Adp_initSeq( void ) {
  Packet *tmp_pkt = writeQueueSend;

  HomeSeq = 0;
  OppoSeq = 0;
  if ( writeQueueSend != NULL) {
    while (writeQueueSend->pk_next !=NULL) {
      tmp_pkt = writeQueueSend;
      writeQueueSend = tmp_pkt->pk_next;
      DevSW_FreePacket(tmp_pkt);
    }
  }
  tmp_pkt = writeQueueRoot;
  if ( writeQueueRoot == NULL)
    return;

  while (writeQueueRoot->pk_next !=NULL) {
    tmp_pkt = writeQueueRoot;
    writeQueueRoot = tmp_pkt->pk_next;
    DevSW_FreePacket(tmp_pkt);
  }
  return;
}
예제 #6
0
/*
 *  Function: DummyCallback
 *   Purpose: Default callback routine to handle unexpected input
 *              on a channel
 *
 *    Params:
 *       Input: packet  The received packet
 *
 *              state   Contains nothing of significance
 *
 *   Returns: Nothing
 */
static void DummyCallback(Packet *packet, void *state)
{
    ChannelID chan;
    const char fmt[] = "Unexpected read on channel %u, length %d\n";
    char fmtbuf[(sizeof(fmt) + 24)];

    UNUSED(state);

    chan = *(packet->pk_buffer);
    sprintf(fmtbuf, fmt, chan, packet->pk_length);
    printf("%s", fmtbuf);

    /*
     * junk this packet
     */
    DevSW_FreePacket(packet);
}
예제 #7
0
static void async_process_appl_read(void)
{
    Packet *packet;
    AdpErrs adp_err;

    /* see if there is anything for the DC_APPL channel */
    adp_err = DevSW_Read(deviceToUse, DC_APPL, &packet, FALSE);

    if (adp_err == adp_ok && packet != NULL)
    {
        /* got an application packet on a shared device */

#ifdef DEBUG
        printf("GOT DC_APPL PACKET: len %d\nData: ", packet->pk_length);
        {
            unsigned int c;
            for ( c = 0; c < packet->pk_length; ++c )
               printf( "%02X ", packet->pk_buffer[c] );
        }
        printf("\n");
#endif

        if (dc_appl_handler != NULL)
        {
            dc_appl_handler( deviceToUse, packet );
        }
        else
        {
            /* for now, just free it!! */
#ifdef DEBUG
            printf("no handler - dropping DC_APPL packet\n");
#endif
            DevSW_FreePacket( packet );
        }
    }
}
예제 #8
0
int HandleSysMessage(Packet *packet, hsys_state *stateptr)
{
  unsigned int reason_code, mode, len, c, nbytes, nbtotal, nbtogo = 0;
  long posn, fl;
  char character;
  int err;

  /* Note: We must not free the buffer passed in as the callback handler */
  /* expects to do this.  Freeing any other buffers we have malloced */
  /* ourselves is acceptable */

  unsigned char *buffp = ((unsigned char *)BUFFERDATA(packet->pk_buffer))+16;
                                          /* buffp points to the parameters*/
                                          /* the invidual messages, excluding*/
                                          /* standard SYS fields (debugID, */
                                          /* osinfo and reasoncode) */
  unsigned char *buffhead = (unsigned char *)(packet->pk_buffer);

  int DebugID, OSInfo1, OSInfo2, count;

  const char* fmode[] = {"r","rb","r+","r+b",
                               "w","wb","w+","w+b",
                               "a","ab","a+","a+b",
                               "r","r","r","r"} /* last 4 are illegal */ ;

  FILEHANDLE fh;  /* fh is used as an index to the real file handle
                         * in OSptr */  
  FILE *fhreal;
  unpack_message(BUFFERDATA(buffhead), "%w%w%w%w", &reason_code,
                 &DebugID, &OSInfo1, &OSInfo2);
                                        /* Extract reason code from buffer. */
  reason_code &= 0xFFFF;        /* Strip away direction bit, OSInfo and     */
                                /* DebugInfo fields.  Will want to do some  */
                                /* sort of validation on this later.        */
  
  switch(reason_code)
  {

  case CL_WriteC:   /* Write a character to the terminal. */
                    /* byte data -> word status           */
    {
#ifdef DEBUG
      int c = (int)(*buffp);
      printf("CL_WriteC: [%02x]>%c<", c, isprint(c) ? c : '.');
#endif
      stateptr->hostif->writec(stateptr->hostif->hostosarg, (int)(*buffp));
      DevSW_FreePacket(packet);
      return msgsend(CI_CLIB,"%w%w%w%w%w", CL_WriteC|HtoT,
                    DebugID, OSInfo1, OSInfo2, NoError);
    }

  case CL_Write0:  /* Write a null terminated string to the terminal. */
    {
      unpack_message(buffp, "%w", &len);
      DebugCheckNullTermString("CL_Write0", TRUE, len, buffp+4);
      stateptr->hostif->write(stateptr->hostif->hostosarg,
                              (char *) buffp+4, len);
      DevSW_FreePacket(packet);
      return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Write0|HtoT, DebugID, 
                    OSInfo1, OSInfo2, NoError);
    }

  case CL_ReadC:   /* Read a byte from the terminal */
    {
      DebugPrintF(("CL_ReadC: "));
      DevSW_FreePacket(packet);

      character = stateptr->hostif->readc(stateptr->hostif->hostosarg);
      DebugPrintF(("\nCL_ReadC returning [%02x]>%c<\n", character,
                   isprint(character) ? character : '.'));

      return msgsend(CI_CLIB, "%w%w%w%w%w%b", CL_ReadC|HtoT,
                    DebugID, OSInfo1, OSInfo2, NoError, character);
    }

  case CL_System:  /* Pass NULL terminated string to the hosts command 
                    * interpreter. As it is nULL terminated we dont need
                    * the length
                    */
    {
      unpack_message(buffp, "%w", &len);
      DebugCheckNullTermString("CL_System", TRUE, len, buffp+4);

      err = system((char *)buffp+4); /* Use the string in the buffer */
      stateptr->last_errno = errno;
      DebugCheckErr("system", TRUE, err, stateptr->last_errno);

      err = msgsend(CI_CLIB, "%w%w%w%w%w%w", CL_System|HtoT,
                    DebugID, OSInfo1, OSInfo2, NoError, err);
      DevSW_FreePacket(packet);
      return err;
    }

  case CL_GetCmdLine:  /* Returns the command line used to call the program */
    {
      /* Note: we reuse the packet here, this may not always be desirable */
      /* /* TODO: Use long buffers if possible */
      DebugPrintF(("CL_GetCmdLine: \"%s\"\n", *(stateptr->CommandLine)));

      if (buffhead!=NULL) {
        len = strlen(*(stateptr->CommandLine));
        if (len > Armsd_BufferSize-24) len = Armsd_BufferSize-24; 
        packet->pk_length = len + msgbuild(BUFFERDATA(buffhead),
                                           "%w%w%w%w%w%w", CL_GetCmdLine|HtoT,
                                           DebugID, OSInfo1, OSInfo2,
                                           NoError, len);
        strncpy((char *) BUFFERDATA(buffhead)+24,*(stateptr->CommandLine),
                len);
        
        Adp_ChannelWrite(CI_CLIB, packet);/* Send message. */
        return 0;
      }
      else return -1;
    }

  case CL_Clock:   /* Return the number of centiseconds since the support */
                   /* code started executing */
    {
      time_t retTime = time(NULL);
      if (retTime == (time_t)-1)
             stateptr->last_errno = errno;
      else
             retTime *=100;

      DebugPrintF(("CL_Clock: %lu\n", retTime));
      DebugCheckErr("time", TRUE, (retTime == (time_t)-1),
                    stateptr->last_errno);

      DevSW_FreePacket(packet);
      return msgsend(CI_CLIB, "%w%w%w%w%w%w",CL_Clock|HtoT,
                         DebugID, OSInfo1, OSInfo2, NoError, retTime);
    }

  case CL_Time:    /* return time, in seconds since the start of 1970 */
    {
      time_t retTime = time(NULL);
      if (retTime == (time_t)-1)
              stateptr->last_errno = errno;

      DebugPrintF(("CL_Time: %lu\n", retTime));
      DebugCheckErr("time", TRUE, (retTime == (time_t)-1),
                    stateptr->last_errno);

      DevSW_FreePacket(packet);
      return msgsend(CI_CLIB,"%w%w%w%w%w%w",CL_Time|HtoT,
                         DebugID, OSInfo1, OSInfo2, NoError, retTime);
    }

  case CL_Remove:  /* delete named in the null terminated string */
    {
      /* Removing an open file will cause problems but once again
       * its not our problem, likely result is a tangled FileTable */
      /* As the filename is passed with a null terminator we can use it
       * straight out of the buffer without copying it.*/

      unpack_message(buffp, "%w", &len);
      DebugCheckNullTermString("CL_Remove", TRUE, len, buffp+4);

      err=remove((char *)buffp+4);
      stateptr->last_errno = errno;
      DevSW_FreePacket(packet);
      DebugCheckErr("remove", TRUE, err, stateptr->last_errno);

      return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Remove|HtoT,
                     DebugID, OSInfo1, OSInfo2, err?-1:NoError);
    }

  case CL_Rename:  /* rename file */
    {
      /* Rename(word nbytes, bytes oname, word nbytes, bytes nname)
      * return(byte status)
      */
      unsigned int len2;

      unpack_message(buffp, "%w", &len);
      DebugCheckNullTermString("CL_Rename", FALSE, len, buffp+4);
      unpack_message(buffp+5+len, "%w", &len2);
      DebugCheckNullTermString("to", TRUE, len2, buffp+9+len);

      /* Both names are passed with null terminators so we can use them
       * directly from the buffer. */
      err = rename((char *)buffp+4, (char *)buffp+9+len);
      stateptr->last_errno = errno;
      DebugCheckErr("rename", TRUE, err, stateptr->last_errno);
      DevSW_FreePacket(packet);

      return msgsend(CI_CLIB, "%w%w%w%w%w",  CL_Rename|HtoT,
                     DebugID, OSInfo1, OSInfo2, (err==0)? NoError : -1);
    }
  
  case CL_Open:    /* open the file */
    {
      /* Open(word nbytes, bytes name, byte mode)
      * return(word handle)
      */
      unpack_message(buffp, "%w", &len);
      /* get the open mode */
      unpack_message((buffp)+4+len+1, "%w", &mode);
      DebugCheckNullTermString("CL_Open", FALSE, len, buffp+4);
      DebugPrintF(("mode: %d\n", mode));

      /* do some checking on the file first? */
      /* check if its a tty */
      if (strcmp((char *)buffp+4, ":tt")==0 && (mode==0||mode==1)) {
        /* opening tty "r" */
        fhreal = stdin;
        stateptr->last_errno = errno;
        DebugPrintF(("\tstdin "));
      }
      else if (strcmp((char *)buffp+4, ":tt")== 0 && (mode==4||mode==5)) {
        /* opening tty "w" */
        fhreal = stdout;
        stateptr->last_errno = errno;
        DebugPrintF(("\tstdout "));
      }
      else
      {
        fhreal = fopen((char *)buffp+4, fmode[mode&0xFF]);
        stateptr->last_errno = errno;
        DebugCheckNonNull("fopen", FALSE, fhreal, stateptr->last_errno);
      }
      DevSW_FreePacket(packet);

      c = NONHANDLE;
      if (fhreal != NULL) {
        /* update filetable */
        for (c=3; c < HSYS_FOPEN_MAX; c++) {
          /* allow for stdin, stdout, stderr (!!! WHY? MJG) */
          if (stateptr->OSptr->FileTable[c] == NULL) {
            stateptr->OSptr->FileTable[c]= fhreal;
            stateptr->OSptr->FileFlags[c]= mode & 1;
            DebugPrintF(("fh: %d\n", c));
            break;
          }
          else if (c == HSYS_FOPEN_MAX) {
          /* no filehandles free */
          DebugPrintF(("no free fh: %d\n", c));
          stateptr->last_errno = EMFILE;
          }
        }
      }
      else {
        /*        c = NULL;*/
        DebugPrintF(("error fh: %d\n", c));
      }
      (void) msgsend(CI_CLIB, "%w%w%w%w%w",  CL_Open|HtoT,
                     DebugID, OSInfo1, OSInfo2, c);
      return 0;
    }

  case CL_Close:   /* close the file pointed to by the filehandle */
    {
      unpack_message(buffp, "%w", &fh);
      DebugPrintF(("CL_Close: fh %d\n", fh));
      DevSW_FreePacket(packet);

      fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
      if (fhreal == NULL)
         err = -1;
      else {
          if (fhreal == stdin || fhreal == stdout || fhreal == stderr) {
              stateptr->last_errno = errno;
              DebugPrintF(("\tskipping close of std*\n"));
              err = 0;
          }
          else {
              err = fclose(fhreal);
              if (err == 0)
                 stateptr->OSptr->FileTable[fh]=NULL;
              stateptr->last_errno = errno;
              DebugCheckErr("fclose", TRUE, err, stateptr->last_errno);
          }
      }
      return msgsend(CI_CLIB,"%w%w%w%w%w",  CL_Close|HtoT, DebugID,
                     OSInfo1, OSInfo2, err);
    }

  case CL_Write:
    {
        /* Write(word handle, word nbtotal, word nbytes, bytes data)
         * return(word nbytes)
         * WriteX(word nbytes, bytes data)
         * return(word nbytes)
         */
      unsigned char *rwdata = NULL, *rwhead = NULL;
      unsigned char *write_source = NULL;
      char flags;
      FILE *fhreal;
      unsigned int ack_reason = CL_Write; /* first ack is for CL_Write */

      err = -1;                 /* err == 0 is fwrite() error indication */
      unpack_message(buffp, "%w%w%w", &fh, &nbtotal, &nbytes); 
      DebugPrintF(("CL_Write: fh %d nbtotal %u nbytes %u\n",
                   fh, nbtotal, nbytes));

      fhreal = hsysGetRealFileHandle(stateptr, fh, &flags);
      nbtogo = nbtotal;

      /* deal with the file handle */
      if (fhreal == NULL)
         err = 0;
      else {
        if (flags & READOP)
           fseek(fhreal,0,SEEK_CUR);
        stateptr->OSptr->FileFlags[fh] = (flags & BINARY) | WRITEOP;

        nbtogo -= nbytes;

        if (nbtogo > 0) {
          write_source = rwdata = rwhead = (unsigned char *)malloc(nbtotal);
          if (rwhead == NULL) {
            fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
                    __LINE__, __FILE__);
            return -1;
          }
          memcpy(rwdata, buffp+12, nbytes);
          rwdata += nbytes;
        }
        else
           write_source = buffp+12;
      }

      do {
        /* at least once!! */

        if (nbtogo == 0 && err != 0) {
          /* Do the actual write! */
          if (fhreal == stdout || fhreal == stderr) {
            stateptr->hostif->write(stateptr->hostif->hostosarg,
                                    (char *)write_source, nbtotal);
          }
          else 
             err = fwrite(write_source, 1, nbtotal, fhreal);
          stateptr->last_errno = errno;
          DebugCheckErr("fwrite", TRUE, (err == 0), stateptr->last_errno);
        }

        DevSW_FreePacket(packet);
        if (msgsend(CI_CLIB,"%w%w%w%w%w%w", ack_reason|HtoT,
                    DebugID, OSInfo1, OSInfo2, (err == 0), nbtogo))
        {
            fprintf(stderr, "COULD NOT REPLY at line %d in %s\n",
                    __LINE__, __FILE__);
            if (rwhead != NULL)
               free(rwhead);
            return -1;
        }

        if (nbtogo == 0 || err == 0) {
          DebugPrintF(("\twrite complete - returning\n"));
          if (rwhead != NULL)
             free(rwhead);
          return 0;
        }
        else {
          /* await extension */
          ack_reason = CL_WriteX;

          packet = DevSW_AllocatePacket(Armsd_BufferSize);
          if (packet == NULL)
          {
            fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
                    __LINE__, __FILE__);
            if (rwhead != NULL)
               free(rwhead);
            return -1;
          }
          Adp_ChannelRegisterRead(CI_CLIB, NULL, NULL);
          Adp_ChannelRead(CI_CLIB, &packet);
          Adp_ChannelRegisterRead(CI_CLIB,
                                  (ChannelCallback)HandleSysMessage,
                                  stateptr);

          buffhead = packet->pk_buffer;
          unpack_message(BUFFERDATA(buffhead), "%w%w%w%w%w", &reason_code,
                         &DebugID, &OSInfo1, &OSInfo2, &nbytes); 
          if (reason_code != (CL_WriteX|TtoH)) {
            DevSW_FreePacket(packet);
            free(rwhead);
            fprintf(stderr, "EXPECTING CL_WriteX GOT %u at line %d in %s\n",
                    reason_code, __LINE__, __FILE__);
            return -1;
          }

          DebugPrintF(("CL_WriteX: nbytes %u\n", nbytes));
          memcpy(rwdata, BUFFERDATA(buffhead)+20, nbytes);
          rwdata += nbytes;
          nbtogo -= nbytes;
        }

      } while (TRUE);           /* will return when done */
    }

  case CL_WriteX:     /*
                       * NOTE: if we've got here something has gone wrong
                       * CL_WriteX's should all be picked up within the
                       * CL_Write loop, probably best to return an error here
                       * do this for the moment just so we do actually return
                       */
    fprintf(stderr, "ERROR: unexpected CL_WriteX message received\n");
    return -1; 

  case CL_Read:
    {
                   /* Read(word handle, word nbtotal)
                    * return(word nbytes, word nbmore, bytes data)
                    */
                   /* ReadX()
                    * return(word nbytes, word nbmore, bytes data) */
      unsigned char *rwdata, *rwhead;
      int gotlen;
      unsigned int max_data_in_buffer=Armsd_BufferSize-28;
      char flags;
      FILE *fhreal;
      unsigned int nbleft = 0, reason = CL_Read;

      err = NoError;

      unpack_message(buffp, "%w%w", &fh, &nbtotal);
      DebugPrintF(("CL_Read: fh %d, nbtotal %d: ", fh, nbtotal));

      rwdata = rwhead = (unsigned char *)malloc(nbtotal);
      if (rwdata == NULL) {
        fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
                __LINE__, __FILE__);
        DevSW_FreePacket(packet);
        return -1;
      }

      /* perform the actual read */
      fhreal = hsysGetRealFileHandle(stateptr, fh, &flags);
      if (fhreal == NULL)
      {
        /* bad file handle */
        err = -1;
        nbytes = 0;
        gotlen = 0;
      }
      else
      {
        if (flags & WRITEOP)
          fseek(fhreal,0,SEEK_CUR);
        stateptr->OSptr->FileFlags[fh] = (flags & BINARY) | WRITEOP;
        if (isatty_(fhreal)) {
          /* reading from a tty, so do some nasty stuff, reading into rwdata */
          if (angel_hostif->gets(stateptr->hostif->hostosarg, (char *)rwdata,
                                 nbtotal) != 0)
             gotlen = strlen((char *)rwdata);
          else
             gotlen = 0;
          stateptr->last_errno = errno;
          DebugPrintF(("ttyread %d\n", gotlen));
        }
        else {
          /* not a tty, reading from a real file */
          gotlen = fread(rwdata, 1, nbtotal, fhreal);
          stateptr->last_errno = errno;
          DebugCheckErr("fread", FALSE, (gotlen == 0), stateptr->last_errno);
          DebugPrintF(("(%d)\n", gotlen));
        }
      }

      nbtogo = gotlen;

      do {
        /* at least once */

        if ((unsigned int) nbtogo <= max_data_in_buffer)
           nbytes = nbtogo;
        else
           nbytes = max_data_in_buffer;
        nbtogo -= nbytes;

        /* last ReadX needs subtle adjustment to returned nbtogo */
        if (nbtogo == 0 && err == NoError && reason == CL_ReadX)
           nbleft = nbtotal - gotlen;
        else
           nbleft = nbtogo;

        count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w%w%w",
                         reason|HtoT, 0, ADP_HandleUnknown,
                         ADP_HandleUnknown, err, nbytes, nbleft);

        if (err == NoError) {
          /* copy data into buffptr */   
          memcpy(BUFFERDATA(buffhead)+28, rwdata, nbytes);
          rwdata += nbytes;
          count += nbytes;
        }

        DebugPrintF(("\treplying err %d, nbytes %d, nbtogo %d\n",
                     err, nbytes, nbtogo));

        packet->pk_length = count;
        Adp_ChannelWrite(CI_CLIB, packet);

        if (nbtogo == 0 || err != NoError) {
          /* done */
          free(rwhead);
          return 0;
        }
        else {
          /* await extension */
          reason = CL_ReadX;

          packet = DevSW_AllocatePacket(Armsd_BufferSize);
          if (packet == NULL) {
            fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
                    __LINE__, __FILE__);
            free(rwhead);
            return -1;
          }
          Adp_ChannelRegisterRead(CI_CLIB, NULL, NULL);
          Adp_ChannelRead(CI_CLIB, &packet);
          Adp_ChannelRegisterRead(CI_CLIB,
                                  (ChannelCallback)HandleSysMessage,
                                  stateptr);
          buffhead = packet->pk_buffer;
          unpack_message(BUFFERDATA(buffhead),"%w", &reason_code);
          if (reason_code != (CL_ReadX|TtoH)) {
            fprintf(stderr, "EXPECTING CL_ReadX GOT %u at line %d in %s\n",
                    reason_code, __LINE__, __FILE__);
            DevSW_FreePacket(packet);
            free(rwdata);
            return -1;
          }
        }

      } while (TRUE);           /* will return above on error or when done */
    }

  case CL_ReadX:      /* If we're here something has probably gone wrong */
    fprintf(stderr, "ERROR: Got unexpected CL_ReadX message\n");
    return -1;

  case CL_Seek:
    {
      unpack_message(buffp, "%w%w", &fh, &posn);
      DebugPrintF(("CL_Seek: fh %d, posn %ld\n", fh, posn));
      DevSW_FreePacket(packet);

      fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
      if (fhreal == NULL)
         err = -1;
      else {
        err = fseek(fhreal, posn, SEEK_SET); 
        stateptr->last_errno = errno;
        DebugCheckErr("fseek", TRUE, err, stateptr->last_errno);
      }

      return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Seek|HtoT, 
                         DebugID, OSInfo1, OSInfo2, err);
    }

  case CL_Flen:
    {
      unpack_message(buffp, "%w", &fh);
      DebugPrintF(("CL_Flen: fh %d ", fh));
      DevSW_FreePacket(packet);

      fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
      if (fhreal == NULL)
        fl = -1;
      else {
        posn = ftell(fhreal);
        if (fseek(fhreal, 0L, SEEK_END) < 0) {
          fl=-1;
        }
        else {
          fl = ftell(fhreal);
          fseek(fhreal, posn, SEEK_SET);
        }
        stateptr->last_errno = errno;
      }
      DebugPrintF(("returning len %ld\n", fl));
      return msgsend(CI_CLIB, "%w%w%w%w%w", CL_Flen|HtoT, DebugID, OSInfo1,
                     OSInfo2, fl);
    } 

  case CL_IsTTY:
    {
      int  ttyOrNot;
      unpack_message(buffp, "%w", &fh);
      DebugPrintF(("CL_IsTTY: fh %d ", fh));
      DevSW_FreePacket(packet);

      fhreal = hsysGetRealFileHandle(stateptr, fh, NULL);
      if (fhreal == NULL)
         ttyOrNot = FALSE;
      else {
        ttyOrNot = isatty_(fhreal);
        stateptr->last_errno = errno;
      }
      DebugPrintF(("returning %s\n", ttyOrNot ? "tty (1)" : "not (0)"));

      return msgsend(CI_CLIB, "%w%w%w%w%w",CL_IsTTY|HtoT, 
                         DebugID, OSInfo1, OSInfo2, ttyOrNot);
    }

  case CL_TmpNam:
    {
      char *name;
      unsigned int tnamelen, TargetID;
      unpack_message(buffp, "%w%w", &tnamelen, &TargetID); 
      DebugPrintF(("CL_TmpNam: tnamelen %d TargetID %d: ",
                   tnamelen, TargetID));
      DevSW_FreePacket(packet);

      TargetID = TargetID & 0xFF;
      if (stateptr->OSptr->TempNames[TargetID] == NULL) {
        if ((stateptr->OSptr->TempNames[TargetID] =
             (char *)malloc(L_tmpnam)) == NULL)
        {
          fprintf(stderr, "OUT OF MEMORY at line %d in %s\n",
                  __LINE__, __FILE__);
          return -1;
        }
        tmpnam(stateptr->OSptr->TempNames[TargetID]);
      }
      name = stateptr->OSptr->TempNames[TargetID];
      len = strlen(name) + 1;
      packet = DevSW_AllocatePacket(Armsd_BufferSize);
      if (packet == NULL)
      {
          fprintf(stderr, "COULD NOT ALLOC PACKET at line %d in %s\n",
                  __LINE__, __FILE__);
          return -1;
      }
      buffhead = packet->pk_buffer;
      if (len > tnamelen) {
        DebugPrintF(("TMPNAME TOO LONG!\n"));
        count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w",
                           CL_TmpNam|HtoT, DebugID, OSInfo1, OSInfo2, -1);
      }
      else {
        DebugPrintF(("returning \"%s\"\n", name));
        count = msgbuild(BUFFERDATA(buffhead), "%w%w%w%w%w%w", CL_TmpNam|HtoT,
                         DebugID, OSInfo1, OSInfo2, 0, len);
        strcpy((char *)BUFFERDATA(buffhead)+count, name);
        count +=len+1;
      }
      packet->pk_length = count;
      Adp_ChannelWrite(CI_CLIB, packet);/* Send message. */
      return 0;
    }

  case CL_Unrecognised:
    DebugPrintF(("CL_Unrecognised!!\n"));
    return 0;

  default:
    fprintf(stderr, "UNRECOGNISED CL code %08x\n", reason_code);
    break;
/* Need some sort of error handling here. */
/* A call to CL_Unrecognised should suffice */
  }
  return -1;  /* Stop a potential compiler warning */
}
예제 #9
0
static void async_process_write( const AsyncMode mode,
                                 bool *const finished  )
{
    Packet *packet;

#ifdef DEBUG
    static unsigned int num_written = 0;
#endif

    /*
     * NOTE: here we rely in the fact that any packet in the writeQueueSend
     * section of the queue will need its sequence number setting up while
     * and packet in the writeQueueRoot section will have its sequence
     * numbers set up from when it was first sent so we can easily look
     * up the packet numbers when(if) we want to resend the packet.
     */

#ifdef DEBUG
    if (writeQueueSend!=NULL)
       printf("written 0x%x\n",num_written += writeQueueSend->pk_length);
#endif
    /*
     * give the switcher a chance to complete any partial writes
     */
    if (DevSW_FlushPendingWrite(deviceToUse) == adp_write_busy)
    {
        /* no point trying a new write */
        return;
    }

    /*
     * now see whether there is anything to write
     */
    packet = NULL;
    if (resending) {
        packet = resend_pkt;
#ifdef RET_DEBUG
        printf("resending hseq 0x%x oseq 0x%x\n",
               packet->pk_buffer[CF_HOME_SEQ_BYTE_POS],
               packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS]);
#endif
    }
    else if (writeQueueSend != NULL) {
#ifdef RETRANS
        /* set up the sequence number on the packet */
        packet = writeQueueSend;
        HomeSeq++;
        (writeQueueSend->pk_buffer[CF_OPPO_SEQ_BYTE_POS])
            = OppoSeq;
        (writeQueueSend->pk_buffer[CF_HOME_SEQ_BYTE_POS])
            = HomeSeq;
        (writeQueueSend->pk_buffer[CF_FLAGS_BYTE_POS])
            = CF_RELIABLE;
# ifdef RET_DEBUG
        printf("sending packet with hseq 0x%x oseq 0x%x\n",
               writeQueueSend->pk_buffer[CF_HOME_SEQ_BYTE_POS],
               writeQueueSend->pk_buffer[CF_OPPO_SEQ_BYTE_POS]);
# endif
#endif /* RETRANS */
    }

    if (packet != NULL) {
        AdpErrs dev_err;

#ifdef FAKE_BAD_LINE_TX
        fake_bad_line_tx();
#endif

        dev_err = DevSW_Write(deviceToUse, packet, DC_DBUG);
        if (dev_err == adp_ok) {
#ifdef RETRANS
            if (resending) {
                /* check to see if we've recovered yet */
                if ((packet->pk_next) == NULL){
# ifdef RET_DEBUG
                    printf("we have recovered\n");
# endif
                    resending = FALSE;
                }
                else {
                    resend_pkt = resend_pkt->pk_next;
                }
            }
            else {
                /*
                 * move the packet we just sent from the send queue to the root
                 */
                Packet *tmp_pkt, *tmp;

# ifdef FAKE_BAD_LINE_TX
                unfake_bad_line_tx();
# endif

                tmp_pkt = writeQueueSend;
                writeQueueSend = writeQueueSend->pk_next;
                tmp_pkt->pk_next = NULL;
                if (writeQueueRoot == NULL)
                   writeQueueRoot = tmp_pkt;
                else {
                    tmp = writeQueueRoot;
                    while (tmp->pk_next != NULL) {
                        tmp = tmp->pk_next;
                    }
                    tmp->pk_next = tmp_pkt;
                }
            }
#else  /* not RETRANS */
            /*
             * switcher has taken the write, so remove it from the
             * queue, and free its resources
             */
            DevSW_FreePacket(Adp_removeFromQueue(&writeQueueSend));
#endif /* if RETRANS ... else ... */

            if (mode == async_block_on_write)
               *finished = DevSW_WriteFinished(deviceToUse);

        } /* endif write ok */
    }
    else /* packet == NULL */
    {
        if (mode == async_block_on_write)
           *finished = DevSW_WriteFinished(deviceToUse);
    }
}
예제 #10
0
static void async_process_dbug_read(const AsyncMode mode, bool *const finished)
{
    Packet *packet;
    unsigned int msg_home, msg_oppo;
    AdpErrs adp_err;

    adp_err = DevSW_Read(deviceToUse, DC_DBUG, &packet,
                         mode == async_block_on_read);

#ifdef FAKE_BAD_LINE_RX
    adp_err = fake_bad_line_rx(packet, adp_err);
#endif /* FAKE_BAD_LINE_RX */

    if (adp_err == adp_bad_packet) {
        /* We got a bad packet, ask for a resend, send a resend message */
#ifdef DEBUG
        printf("received a bad packet\n");
#endif /* DEBUG */
        send_resend_msg(DC_DBUG);
    } else if (packet != NULL) {
        /* update the heartbeat clock */
        gettimeofday(&time_lastalive, NULL);

	/*
	 * we got a live one here - were we waiting for it?
	 */
	if (mode == async_block_on_read) {
           /* not any more */
           *finished = TRUE;
	}
#ifdef RETRANS

        if (packet->pk_length < CF_DATA_BYTE_POS) {
            /* we have got a packet with no header information! */
            printf("ERROR: packet with no transport header\n");
            send_resend_msg(DC_DBUG);
        } else {
# ifdef RET_DEBUG
            unsigned int c;
# endif /* RET_DEBUG */
            /*
             * TODO: Check to see if its acknowledgeing anything, remove
             * those packets it is from the queue.  If it is a retrans, add the
             * packets to the queue
             */
            msg_home = packet->pk_buffer[CF_HOME_SEQ_BYTE_POS];
            msg_oppo = packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS];
# ifdef RET_DEBUG
            printf("msg seq numbers are hseq 0x%x oseq 0x%x\n",
                   msg_home, msg_oppo);
	    for ((c = 0); (c < packet->pk_length); c++) {
               printf("%02.2x", packet->pk_buffer[c]);
	    }
            printf("\n");
# endif /* RET_DEBUG */
            /* now was it a resend request? */
            if ((packet->pk_buffer[CF_FLAGS_BYTE_POS])
                & CF_RESEND) {
                /* we have been asked for a resend, so we had better resend */
                /*
                 * I do NOT think we can use a resend as acknowledgement for
                 * anything, so let us NOT do this for the moment:
                 * check_seq(msg_home, msg_oppo);
                 */
# ifdef RET_DEBUG
                printf("received a resend request\n");
# endif /* RET_DEBUG */
                if (HomeSeq != msg_oppo) {
                    int found = FALSE;
                    /* need to resend from msg_oppo +1 upwards */
                    DevSW_FreePacket(packet);
                    resending = TRUE;
                    /* find the correct packet to resend from */
                    packet = writeQueueRoot;
                    while (((packet->pk_next) != NULL) && !found) {
                        if ((packet->pk_buffer[CF_OPPO_SEQ_BYTE_POS])
                            != msg_oppo+1) {
                            resend_pkt = packet;
                            found = TRUE;
                        }
                        packet = packet->pk_next;
                    }
                    if (!found) {
                        panic("trying to resend non-existent packets\n");
                    }
                } else if (OppoSeq != msg_home) {
                    /*
                     * send a resend request telling the target where we think
                     * the world is at
                     */
                    DevSW_FreePacket(packet);
                    send_resend_msg(DC_DBUG);
                }
            } else {
                /* not a resend request, let us check the sequence numbers */

                if ((packet->pk_buffer[CF_CHANNEL_BYTE_POS] != CI_HBOOT) &&
                    (packet->pk_buffer[CF_CHANNEL_BYTE_POS] != CI_TBOOT)) {
                    adp_err = check_seq((unsigned char)msg_home,
					(unsigned char)msg_oppo);
                    if (adp_err == adp_seq_low) {
                        /* we have already received this packet so discard */
                        DevSW_FreePacket(packet);
                    } else if (adp_err == adp_seq_high) {
                        /*
                         * we must have missed a packet somewhere, discard this
                         * packet and tell the target where we are
                         */
                        DevSW_FreePacket(packet);
                        send_resend_msg(DC_DBUG);
                    } else {
                       /*
                        * now pass the packet to whoever is waiting for it
                        */
                       FireCallback(packet);
		    }
                } else {
                   FireCallback(packet);
		}
            }
        }
#else
	/*
	 * now pass the packet to whoever is waiting for it
	 */
        FireCallback(packet);
#endif /* RETRANS */
    }
}