Exemplo n.º 1
0
/* Update network interrupt status */
static inline void dev_c2600_iofpga_net_update_irq(struct c2600_iofpga_data *d)
{
   if (d->net_irq_status) {
      vm_set_irq(d->router->vm,C2600_NETIO_IRQ);
   } else {
      vm_clear_irq(d->router->vm,C2600_NETIO_IRQ);
   }
}
Exemplo n.º 2
0
/* Process remote control char */
static void remote_control(vtty_t *vtty,u_char c)
{
   vm_instance_t *vm = vtty->vm;
   cpu_gen_t *cpu0;
  
   cpu0 = vm->boot_cpu;

   /* Specific commands for the different CPU models */
   if (cpu0) {
      switch(cpu0->type) {
         case CPU_TYPE_MIPS64:
            if (remote_control_mips64(vtty,c,CPU_MIPS64(cpu0)))
               return;
            break;
         case CPU_TYPE_PPC32:
            if (remote_control_ppc32(vtty,c,CPU_PPC32(cpu0)))
               return;
            break;
      }
   }

   switch(c) {
      /* Show the object list */
      case 'o':
         vm_object_dump(vm);
         break;
  
      /* Stop the MIPS VM */
      case 'q':
         vm->status = VM_STATUS_SHUTDOWN;
         break;
  
      /* Reboot the C7200 */
      case 'k':
#if 0
         if (vm->type == VM_TYPE_C7200)
            c7200_boot_ios(VM_C7200(vm));
#endif
         break;
  
      /* Show the device list */
      case 'd':
         dev_show_list(vm);
         pci_dev_show_list(vm->pci_bus[0]);
         pci_dev_show_list(vm->pci_bus[1]);
         break;

      /* Show info about Port Adapters or Network Modules */
      case 'p':
         vm_slot_show_all_info(vm);
         break;
  
      /* Dump the MIPS registers */
      case 'r':
         if (cpu0) cpu0->reg_dump(cpu0);
         break;

      /* Dump the latest memory accesses */
      case 'm':
         if (cpu0) memlog_dump(cpu0);
         break;      
         
      /* Suspend CPU emulation */
      case 's':
         vm_suspend(vm);
         break;
  
      /* Resume CPU emulation */
      case 'u':
         vm_resume(vm);
         break;
  
      /* Dump the MMU information */
      case 't':
         if (cpu0) cpu0->mmu_dump(cpu0);
         break;
  
      /* Dump the MMU information (raw mode) */
      case 'z':
         if (cpu0) cpu0->mmu_raw_dump(cpu0);
         break;

      /* Memory translation cache statistics */
      case 'l':
         if (cpu0) cpu0->mts_show_stats(cpu0);
         break;

      /* Extract the configuration from the NVRAM */
      case 'c':
         vm_ios_save_config(vm);
         break;
  
      /* Determine an idle pointer counter */
      case 'i':
         if (cpu0)
            cpu0->get_idling_pc(cpu0);
         break;
  
      /* Experimentations / Tests */
      case 'x':

#if 0
         if (cpu0) {
            /* IRQ triggering */
            vm_set_irq(vm,6);
            //CPU_MIPS64(cpu0)->irq_disable = TRUE;
         }
#endif
#ifdef USE_UNSTABLE
         tsg_show_stats();
#endif
         break;

      case 'y':
         if (cpu0) {
            /* IRQ clearing */
            vm_clear_irq(vm,6);
         }
         break;

      /* Twice Ctrl + ']' (0x1d, 29), or Alt-Gr + '*' (0xb3, 179) */
      case 0x1d:
      case 0xb3:
         vtty_store(vtty,c);
         break;
         
      default:
         printf("\n\nInstance %s (ID %d)\n\n",vm->name,vm->instance_id);
         
         printf("o     - Show the VM object list\n"
                "d     - Show the device list\n"
                "r     - Dump CPU registers\n"
                "t     - Dump MMU information\n"
                "z     - Dump MMU information (raw mode)\n"
                "m     - Dump the latest memory accesses\n"
                "s     - Suspend CPU emulation\n"
                "u     - Resume CPU emulation\n"
                "q     - Quit the emulator\n"
                "k     - Reboot the virtual machine\n"
                "b     - Show info about JIT compiled pages\n"
                "l     - MTS cache statistics\n"
                "c     - Write IOS configuration to disk\n"
                "j     - Non-JIT mode statistics\n"
                "i     - Determine an idling pointer counter\n"
                "x     - Experimentations (can crash the box!)\n"
                "^]    - Send ^]\n"
                "Other - This help\n");
   }
}
Exemplo n.º 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;
}
/*
 * dev_c3660_iofpga_access()
 */
