Пример #1
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);
}
Пример #2
0
/* Read a character (until one is available) and store it in buffer */
static void vtty_read_and_store(vtty_t *vtty,int *fd_slot)
{
   int c;
   
   /* wait until we get a character input */
   c = vtty_read(vtty,fd_slot);
  
   /* if read error, do nothing */
   if (c < 0) return;

   /* If something was read, make sure the handler is informed */
   vtty->input_pending = TRUE;  

   if (!vtty->terminal_support) {
      vtty_store(vtty,c);
      return;
   }
  
   switch(vtty->input_state) {
      case VTTY_INPUT_TEXT :
         switch(c) {
            case 0x1b:
               vtty->input_state = VTTY_INPUT_VT1;
               return;

            /* Ctrl + ']' (0x1d, 29), or Alt-Gr + '*' (0xb3, 179) */
            case 0x1d:
            case 0xb3:
               if (ctrl_code_ok == 1) {
                 vtty->input_state = VTTY_INPUT_REMOTE;
               } else {
                 vtty_store(vtty,c);
               }
               return;
            case IAC :
               vtty->input_state = VTTY_INPUT_TELNET;
               return;
            case 0:  /* NULL - Must be ignored - generated by Linux telnet */
            case 10: /* LF (Line Feed) - Must be ignored on Windows platform */
               return;
            default:
               /* Store a standard character */
               vtty_store(vtty,c);
               return;
         }
         
      case VTTY_INPUT_VT1 :
         switch(c) {
            case 0x5b:
               vtty->input_state = VTTY_INPUT_VT2;
               return;
            default:
               vtty_store(vtty,0x1b);
               vtty_store(vtty,c);
         }
         vtty->input_state = VTTY_INPUT_TEXT;
         return;
  
      case VTTY_INPUT_VT2 :
         switch(c) {
            case 0x41:   /* Up Arrow */
               vtty_store(vtty,16);
               break;
            case 0x42:   /* Down Arrow */
               vtty_store(vtty,14);
               break;
            case 0x43:   /* Right Arrow */
               vtty_store(vtty,6);
               break;
            case 0x44:   /* Left Arrow */
               vtty_store(vtty,2);
               break;
            default:
               vtty_store(vtty,0x5b);
               vtty_store(vtty,0x1b);
               vtty_store(vtty,c);
               break;
         }
         vtty->input_state = VTTY_INPUT_TEXT;
         return;
  
      case VTTY_INPUT_REMOTE :
         remote_control(vtty, c);
         vtty->input_state = VTTY_INPUT_TEXT;
         return;
  
      case VTTY_INPUT_TELNET :
         vtty->telnet_cmd = c;
         switch(c) {
            case WILL:
            case WONT:
            case DO:
            case DONT:
               vtty->input_state = VTTY_INPUT_TELNET_IYOU;
               return;
            case SB :
               vtty->telnet_cmd = c;
               vtty->input_state = VTTY_INPUT_TELNET_SB1;
               return;
            case SE:
               break;
            case IAC :
               vtty_store(vtty, IAC);
               break;
         }
         vtty->input_state = VTTY_INPUT_TEXT;
         return;
  
      case VTTY_INPUT_TELNET_IYOU :
         vtty->telnet_opt = c;
         /* if telnet client can support ttype, ask it to send ttype string */
         if ((vtty->telnet_cmd == WILL) && 
             (vtty->telnet_opt == TELOPT_TTYPE)) 
         {
            vtty_put_char(vtty, IAC);
            vtty_put_char(vtty, SB);
            vtty_put_char(vtty, TELOPT_TTYPE);
            vtty_put_char(vtty, TELQUAL_SEND);
            vtty_put_char(vtty, IAC);
            vtty_put_char(vtty, SE);
         }
         vtty->input_state = VTTY_INPUT_TEXT;
         return;
  
      case VTTY_INPUT_TELNET_SB1 :
         vtty->telnet_opt = c;
         vtty->input_state = VTTY_INPUT_TELNET_SB2;
         return;
  
      case VTTY_INPUT_TELNET_SB2 :
         vtty->telnet_qual = c;
         if ((vtty->telnet_opt == TELOPT_TTYPE) && 
             (vtty->telnet_qual == TELQUAL_IS))
            vtty->input_state = VTTY_INPUT_TELNET_SB_TTYPE;
         else
            vtty->input_state = VTTY_INPUT_TELNET_NEXT;
         return;
  
      case VTTY_INPUT_TELNET_SB_TTYPE :
         /* parse ttype string: first char is sufficient */
         /* if client is xterm or vt, set the title bar */
         if ((c == 'x') || (c == 'X') || (c == 'v') || (c == 'V')) {
            fd_printf(*fd_slot,0,"\033]0;%s\07", vtty->vm->name);
         }
         vtty->input_state = VTTY_INPUT_TELNET_NEXT;
         return;
  
      case VTTY_INPUT_TELNET_NEXT :
         /* ignore all chars until next IAC */
         if (c == IAC)
            vtty->input_state = VTTY_INPUT_TELNET;
         return;
   }
}
Пример #3
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;
}
Пример #4
0
void *dev_pic32_uart_access (cpu_mips_t * cpu, struct vdevice *dev,
    m_uint32_t offset, u_int op_size, u_int op_type,
    m_reg_t * data, m_uint8_t * has_set_value)
{
    struct pic32_uart_data *d = dev->priv_data;
    unsigned newval;

    if (offset >= UART_REG_SIZE) {
        *data = 0;
        return NULL;
    }
    if (op_type == MTS_READ) {
        /*
         * Reading UART registers.
         */
        switch (offset) {
        case PIC32_U1RXREG & 0xff:              /* Receive data */
            *data = vtty_get_char (d->vtty);
            if (vtty_is_char_avail (d->vtty)) {
                d->sta |= PIC32_USTA_URXDA;
            } else {
                d->sta &= ~PIC32_USTA_URXDA;
                d->vm->clear_irq (d->vm, d->irq + IRQ_RX);
            }
            break;

        case PIC32_U1BRG & 0xff:                /* Baud rate */
            *data = d->brg;
            break;

        case PIC32_U1MODE & 0xff:               /* Mode */
            *data = d->mode;
            break;

        case PIC32_U1STA & 0xff:                /* Status and control */
            d->sta |= PIC32_USTA_RIDLE |        /* Receiver is idle */
                PIC32_USTA_TRMT;                /* Transmit shift register is empty */
            if (vtty_is_char_avail (d->vtty))
                d->sta |= PIC32_USTA_URXDA;
            *data = d->sta;
#if 0
            printf ("<%x>", d->sta);
            fflush (stdout);
#endif
            break;

        case PIC32_U1TXREG & 0xff:              /* Transmit */
        case PIC32_U1MODECLR & 0xff:
        case PIC32_U1MODESET & 0xff:
        case PIC32_U1MODEINV & 0xff:
        case PIC32_U1STACLR & 0xff:
        case PIC32_U1STASET & 0xff:
        case PIC32_U1STAINV & 0xff:
        case PIC32_U1BRGCLR & 0xff:
        case PIC32_U1BRGSET & 0xff:
        case PIC32_U1BRGINV & 0xff:
            *data = 0;
            break;

        default:
            ASSERT (0, "reading unknown uart offset %x\n", offset);
        }
        *has_set_value = TRUE;
#if 0
        printf ("--- uart: read %02x -> %08x\n", offset, *data);
        fflush (stdout);
#endif
    } else {
        /*
         * Writing UART registers.
         */
#if 0
        printf ("--- uart: write %02x := %08x\n", offset, *data);
        fflush (stdout);
#endif
        switch (offset) {
        case PIC32_U1TXREG & 0xff:              /* Transmit */
            /* Skip ^M. */
            if ((char) (*data) != '\r')
                vtty_put_char (d->vtty, (char) (*data));
            if ((d->mode & PIC32_UMODE_ON) &&
                (d->sta & PIC32_USTA_UTXEN) && (d->output == 0)) {
                /*
                 * yajin.
                 *
                 * In order to put the next data more quickly,
                 * just set irq not waiting for
                 * host_alarm_handler to set irq. Sorry uart,
                 * too much work for you.
                 *
                 * Sometimes, linux kernel prints "serial8250:
                 * too much work for irq9" if we print large
                 * data on screen. Please patch the kernel.
                 * comment "printk(KERN_ERR "serial8250: too
                 * much work for " "irq%d\n", irq);" qemu has
                 * some question.
                 * http://lkml.org/lkml/2008/1/12/135
                 * http://kerneltrap.org/mailarchive/linux-ker
                 * nel/2008/2/7/769924
                 *
                 * If jit is used in future, we may not need to
                 * set irq here because simulation is quick
                 * enough. Then we have no "too much work for
                 * irq9" problem.
                 */
                d->output = TRUE;
                d->vm->set_irq (d->vm, d->irq + IRQ_TX);
            }
            break;

        case PIC32_U1MODE & 0xff:               /* Mode */
            newval = *data;
write_mode:
            d->mode = newval;
            if (!(d->mode & PIC32_UMODE_ON)) {
                d->vm->clear_irq (d->vm, d->irq + IRQ_RX);
                d->vm->clear_irq (d->vm, d->irq + IRQ_TX);
                d->sta &= ~PIC32_USTA_URXDA;
                d->sta &= ~(PIC32_USTA_URXDA | PIC32_USTA_FERR |
                    PIC32_USTA_PERR | PIC32_USTA_UTXBF);
                d->sta |= PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
            }
            break;
        case PIC32_U1MODECLR & 0xff:
            newval = d->mode & ~*data;
            goto write_mode;
        case PIC32_U1MODESET & 0xff:
            newval = d->mode | *data;
            goto write_mode;
        case PIC32_U1MODEINV & 0xff:
            newval = d->mode ^ *data;
            goto write_mode;

        case PIC32_U1STA & 0xff:                /* Status and control */
            newval = *data;
write_sta:
            d->sta &= PIC32_USTA_URXDA | PIC32_USTA_FERR |
                PIC32_USTA_PERR | PIC32_USTA_RIDLE |
                PIC32_USTA_TRMT | PIC32_USTA_UTXBF;
            d->sta |= newval & ~(PIC32_USTA_URXDA | PIC32_USTA_FERR |
                PIC32_USTA_PERR | PIC32_USTA_RIDLE |
                PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
            if (!(d->sta & PIC32_USTA_URXEN)) {
                d->vm->clear_irq (d->vm, d->irq + IRQ_RX);
                d->sta &= ~(PIC32_USTA_URXDA | PIC32_USTA_FERR |
                    PIC32_USTA_PERR);
            }
            if (!(d->sta & PIC32_USTA_UTXEN)) {
                d->vm->clear_irq (d->vm, d->irq + IRQ_TX);
                d->sta &= ~PIC32_USTA_UTXBF;
                d->sta |= PIC32_USTA_TRMT;
            }
            break;
        case PIC32_U1STACLR & 0xff:
            newval = d->sta & ~*data;
            goto write_sta;
        case PIC32_U1STASET & 0xff:
            newval = d->sta | *data;
            goto write_sta;
        case PIC32_U1STAINV & 0xff:
            newval = d->sta ^ *data;
            goto write_sta;

        case PIC32_U1BRG & 0xff:                /* Baud rate */
            newval = *data;
write_brg:
            d->brg = newval;
            break;
        case PIC32_U1BRGCLR & 0xff:
            newval = d->brg & ~*data;
            goto write_brg;
        case PIC32_U1BRGSET & 0xff:
            newval = d->brg | *data;
            goto write_brg;
        case PIC32_U1BRGINV & 0xff:
            newval = d->brg ^ *data;
            goto write_brg;

        case PIC32_U1RXREG & 0xff:              /* Receive */
            /* Ignore */
            break;

        default:
            ASSERT (0, "writing unknown uart offset %x\n", offset);
        }
        *has_set_value = TRUE;
    }
    return NULL;
}
Пример #5
0
/*
 * dev_remote_control_access()
 */
void *dev_remote_control_access(cpu_gen_t *cpu,struct vdevice *dev,
                                m_uint32_t offset,u_int op_size,u_int op_type,
                                m_uint64_t *data)
{
   vm_instance_t *vm = cpu->vm;
   struct remote_data *d = dev->priv_data;
   struct vdevice *storage_dev;
   size_t len;

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

#if DEBUG_ACCESS
   if (op_type == MTS_READ) {
      cpu_log(cpu,"REMOTE","reading reg 0x%x at pc=0x%llx\n",
              offset,cpu_get_pc(cpu));
   } else {
      cpu_log(cpu,"REMOTE","writing reg 0x%x at pc=0x%llx, data=0x%llx\n",
              offset,cpu_get_pc(cpu),*data);
   }
#endif

   switch(offset) {
      /* ROM Identification tag */
      case 0x000: 
         if (op_type == MTS_READ)
            *data = ROM_ID;
         break;

      /* CPU ID */
      case 0x004: 
         if (op_type == MTS_READ)
            *data = cpu->id;
         break;

      /* Display CPU registers */
      case 0x008:
         if (op_type == MTS_WRITE)
            cpu->reg_dump(cpu);
         break;

      /* Display CPU memory info */
      case 0x00c:
         if (op_type == MTS_WRITE)
            cpu->mmu_dump(cpu);
         break;

      /* Reserved/Unused */
      case 0x010:
         break;

      /* RAM size */
      case 0x014: 
         if (op_type == MTS_READ)
            *data = vm->ram_size;
         break;

      /* ROM size */
      case 0x018: 
         if (op_type == MTS_READ)
            *data = vm->rom_size;
         break;

      /* NVRAM size */
      case 0x01c: 
         if (op_type == MTS_READ)
            *data = vm->nvram_size;
         break;             

      /* IOMEM size */
      case 0x020:
        if (op_type == MTS_READ)
            *data = vm->iomem_size;
         break;

      /* Config Register */
      case 0x024:
         if (op_type == MTS_READ)
            *data = vm->conf_reg;
         break;

      /* ELF entry point */
      case 0x028: 
         if (op_type == MTS_READ)
            *data = vm->ios_entry_point;
         break;      

      /* ELF machine id */
      case 0x02c:
         if (op_type == MTS_READ)
            *data = vm->elf_machine_id;
         break;

      /* Restart IOS Image */
      case 0x030:
         /* not implemented */
         break;

      /* Stop the virtual machine */
      case 0x034:
          // FIXME: WTF is this for?!?!?
         //vm->status = VM_STATUS_SHUTDOWN;
         break;

      /* Debugging/Log message: /!\ physical address */
      case 0x038:
         if (op_type == MTS_WRITE) {
            len = physmem_strlen(vm,*data);
            if (len < sizeof(d->con_buffer)) {
               physmem_copy_from_vm(vm,d->con_buffer,*data,len+1);
               vm_log(vm,"ROM",d->con_buffer);
            }
         }
         break;

      /* Console Buffering */
      case 0x03c:
         if (op_type == MTS_WRITE) {
            if (d->con_buf_pos < (sizeof(d->con_buffer)-1)) {
               d->con_buffer[d->con_buf_pos++] = *data & 0xFF;
               d->con_buffer[d->con_buf_pos] = 0;

               if (d->con_buffer[d->con_buf_pos-1] == '\n') {
                  vm_log(vm,"ROM","%s",d->con_buffer);
                  d->con_buf_pos = 0;
               }
            } else
               d->con_buf_pos = 0;
         }
         break;

      /* Console output */
      case 0x040:
         if (op_type == MTS_WRITE)
            vtty_put_char(vm->vtty_con,(char)*data);
         break;

      /* NVRAM address */
      case 0x044:
         if (op_type == MTS_READ) {
            if ((storage_dev = dev_get_by_name(vm,"nvram")))
               *data = storage_dev->phys_addr;

            if ((storage_dev = dev_get_by_name(vm,"ssa")))
               *data = storage_dev->phys_addr;

            if (cpu->type == CPU_TYPE_MIPS64)
               *data += MIPS_KSEG1_BASE;
         }
         break;

      /* IO memory size for Smart-Init (C3600, others ?) */
      case 0x048:
         if (op_type == MTS_READ)
            *data = vm->nm_iomem_size;
         break;

      /* Cookie position selector */
      case 0x04c:
         if (op_type == MTS_READ)
            *data = d->cookie_pos;
         else
            d->cookie_pos = *data;
         break;
         
      /* Cookie data */
      case 0x050:
         if ((op_type == MTS_READ) && (d->cookie_pos < 64))
            *data = vm->chassis_cookie[d->cookie_pos];
         break;

      /* ROMMON variable */
      case 0x054:
         if (op_type == MTS_WRITE) {
            if (d->var_buf_pos < (sizeof(d->var_buffer)-1)) {
               d->var_buffer[d->var_buf_pos++] = *data & 0xFF;
               d->var_buffer[d->var_buf_pos] = 0;
            } else
               d->var_buf_pos = 0;
         } else {
            if (d->var_buf_pos < (sizeof(d->var_buffer)-1)) {
               *data = d->var_buffer[d->var_buf_pos++];
            } else {
               d->var_buf_pos = 0;
               *data = 0;
            }
         }
         break;

      /* ROMMON variable command */
      case 0x058:
         if (op_type == MTS_WRITE) {
            switch(*data & 0xFF) {
               case ROMMON_SET_VAR:
                  d->var_status = rommon_var_add_str(&vm->rommon_vars,
                                                     d->var_buffer);
                  d->var_buf_pos = 0;
                  break;
               case ROMMON_GET_VAR:
                  d->var_status = rommon_var_get(&vm->rommon_vars,
                                                 d->var_buffer,
                                                 d->var_buffer,
                                                 sizeof(d->var_buffer));
                  d->var_buf_pos = 0;
                  break;
               case ROMMON_CLEAR_VAR_STAT:
                  d->var_buf_pos = 0;
                  break;
               default:
                  d->var_status = -1;
            }
         } else {
            *data = d->var_status;
         }
         break;
   }

   return NULL;
}