Beispiel #1
0
/* Accept a TCP connection */
static int vtty_tcp_conn_accept(vtty_t *vtty, int nsock)
{
   int fd,*fd_slot;
   u_int i;
   
   if (fd_pool_get_free_slot(&vtty->fd_pool,&fd_slot) < 0) {
      vm_error(vtty->vm,"unable to create a new VTTY TCP connection\n");
      return(-1);
   }
   
   if ((fd = accept(vtty->fd_array[nsock],NULL,NULL)) < 0) {
      vm_error(vtty->vm,"vtty_tcp_conn_accept: accept on port %d failed %s\n",
              vtty->tcp_port,strerror(errno));
      return(-1);
   }

   /* Register the new FD */
   *fd_slot = fd;

   vm_log(vtty->vm,"VTTY","%s is now connected (accept_fd=%d,conn_fd=%d)\n",
          vtty->name,vtty->fd_array[nsock],fd);

   /* Adapt Telnet settings */
   if (vtty->terminal_support) {      
      vtty_telnet_do_ttype(fd);
      vtty_telnet_will_echo(fd);
      vtty_telnet_will_suppress_go_ahead(fd);
      vtty_telnet_dont_linemode(fd);
      vtty->input_state = VTTY_INPUT_TEXT;
   }

   if (telnet_message_ok == 1) {
      fd_printf(fd,0,
                "Connected to Dynamips VM \"%s\" (ID %u, type %s) - %s\r\n"
                "Press ENTER to get the prompt.\r\n", 
                vtty->vm->name, vtty->vm->instance_id, vm_get_type(vtty->vm),
                vtty->name);
      /* replay old text */
      for (i = vtty->replay_ptr; i < VTTY_BUFFER_SIZE; i++) {
         if (vtty->replay_buffer[i] != 0) {
            send(fd,&vtty->replay_buffer[i],VTTY_BUFFER_SIZE-i,0);
            break;
         }
      }
      for (i = 0; i < vtty->replay_ptr; i++) {
         if (vtty->replay_buffer[i] != 0) {
            send(fd,&vtty->replay_buffer[i],vtty->replay_ptr-i,0);
            break;
         }
      }
      /* warn if not running */
      if (vtty->vm->status != VM_STATUS_RUNNING)
         fd_printf(fd,0,"\r\n!!! WARNING - VM is not running, will be unresponsive (status=%d) !!!\r\n",vtty->vm->status);
      vtty_flush(vtty);
   }
   return(0);
}
Beispiel #2
0
/* Put a buffer to vtty */
void vtty_put_buffer(vtty_t *vtty,char *buf,size_t len)
{
   size_t i;

   for(i=0;i<len;i++)
      vtty_put_char(vtty,buf[i]);
   
   vtty_flush(vtty);
}
Beispiel #3
0
/* VTTY thread */
static void *vtty_thread_main(void *arg)
{
   vtty_t *vtty;
   struct timeval tv;
   int fd_max,fd_tcp,res;
   fd_set rfds;
   int i;

   for(;;) {
      VTTY_LIST_LOCK();

      /* Build the FD set */
      FD_ZERO(&rfds);
      fd_max = -1;
      for(vtty=vtty_list;vtty;vtty=vtty->next) {

          switch(vtty->type) {
              case VTTY_TYPE_TCP:

                  for(i=0;i<vtty->fd_count;i++)
                      if (vtty->fd_array[i] != -1) {
                          FD_SET(vtty->fd_array[i],&rfds);
                          if (vtty->fd_array[i] > fd_max)
                              fd_max = vtty->fd_array[i];
                      }

                  fd_tcp = fd_pool_set_fds(&vtty->fd_pool,&rfds);
                  fd_max = m_max(fd_tcp,fd_max);
                  break;

              default:
                  if (vtty->fd_array[0] != -1) {
                      FD_SET(vtty->fd_array[0],&rfds);
                      fd_max = m_max(vtty->fd_array[0],fd_max);
                  }
          }

      }
      VTTY_LIST_UNLOCK();

      /* Wait for incoming data */
      tv.tv_sec  = 0;
      tv.tv_usec = 50 * 1000;  /* 50 ms */
      res = select(fd_max+1,&rfds,NULL,NULL,&tv);

      if (res == -1) {
         if (errno != EINTR) {
            perror("vtty_thread: select");
         }
         continue;
      }

      /* Examine active FDs and call user handlers */
      VTTY_LIST_LOCK();
      for(vtty=vtty_list;vtty;vtty=vtty->next) {

         switch(vtty->type) {
            case VTTY_TYPE_TCP:

               /* check incoming connection */
               for(i=0;i<vtty->fd_count;i++) {
                   
                   if (vtty->fd_array[i] == -1)
                       continue;
                   
                   if (!FD_ISSET(vtty->fd_array[i],&rfds))
                       continue;
                   
                   vtty_tcp_conn_accept(vtty, i);
               }

               /* check established connection */
               fd_pool_check_input(&vtty->fd_pool,&rfds,vtty_tcp_input,vtty);
               break;
      
            /* Term, Serial */
            default:
               if (vtty->fd_array[0] != -1 && FD_ISSET(vtty->fd_array[0],&rfds)) {
                  vtty_read_and_store(vtty,&vtty->fd_array[0]);
                  vtty->input_pending = TRUE;
               }
         }
         
         if (vtty->input_pending) {
            if (vtty->read_notifier != NULL)
               vtty->read_notifier(vtty);

            vtty->input_pending = FALSE;
         }

         /* Flush any pending output */
         if (!vtty->managed_flush)
            vtty_flush(vtty);
      }
      VTTY_LIST_UNLOCK();
   }
   
   return NULL;
}
Beispiel #4
0
/*
 * dev_ns16552_access()
 */