static void *
dev_c3660_iofpga_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 c3600_iofpga_data *d = dev->priv_data;
   u_int slot;

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

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

   switch(offset) {
      /* 
       * 0x7d00 is written here regularly.
       * Some kind of hardware watchdog ?
       */     
      case 0x0000c:
         break;

      /* Probably flash protection (if 0, no write access allowed) */
      case 0x00008:
         if (op_type == MTS_READ)
            *data = 0xFF;
         break;

      /* Bootflash of 8 Mb */
      case 0x0000a:
         if (op_type == MTS_READ)
            *data = 0x1000;
         break;

      /* NM presence - slots 1 to 4 */
      case 0x10006:
         if (op_type == MTS_READ)
            *data = nm_get_status_2(d,0);
         break;

      /* NM presence - slot 5 to 6 */
      case 0x10008:
         if (op_type == MTS_READ)
            *data = nm_get_status_2(d,1);
         break;
      
      /* Fan status, PS presence */
      case 0x10018:
         if (op_type == MTS_READ)
            *data = 0x0000;
         break;

      /* unknown, read by env monitor */
      case 0x1001a: 
         if (op_type == MTS_READ)
            *data = 0x0000;
         break;

      /* board temperature */
      case 0x30004:
         if (op_type == MTS_READ) {
            *data = 32 + 1;
         }
         break;

      /* sh c3600: Per Slot Intr Mask */
      case 0x10016:
         if (op_type == MTS_READ)
            *data = 0x12;
         break;

      /* sh c3600: OIR fsm state slot's (12) */
      case 0x10020:
         if (op_type == MTS_READ)
            *data = 0x00;
         break;

      /* sh c3600: OIR fsm state slot's (34) */
      case 0x10022:
         if (op_type == MTS_READ)
            *data = 0x00;
         break;

      /* sh c3600: OIR fsm state slot's (56) */
      case 0x10024:
         if (op_type == MTS_READ)
            *data = 0x00;
         break;

      /* 
       * Backplane EEPROM.
       *
       * Bit 7: 0=Telco chassis, 1=Enterprise chassis.
       */
      case 0x10000:
         if (op_type == MTS_WRITE)
            nmc93cX6_write(&d->router->mb_eeprom_group,(u_int)(*data));
         else
            *data = nmc93cX6_read(&d->router->mb_eeprom_group) | 0x80;
         break;

      /* NM EEPROMs - slots 1 to 6 */
      case 0x1000a:
      case 0x1000b:
      case 0x1000c:
      case 0x1000d:
      case 0x1000e:
      case 0x1000f:
         slot = (offset - 0x1000a) + 1;

         if (op_type == MTS_WRITE) {
            nmc93cX6_write(&d->router->c3660_nm_eeprom_group[slot],
                           (u_int)(*data));
         } else {
            *data = nmc93cX6_read(&d->router->c3660_nm_eeprom_group[slot]);
         }
         break;

      /* NM EEPROM - slot 0 */
      case 0x20006:
         if (op_type == MTS_WRITE) {
            nmc93cX6_write(&d->router->c3660_nm_eeprom_group[0],
                           (u_int)(*data));
         } else {
            *data = nmc93cX6_read(&d->router->c3660_nm_eeprom_group[0]);
         }
         break;

      /* Unknown EEPROMs ? */
      case 0x20000:
      case 0x20002:
      case 0x20004:
         if (op_type == MTS_READ)
            *data = 0xFFFF;
         break;

      /* IO Mask (displayed by "show c3600") */
      case 0x20008:
         if (op_type == MTS_READ)
            *data = d->io_mask;
         else
            d->io_mask = *data;
         break;

      /* 0: 3640, 4 << 5: 3620, 3 << 5: 3660 */
      case 0x30000:
         if (op_type == MTS_READ)            
            *data = 3 << 5;
         break;

      /* ??? */   
      case 0x30008:
        if (op_type == MTS_READ)
           *data = 0xFF;
        break;

      /* 
       * Read at net interrupt (size 4).
       * It seems that there are 4 lines per slot.
       *
       *   Bit 24-27: slot 1
       *   Bit 16-19: slot 2
       *   Bit 28-31: slot 3
       *   Bit 20-23: slot 4
       *   Bit 08-11: slot 5
       *   Bit 00-03: slot 6
       *
       * Other bits are unknown.
       */
      case 0x10010:
         if (op_type == MTS_READ)
            *data = d->net_irq_status[0];
         break;

      /* 
       * Read at net interrupt (size 1) 
       *
       *   Bit 7-6: we get "Unexpected AIM interrupt on AIM slot 1".
       *   Bit 5-4: we get "Unexpected AIM interrupt on AIM slot 0".
       *   Bit 0-3: net interrupt for slot 0.
       */        
      case 0x20010:
         if (op_type == MTS_READ)
            *data = d->net_irq_status[1];
         break;

      /* 
       * Read when a PA Management interrupt is triggered.
       *
       * If not 0, we get:
       *   "Error: Unexpected NM Interrupt received from slot: x"
       */
      case 0x10014:
         if (op_type == MTS_READ)
            *data = 0x00;
         vm_clear_irq(d->router->vm,C3600_NM_MGMT_IRQ);
         break;

      /* 
       * Read when an external interrupt is triggered.
       *
       * Bit 4: 1 = %UNKNOWN-1-GT64010: Unknown fatal interrupt(s)
       * Bit 6: 1 = %OIRINT: OIR Event has occurred oir_ctrl 1000 oir_stat FFFF
       *
       * oir_ctrl = register 0x10004
       * oir_stat = register 0x10006
       */
      case 0x2000a:
         if (op_type == MTS_READ)
            *data = 0x54;
         vm_clear_irq(d->router->vm,C3600_EXT_IRQ);
         break;

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

   return NULL;
}
/*
 * dev_c3620_c3640_iofpga_access()
 */
static void *
dev_c3620_c3640_iofpga_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 c3600_iofpga_data *d = dev->priv_data;

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

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

   switch(offset) {
      /* Probably flash protection (if 0, no write access allowed) */
      case 0x00008:
         if (op_type == MTS_READ)
            *data = 0xFF;
         break;

      /* Bootflash of 8 Mb */
      case 0x0000a:
         if (op_type == MTS_READ)
            *data = 0x1000;
         break;

      /* 
       * 0x7d00 is written here regularly.
       * Some kind of hardware watchdog ?
       */     
      case 0x0000c:
         break;

      /* Mainboard EEPROM */
      case 0x0000e:
         if (op_type == MTS_WRITE)
            nmc93cX6_write(&d->router->mb_eeprom_group,(u_int)(*data));
         else
            *data = nmc93cX6_read(&d->router->mb_eeprom_group);
         break;

      case 0x10004:  /* ??? OIR control ??? */
         if (op_type == MTS_READ) {
            *data = 0x0000;
         }
         break;
         
      /* 
       * Network modules presence.
       *
       * Bit 0: 0 = NM in slot 0 is valid
       * Bit 1: 0 = NM in slot 1 is valid
       * Bit 2: 0 = NM in slot 2 is valid
       * Bit 3: 0 = NM in slot 3 is valid
       *
       * Very well explained on Cisco website:
       * http://www.cisco.com/en/US/customer/products/hw/routers/ps274/products_tech_note09186a0080109510.shtml
       */
      case 0x10006:
         if (op_type == MTS_READ)
            *data = nm_get_status_1(d);
         break;
        
      /*
       * NM EEPROMs.
       */
      case 0x10008:
         if (op_type == MTS_WRITE) {
            d->eeprom_slot = *data & 0x03;
            nm_eeprom_select(d,d->eeprom_slot);
            nmc93cX6_write(&d->router->nm_eeprom_group,*data);
         } else {
            *data = nmc93cX6_read(&d->router->nm_eeprom_group);
         }
         break;

      /* Network interrupt status */
      case 0x20000:   /* slot 1 */
         if (op_type == MTS_READ)
            *data = d->net_irq_status[0] >> 24;
         break;
      case 0x20001:   /* slot 0 */
         if (op_type == MTS_READ)
            *data = d->net_irq_status[0] >> 16;
         break;
      case 0x20002:   /* slot 3 */
         if (op_type == MTS_READ)
            *data = d->net_irq_status[0] >> 8;
         break;
      case 0x20003:   /* slot 2 */
         if (op_type == MTS_READ)
            *data = d->net_irq_status[0];
         break;

      /* 
       * Read when a PA Management interrupt is triggered.
       *
       * If not 0, we get:
       *   "Error: Unexpected NM Interrupt received from slot: x"
       */
      case 0x20004:
         if (op_type == MTS_READ)
            *data = 0x00;
         vm_clear_irq(d->router->vm,C3600_NM_MGMT_IRQ);
         break;

      /* 
       * Read when an external interrupt is triggered.
       *
       * Bit 4: 1 = %UNKNOWN-1-GT64010: Unknown fatal interrupt(s)
       * Bit 6: 1 = %OIRINT: OIR Event has occurred oir_ctrl 1000 oir_stat FFFF
       *
       * oir_ctrl = register 0x10004
       * oir_stat = register 0x10006
       */
      case 0x20006:
         if (op_type == MTS_READ)
            *data = 0x00;
         vm_clear_irq(d->router->vm,C3600_EXT_IRQ);
         break;

      /* IO Mask (displayed by "show c3600") */
      case 0x20008:
         if (op_type == MTS_READ)
            *data = d->io_mask;
         else
            d->io_mask = *data;
         break;

      /* 
       * Platform type ?
       * 0: 3640, 4 << 5: 3620, 3 << 5: 3660 
       */
      case 0x30000:
         if (op_type == MTS_READ) {
            switch(c3600_chassis_get_id(d->router)) {
               case 3620:
                  *data = 4 << 5;
                  break;
               case 3640:
                  *data = 0 << 5;
                  break;
               case 3660:
                  *data = 3 << 5;
                  break;
               default:
                  *data = 0;
            }
         }
         break;

      /* ??? */
      case 0x30002:
         if (op_type == MTS_WRITE) {
            d->sel = *data;
         } else {
            //*data = d->sel;
         }
         break;

      /* 
       * Environmental parameters, determined with "sh env all". 
       *
       * Bit 0: 0 = overtemperature condition.
       * Bit 4: 0 = RPS present.
       * Bit 5: 0 = Input Voltage status failure.
       * Bit 6: 1 = Thermal status failure.
       * Bit 7: 1 = DC Output Voltage status failure.
       */
      case 0x30004:
         if (op_type == MTS_READ) {
            *data = 32 + 1;
         }
         break;

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

   return NULL;
}