void *dev_ns16552_access(cpu_gen_t *cpu,struct vdevice *dev,m_uint32_t offset,
                         u_int op_size,u_int op_type,m_uint64_t *data)
{
   struct ns16552_data *d = dev->priv_data;
   int channel = 0;
   u_char odata;

   if (op_type == MTS_READ)
      *data = 0;

#if DEBUG_ACCESS
   if (op_type == MTS_READ) {
      cpu_log(cpu,"NS16552","read from 0x%x, pc=0x%llx\n",
              offset,cpu_get_pc(cpu));
   } else {
      cpu_log(cpu,"NS16552","write to 0x%x, value=0x%llx, pc=0x%llx\n",
              offset,*data,cpu_get_pc(cpu));
   }
#endif

   offset >>= d->reg_div;

   if (offset >= 0x08)
      channel = 1;

// From the NS16552V datasheet, the following is known about the registers
// Bit 4 is channel
// Value 0 Receive or transmit buffer
// Value 1 Interrupt enable
// Value 2 Interrupt identification (READ), FIFO Config (Write)
// Value 3 Line Control (Appears in IOS)
//    0x1 - Word Length Selector bit 0
//    0x2 - Word Length Selector bit 1
//    0x4 - Num stop bits
//    0x8 - Parity Enable
//    0x16 - Parity even
//    0x32 - Stick Parity
//    0x64 - Set Break
//    0x128 - Division Latch
// Value 4 Modem Control (Appears in IOS)
// Value 5 Line status
// Value 6 Modem Status
// Value 7 Scratch
	  
   switch(offset) {
      /* Receiver Buffer Reg. (RBR) / Transmitting Holding Reg. (THR) */
      case 0x00:
      case 0x08:
         if (d->div_latch == 0) {
           if (op_type == MTS_WRITE) {
              vtty_put_char(d->channel[channel].vtty,(char)*data);
  
              if (d->channel[channel].ier & IER_ETXRDY)
                 vm_set_irq(d->vm,d->irq);
  
              d->channel[channel].output = TRUE;
           } else
              *data = vtty_get_char(d->channel[channel].vtty);
         } else {
           if (op_type == MTS_WRITE)
             d->baud_divisor = ((*data) & 0x00ff) | (d->baud_divisor & 0xff00);
         }
         break;

      /* Interrupt Enable Register (IER) */
      case 0x01:
      case 0x09:
         if (d->div_latch == 0) {
           if (op_type == MTS_READ) {
              *data = d->channel[channel].ier;
           } else {
              d->channel[channel].ier = *data & 0xFF;

              if ((*data & 0x02) == 0) {   /* transmit holding register */
                 d->channel[channel].vtty->managed_flush = TRUE;
                 vtty_flush(d->channel[channel].vtty);               
              }
           }
         } else {
           if (op_type == MTS_WRITE)
              d->baud_divisor = (((*data) & 0xff)<<8)|(d->baud_divisor & 0xff);
         }
         break;

      /* Interrupt Ident Register (IIR) */
      case 0x02:
      case 0x0A:
         if (d->div_latch == 0) {
           vm_clear_irq(d->vm,d->irq);
           if (op_type == MTS_READ) {
             odata = IIR_NPENDING;

             if (vtty_is_char_avail(d->channel[channel].vtty)) {
               odata = IIR_RXRDY;
             } else {
               if (d->channel[channel].output) {
                  odata = IIR_TXRDY;
                  d->channel[channel].output = 0;
               }
             }

             *data = odata;
           }
         }
         break;
      case 0x03:
      case 0x0B:
         if (op_type == MTS_READ) {
           *data = d->line_control_reg;
         } else {

           d->line_control_reg = (uint)*data;
           uint bits = 5;
           __maybe_unused char *stop = "1";
           __maybe_unused char *parity = "no ";
           __maybe_unused char *parityeven = "odd";
           if (*data & LCR_WRL0) bits+=1;
           if (*data & LCR_WRL1) bits+=2;
         
           if (*data & LCR_NUMSTOP) {
             if ( bits >= 6) {
               stop = "2";
             } else {
               stop = "1.5";
             }
           }

           if (*data & LCR_PARITYON)
             parity=""; //Parity on
           if (*data & LCR_PARITYEV)
             parityeven="even";

           // DIV LATCH changes the behavior of 0x0,0x1,and 0x2
           if (*data & LCR_DIVLATCH) {
             d->div_latch = 1;
           } else {
             __maybe_unused uint baud;
             d->div_latch = 0;
             //  1200 divisor was 192
             //  9600 divisor was  24
             // 19200 divisor was  12
             // Suggests a crystal of 3686400 hz
             if (d->baud_divisor > 0) {
               baud = 3686400 / (d->baud_divisor * 16);
             } else {
               baud = 0;
             }
           }
         }
         break;
      case 0x04:
      case 0x0C:
         if (op_type != MTS_READ) {
           __maybe_unused char *f1 = "";
           __maybe_unused char *f2 = "";
           __maybe_unused char *f3 = "";
           __maybe_unused char *f4 = "";
           __maybe_unused char *f5 = "";
           if (*data & MCR_DTR) f1 = "DTR ";
           if (*data & MCR_RTS) f2 = "RTS ";
           if (*data & MCR_OUT1) f3 = "OUT1 ";
           if (*data & MCR_OUT2) f4 = "OUT2 ";
           if (*data & MCR_LOOP) f5 = "LOOP ";
         }
         break;

      /* Line Status Register (LSR) */
      case 0x05:
      case 0x0D:
         if (op_type == MTS_READ) {
            odata = 0;

            if (vtty_is_char_avail(d->channel[channel].vtty))
               odata |= LSR_RXRDY;

            odata |= LSR_TXRDY|LSR_TXEMPTY;
            *data = odata;
         }
         break;

#if DEBUG_UNKNOWN
      default:
         if (op_type == MTS_READ) {
            cpu_log(cpu,"NS16552","read from addr 0x%x, pc=0x%llx (size=%u)\n",
                    offset,cpu_get_pc(cpu),op_size);
         } else {
            cpu_log(cpu,
                    "NS16552","write to addr 0x%x, value=0x%llx, "
                    "pc=0x%llx (size=%u)\n",
                    offset,*data,cpu_get_pc(cpu),op_size);
         }
#endif
   }

   return NULL;
}