/*
 * dev_sb1_access()
 */
void *dev_sb1_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 sb1_data *d = dev->priv_data;

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

   switch(offset) {
      case 0x20000:
         if (op_type == MTS_READ)
            *data = 0x125020FF;
         break;

         /* Seen on a real NPE-G1 :) */
      case 0x20008:
         if (op_type == MTS_READ)
            *data = 0x00800000FCDB0700ULL;
         break;

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

   return NULL;
}
Beispiel #2
0
/*
 * dev_ssram_access
 */
static void *dev_ssram_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 pa_mc_data *d = dev->priv_data;

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

   if ((offset >= SSRAM_START) && (offset < SSRAM_END))
      return(&d->ssram_data[offset-SSRAM_START]);

#if DEBUG_ACCESS
   if (op_type == MTS_READ) {
      cpu_log(cpu,d->name,
              "read  access to offset = 0x%x, pc = 0x%llx (size=%u)\n",
              offset,cpu_get_pc(cpu),op_size);
   } else {
      cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, "
              "val = 0x%llx (size=%u)\n",
              offset,cpu_get_pc(cpu),*data,op_size);
   }
#endif

   switch(offset) {      
      case 0xfff0c:
         if (op_type == MTS_READ)
            *data = 0xdeadbeef;
         break;

      case 0xfff10:
         if (op_type == MTS_READ)
            *data = 0xbeeffeed;
         break;

      case 0x08:  /* max_dsx1 */
      case 0x10:  /* no_buf */
      case 0x18:  /* ev */
         if (op_type == MTS_READ)
            *data = 0x0ULL;
         break;

      case 0x00:  /* tx packets */
         if (op_type == MTS_READ)
            *data = 0x0;
         break;

      case 0x04:  /* rx packets */
         if (op_type == MTS_READ)
            *data = 0x0;
         break;
         
      case 0x0c:  /* rx drops */
         if (op_type == MTS_READ)
            *data = 0;
         break;
   }

   return NULL;
}
Beispiel #3
0
/*
 * dev_wic1t_access()
 */
static void *dev_wic1t_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 wic_serial_data *d = dev->priv_data;

   switch(offset) {
      case 0x04: 
         if (op_type == MTS_READ)
            *data = 0xFF;
         break;

      case 0x08:
         if (op_type == MTS_READ)
            *data = 0xFF;
         break;

#if DEBUG_UNKNOWN
      default:
         if (op_type == MTS_READ) {
            cpu_log(cpu,d->name,
                    "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
                    offset,cpu_get_pc(cpu),op_size);
         } else {
            cpu_log(cpu,d->name,
                    "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;
}
Beispiel #4
0
/* CACHE: Cache operation */
fastcall void MTS_PROTO(cache)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int op)
{
   mips64_jit_tcb_t *block;
   m_uint32_t pc_hash;

#if DEBUG_CACHE
   cpu_log(cpu->gen,
           "MTS","CACHE: PC=0x%llx, vaddr=0x%llx, cache=%u, code=%u\n",
           cpu->pc, vaddr, op & 0x3, op >> 2);
#endif

   if (cpu->exec_blk_map) {
      pc_hash = mips64_jit_get_pc_hash(vaddr);
      block = cpu->exec_blk_map[pc_hash];

      if (block && (block->start_pc == (vaddr & MIPS_MIN_PAGE_MASK))) {
#if DEBUG_CACHE
         cpu_log(cpu->gen,"MTS",
                 "CACHE: removing compiled page at 0x%llx, pc=0x%llx\n",
                 block->start_pc,cpu->pc);
#endif
         cpu->exec_blk_map[pc_hash] = NULL;
         mips64_jit_tcb_free(cpu,block,TRUE);
      }
      else
      {
#if DEBUG_CACHE
         cpu_log(cpu->gen,"MTS",
                 "CACHE: trying to remove page 0x%llx with pc=0x%llx\n",
                 vaddr, cpu->pc);
#endif         
      }
   }
}
Beispiel #5
0
/* Memory access with special access mask */
void ppc32_access_special(cpu_ppc_t *cpu,m_uint32_t vaddr,u_int cid,
                          m_uint32_t mask,u_int op_code,u_int op_type,
                          u_int op_size,m_uint64_t *data)
{
   switch(mask) {
      case MTS_ACC_T:
         if (op_code != PPC_MEMOP_LOOKUP) {
#if DEBUG_MTS_ACC_T
            cpu_log(cpu->gen,
                    "MTS","MMU exception for address 0x%8.8x at ia=0x%8.8x "
                    "(%s access, size=%u)\n",
                    vaddr,cpu->ia,(op_type == MTS_READ) ? 
                    "read":"write",op_size);
            //ppc32_dump_regs(cpu->gen);
#if MEMLOG_ENABLE
            memlog_dump(cpu->gen);
#endif
#endif
            if (cid == PPC32_MTS_DCACHE) {
               cpu->dsisr = PPC32_DSISR_NOTRANS;

               if (op_type == MTS_WRITE)
                  cpu->dsisr |= PPC32_DSISR_STORE;

               cpu->dar = vaddr;
               ppc32_trigger_exception(cpu,PPC32_EXC_DSI);
               cpu_exec_loop_enter(cpu->gen);
            } else {
               ppc32_trigger_exception(cpu,PPC32_EXC_ISI);
               cpu_exec_loop_enter(cpu->gen);
            }
         }        
         break;

      case MTS_ACC_U:
         if (op_type == MTS_READ)
            *data = 0;

         if (cpu->gen->undef_mem_handler != NULL) {
            if (cpu->gen->undef_mem_handler(cpu->gen,(m_uint64_t)vaddr,
                                            op_size,op_type,data))
               return;
         }

#if DEBUG_MTS_ACC_U
         if (op_type == MTS_READ)
            cpu_log(cpu->gen,
                    "MTS","read  access to undefined address 0x%8.8x at "
                    "ia=0x%8.8x (size=%u)\n",vaddr,cpu->ia,op_size);
         else
            cpu_log(cpu->gen,
                    "MTS","write access to undefined address 0x%8.8x at "
                    "ia=0x%8.8x, value=0x%8.8llx (size=%u)\n",
                    vaddr,cpu->ia,*data,op_size);
#endif
         break;
   }
}
Beispiel #6
0
/*
 * pos_tx_access()
 */
static void *dev_pos_tx_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 pos_oc3_data *d = dev->priv_data;

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

#if DEBUG_ACCESS
   if (op_type == MTS_READ) {
      cpu_log(cpu,d->tx_name,"read  access to offset = 0x%x, pc = 0x%llx\n",
              offset,cpu_get_pc(cpu));
   } else {
      cpu_log(cpu,d->tx_name,"write access to vaddr = 0x%x, pc = 0x%llx, "
              "val = 0x%llx\n",offset,cpu_get_pc(cpu),*data);
   }
#endif

   switch(offset) {
     case 0x04:
         if (op_type == MTS_READ)
            *data = d->tx_start;
         else
            d->tx_start = *data;
         break;

      case 0x08:
         if (op_type == MTS_READ)
            *data = d->tx_current;
         else
            d->tx_current = *data;
         break;

#if DEBUG_UNKNOWN
      default:
         if (op_type == MTS_READ) {
            cpu_log(cpu,d->tx_name,
                    "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
                    offset,cpu_get_pc(cpu),op_size);
         } else {
            cpu_log(cpu,d->tx_name,
                    "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;
}
Beispiel #7
0
/* TLBP: Probe a TLB entry */
void fastcall mips_cp0_exec_tlbp (cpu_mips_t * cpu)
{
    mips_cp0_t *cp0 = &cpu->cp0;

    m_uint32_t vpn2, hi_reg, vpn2_mask, page_mask, hi_addr;
    tlb_entry_t *entry;
    u_int asid;
    int i;
    vpn2_mask = mips_cp0_get_vpn2_mask (cpu);
    hi_reg = cp0->reg[MIPS_CP0_TLB_HI];
    asid = hi_reg & MIPS_TLB_ASID_MASK;
    vpn2 = hi_reg & vpn2_mask;

    cp0->reg[MIPS_CP0_INDEX] = 0x80000000;
    for (i = 0; i < cp0->tlb_entries; i++) {
        entry = &cp0->tlb[i];
        page_mask = ~(entry->mask + 0x1FFF);
        hi_addr = entry->hi & mips_cp0_get_vpn2_mask (cpu);
        if (((vpn2 & page_mask) == (hi_addr & page_mask)) &&
            (((entry->hi & MIPS_TLB_G_MASK))
                || ((entry->hi & MIPS_TLB_ASID_MASK) == asid))) {
            cp0->reg[MIPS_CP0_INDEX] = i;
            cp0->reg[MIPS_CP0_INDEX] &= ~0x80000000ULL;
            return;
#if DEBUG_TLB_ACTIVITY
            cpu_log (cpu, "", "CPU: CP0_TLBP returned %x\n", i);
#endif
        }
    }
}
Beispiel #8
0
/* TLBR: Read Indexed TLB entry */
void fastcall mips_cp0_exec_tlbr (cpu_mips_t * cpu)
{
    mips_cp0_t *cp0 = &cpu->cp0;
    tlb_entry_t *entry;
    u_int index;

    index = cp0->reg[MIPS_CP0_INDEX];

#if DEBUG_TLB_ACTIVITY
    cpu_log (cpu, "TLB", "CP0_TLBR: reading entry %u.\n", index);
#endif

    if (index < cp0->tlb_entries) {
        entry = &cp0->tlb[index];

        cp0->reg[MIPS_CP0_PAGEMASK] = entry->mask;
        cp0->reg[MIPS_CP0_TLB_HI] = entry->hi;
        cp0->reg[MIPS_CP0_TLB_LO_0] = entry->lo0;
        cp0->reg[MIPS_CP0_TLB_LO_1] = entry->lo1;
        if (entry->hi & MIPS_TLB_G_MASK) {
            cp0->reg[MIPS_CP0_TLB_LO_0] |= MIPS_CP0_LO_G_MASK;
            cp0->reg[MIPS_CP0_TLB_LO_1] |= MIPS_CP0_LO_G_MASK;
            cp0->reg[MIPS_CP0_TLB_HI] &= ~MIPS_TLB_G_MASK;
        }

    }
}
Beispiel #9
0
void cpu_restart(cpu_mips_t * cpu)
{
   if (cpu)
   {
      cpu_log(cpu, "CPU_STATE", "Restartting CPU (old state=%u)...\n", cpu->state);
      cpu->state = CPU_STATE_RESTARTING;
   }
}
Beispiel #10
0
/* Stop a CPU */
void cpu_stop(cpu_mips_t * cpu)
{
   if (cpu)
   {
      cpu_log(cpu, "CPU_STATE", "Halting CPU (old state=%u)...\n", cpu->state);
      cpu->state = CPU_STATE_HALTED;
   }
}
/*
 * dev_nvram_access()
 */
void *dev_nvram_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 nvram_data *d = dev->priv_data;

#if DEBUG_ACCESS
   if (op_type == MTS_READ)
      cpu_log(cpu,dev->name,"read  access to offset=0x%x, pc=0x%llx\n",
              offset,cpu_get_pc(cpu));
   else
      cpu_log(cpu,dev->name,
              "write access to vaddr=0x%x, pc=0x%llx, val=0x%llx\n",
              offset,cpu_get_pc(cpu),*data);
#endif

   switch(offset) {
      case 0x03:
         if (op_type == MTS_READ) {            
            *data = d->cal_read & 1;
            d->cal_read >>= 1;
         } else {
Beispiel #12
0
/*
 * pa_mc8te1_access()
 */
_unused static void *pa_mc8te1_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 pa_mc_data *d = dev->priv_data;

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

#if DEBUG_ACCESS
   if (op_type == MTS_READ) {
      cpu_log(cpu,d->name,"read  access to offset = 0x%x, pc = 0x%llx\n",
              offset,cpu_get_pc(cpu));
   } else {
      cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, "
              "val = 0x%llx\n",offset,cpu_get_pc(cpu),*data);
   }
#endif

   switch(offset) {

#if DEBUG_UNKNOWN
      default:
         if (op_type == MTS_READ) {
            cpu_log(cpu,d->name,
                    "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
                    offset,cpu_get_pc(cpu),op_size);
         } else {
            cpu_log(cpu,d->name,
                    "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;
}
Beispiel #13
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_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;
}
/*
 * dev_mv64460_access()
 */
void *dev_mv64460_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 mv64460_data *mv_data = dev->priv_data;

   MV64460_LOCK(mv_data);

   if (op_type == MTS_READ) {
      *data = 0;
   } else {
      if (op_size == 4)
         *data = swap32(*data);
   }

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

   /* Serial DMA channel registers */
   if (mv64460_sdma_access(cpu,dev,offset,op_size,op_type,data) != 0)
      goto done;

   /* MPSC registers */
   if (mv64460_mpsc_access(cpu,dev,offset,op_size,op_type,data) != 0)
      goto done;

   switch(offset) {
      /* Interrupt Main Cause Low */
      case MV64460_REG_ILMCR:
         if (op_type == MTS_READ)
            *data = mv_data->intr_lo;
         break;
         
      /* Interrupt Main Cause High */
      case MV64460_REG_IHMCR:
         if (op_type == MTS_READ)
            *data = mv_data->intr_hi;
         break;

      /* CPU_INTn[0] Mask Low */
      case MV64460_REG_CPU_INTN0_MASK_LO:
         if (op_type == MTS_READ) {
            *data = mv_data->cpu_intn0_mask_lo;
         } else {
            mv_data->cpu_intn0_mask_lo = *data;
            mv64460_int_sync(mv_data);
         }

         break;

      /* CPU_INTn[0] Mask High */
      case MV64460_REG_CPU_INTN0_MASK_HI:
         if (op_type == MTS_READ) {
            *data = mv_data->cpu_intn0_mask_hi;
         } else {
            mv_data->cpu_intn0_mask_hi = *data;
            mv64460_int_sync(mv_data);
         }
         break;

      /* CPU_INTn[0] Select Cause (read-only) */
      case MV64460_REG_CPU_INTN0_SEL_CAUSE:
         if (op_type == MTS_READ) {
            *data = mv64460_ic_get_sel_cause(mv_data,
                                             mv_data->cpu_intn0_mask_lo,
                                             mv_data->cpu_intn0_mask_hi);
         }
         break;

      /* CPU_INTn[1] Mask Low */
      case MV64460_REG_CPU_INTN1_MASK_LO:
         if (op_type == MTS_READ)
            *data = mv_data->cpu_intn1_mask_lo;
         else
            mv_data->cpu_intn1_mask_lo = *data;
         break;

      /* CPU_INTn[1] Mask High */
      case MV64460_REG_CPU_INTN1_MASK_HI:
         if (op_type == MTS_READ)
            *data = mv_data->cpu_intn1_mask_hi;
         else
            mv_data->cpu_intn1_mask_hi = *data;
         break;

      /* CPU_INTn[1] Select Cause (read-only) */
      case MV64460_REG_CPU_INTN1_SEL_CAUSE:
         if (op_type == MTS_READ) {
            *data = mv64460_ic_get_sel_cause(mv_data,
                                             mv_data->cpu_intn1_mask_lo,
                                             mv_data->cpu_intn1_mask_hi);
         }
         break;

      /* INT0n Mask Low */
      case MV64460_REG_INT0N_MASK_LO:
         if (op_type == MTS_READ)
            *data = mv_data->int0n_mask_lo;
         else
            mv_data->int0n_mask_lo = *data;
         break;

      /* INT0n Mask High */
      case MV64460_REG_INT0N_MASK_HI:
         if (op_type == MTS_READ)
            *data = mv_data->int0n_mask_hi;
         else
            mv_data->int0n_mask_hi = *data;
         break;

      /* INT0n Select Cause (read-only) */
      case MV64460_REG_INT0N_SEL_CAUSE:
         if (op_type == MTS_READ) {
            *data = mv64460_ic_get_sel_cause(mv_data,
                                             mv_data->int0n_mask_lo,
                                             mv_data->int0n_mask_hi);
         }
         break;

      /* INT1n Mask Low */
      case MV64460_REG_INT1N_MASK_LO:
         if (op_type == MTS_READ)
            *data = mv_data->int1n_mask_lo;
         else
            mv_data->int1n_mask_lo = *data;
         break;

      /* INT1n Mask High */
      case MV64460_REG_INT1N_MASK_HI:
         if (op_type == MTS_READ)
            *data = mv_data->int1n_mask_hi;
         else
            mv_data->int1n_mask_hi = *data;
         break;

      /* INT1n Select Cause (read-only) */
      case MV64460_REG_INT1N_SEL_CAUSE:
         if (op_type == MTS_READ) {
            *data = mv64460_ic_get_sel_cause(mv_data,
                                             mv_data->int1n_mask_lo,
                                             mv_data->int1n_mask_hi);
         }
         break;

      /* ===== PCI Bus 0 ===== */
      case PCI_BUS_ADDR:    /* pci configuration address (0xcf8) */
         pci_dev_addr_handler(cpu,mv_data->bus[0],op_type,FALSE,data);
         break;

      case PCI_BUS_DATA:    /* pci data address (0xcfc) */
         pci_dev_data_handler(cpu,mv_data->bus[0],op_type,FALSE,data);
         break;

      /* ===== PCI Bus 0 ===== */
      case 0xc78:           /* pci configuration address (0xc78) */
         pci_dev_addr_handler(cpu,mv_data->bus[1],op_type,FALSE,data);
         break;

      case 0xc7c:           /* pci data address (0xc7c) */
         pci_dev_data_handler(cpu,mv_data->bus[1],op_type,FALSE,data);
         break;

      /* MII */
      case 0x2004:
         if (op_type == MTS_READ)
            *data = 0x08000000;
         break;

      /* GPP interrupt cause */
      case MV64460_REG_GPP_INTR_CAUSE:
         if (op_type == MTS_READ)
            *data = mv_data->gpp_intr;
         break;

      /* GPP interrupt mask0 */
      case MV64460_REG_GPP_INTR_MASK0:
         if (op_type == MTS_READ) {
            *data = mv_data->gpp_mask0;
         } else {
            mv_data->gpp_mask0 = *data;
            mv64460_gpio_update_int_status(mv_data);
         }
         break;

      /* GPP interrupt mask1 */
      case MV64460_REG_GPP_INTR_MASK1:
         if (op_type == MTS_READ) {
            *data = mv_data->gpp_mask1;
         } else {
            mv_data->gpp_mask1 = *data;
            mv64460_gpio_update_int_status(mv_data);
         }
         break;

      /* GPP value set */
      case MV64460_REG_GPP_VALUE_SET:
         if (op_type == MTS_WRITE) {
            mv_data->gpp_intr |= *data;
            mv64460_gpio_update_int_status(mv_data);
         }
         break;

      /* GPP value clear */
      case MV64460_REG_GPP_VALUE_CLEAR:
         if (op_type == MTS_WRITE) {
            mv_data->gpp_intr &= ~(*data);
            mv64460_gpio_update_int_status(mv_data);
         }
         break;

      /* SDMA cause register */
      case MV64460_REG_SDMA_CAUSE:
         if (op_type == MTS_READ) {
            *data = mv_data->sdma_cause;
         } else {
            mv_data->sdma_cause = *data;
            mv64460_sdma_update_int_status(mv_data);
         }
         break;

      /* SDMA mask register */
      case MV64460_REG_SDMA_MASK:
         if (op_type == MTS_READ) {
            *data = mv_data->sdma_mask;
         } else {
            mv_data->sdma_mask = *data;
            mv64460_sdma_update_int_status(mv_data);
         }
         break;

      /* Integrated SRAM base address */ 
      case MV64460_REG_SRAM_BASE:
         if (op_type == MTS_READ) {
            *data = mv_data->sram_dev.phys_addr << MV64460_SRAM_WIDTH;
         } else {
            m_uint64_t sram_addr;

            sram_addr = *data & MV64460_SRAM_BASE_MASK;
            sram_addr >>= MV64460_SRAM_BASE_SHIFT;
            sram_addr <<= MV64460_SRAM_WIDTH;

            vm_map_device(mv_data->vm,&mv_data->sram_dev,sram_addr);

            MV64460_LOG(mv_data,"SRAM mapped at 0x%10.10llx\n",
                        mv_data->sram_dev.phys_addr);
         }
         break;

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

 done:
   MV64460_UNLOCK(mv_data);
   if ((op_type == MTS_READ) && (op_size == 4))
      *data = swap32(*data);
   return NULL;
}
/*
 * SDMA registers access.
 */
static int mv64460_sdma_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 mv64460_data *mv_data = dev->priv_data;
   struct sdma_channel *channel;
   int id = -1;

   /* Access to SDMA channel 0 registers ? */
   if ((offset >= MV64460_REG_SDMA0) && 
       (offset < (MV64460_REG_SDMA0 + 0x1000))) 
   {
      offset -= MV64460_REG_SDMA0;
      id = 0;
   }

   /* Access to SDMA channel 1 registers ? */
   if ((offset >= MV64460_REG_SDMA1) && 
       (offset < (MV64460_REG_SDMA1 + 0x1000))) 
   {
      offset -= MV64460_REG_SDMA1;
      id = 1;
   }
   
   if (id == -1)
      return(FALSE);

   channel = &mv_data->sdma[id];

   switch(offset) {
      case MV64460_SDMA_SDCM:
         if (op_type == MTS_READ)
            ; //*data = chan->sdcm;
         else {
            channel->sdcm = *data;

            if (channel->sdcm & MV64460_SDCMR_TXD) {
               while(mv64460_sdma_tx_start(mv_data,channel))
                  ;
            }
         }
         break;

      case MV64460_SDMA_SCRDP:
         if (op_type == MTS_READ)
            *data = channel->scrdp;
         else
            channel->scrdp = *data;
         break;

      case MV64460_SDMA_SCTDP:
         if (op_type == MTS_READ)
            *data = channel->sctdp;
         else
            channel->sctdp = *data;
         break;

      case MV64460_SDMA_SFTDP:
         if (op_type == MTS_READ)
            *data = channel->sftdp;
         else
            channel->sftdp = *data;
         break;

#if DEBUG_UNKNOWN
      default:
         if (op_type == MTS_READ) {
            cpu_log(cpu,"MV64460/SDMA",
                    "read access to unknown register 0x%x, pc=0x%llx\n",
                    offset,cpu_get_pc(cpu));
         } else {
            cpu_log(cpu,"MV64460/SDMA",
                    "write access to unknown register 0x%x, value=0x%llx, "
                    "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu));
         }
#endif
   }

   return(TRUE);
}
Beispiel #17
0
/*
 * pos_cs_access()
 */
static void *dev_pos_cs_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 pos_oc3_data *d = dev->priv_data;

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

#if DEBUG_ACCESS
   if (op_type == MTS_READ) {
      cpu_log(cpu,d->cs_name,"read  access to offset = 0x%x, pc = 0x%llx\n",
              offset,cpu_get_pc(cpu));
   } else {
      cpu_log(cpu,d->cs_name,"write access to vaddr = 0x%x, pc = 0x%llx, "
              "val = 0x%llx\n",offset,cpu_get_pc(cpu),*data);
   }
#endif

   switch(offset) {
      case 0x300000:
      case 0x300004:
      case 0x30001c:
         if (op_type == MTS_READ) {
            *data = 0x00000FFF;

            /* Add a delay before clearing the IRQ */
            if (++d->irq_clearing_count == 20) {
               pci_dev_clear_irq(d->vm,d->pci_dev);
               d->irq_clearing_count = 0;
            }
         }     
         break;

      case 0x300008:
         if (op_type == MTS_READ)
            *data = 0x000007F;      
         break;

      case 0x300028:
         if (op_type == MTS_READ) {
            *data = d->ctrl_reg1;
         } else {
            d->ctrl_reg1 = *data;

            switch(*data) {
               case 0x06:
                  d->crc_size = 2;
                  break;
               case 0x07:
                  d->crc_size = 4;
                  break;
               default:
                  d->crc_size = 2;
                  cpu_log(cpu,d->cs_name,
                          "unknown value 0x%4.4llx written in ctrl_reg1\n",
                          *data);
            }
            cpu_log(cpu,d->cs_name,"CRC size set to 0x%4.4x\n",d->crc_size);
         }
         break;

#if DEBUG_UNKNOWN
      default:
         if (op_type == MTS_READ) {
            cpu_log(cpu,d->cs_name,
                    "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
                    offset,cpu_get_pc(cpu),op_size);
         } else {
            cpu_log(cpu,d->cs_name,
                    "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_c1700_iofpga_access()
 */
static void *
dev_c1700_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 c1700_iofpga_data *d = dev->priv_data;

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

#if DEBUG_ACCESS
   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) {
      /* 
       * Bits 0-2: motherboard model (change with caution, different log patterns)
       *  0=MPC860T
       *  1=MPC860T
       *  2=MPC860
       *  3=MPC860P
       *  4=MPC862P
       *  5=MPC855T
       *  6=MPC860P
       *  7=(see iofpga[5]&0xf)
       * Bits 3-7: ???
       */
      case 0x04:
         break;

      /* (iopfga[4]&0x7 == 7)
       * Bits 0-3: extended motherboard model
       *  0-1=MPC860P
       *  2-15=MPC860
       * Bits 4-7: ??? related to clock speed?
      case 0x05:
      */

      /* (iopfga[4]&0x7 == 7 and iofpga[5]&0xF == 1)
       * Bits 0-7: ???
      case 0x0A:
      */

      /* 
       * Bit 0: ???
       * Bit 1: card present in slot 0 / WIC 0.
       * Bit 2: card present in slot 0 / WIC 1.
       * Bit 3: compression/VPN module ? (mention of "slot 3")
       * Bits 4-7: ???
       */
      case 0x10:
         if (op_type == MTS_READ) {
            *data = 0;

            /* check WIC 0 */
            if (vm_slot_check_eeprom(d->router->vm,0,0x10))
               *data |= 0x02;

            /* check WIC 1 */
            if (vm_slot_check_eeprom(d->router->vm,0,0x20))
               *data |= 0x04;
         }
         break;

      /* 
       * Bit 0: ??? NVRAM write protection?
       * Bit 1: ???
       * Bit 2: ??? related to syscalls?
       * Bits 3-7: ???
      case 0x14:
      */

      /* WIC card selection for EEPROM reading
       * Bits 0-2: ???
       * Bit 3: wic_port 0x10
       * Bit 4: ???
       * Bit 5: wic_port 0x20
       * Bits 6-7: ???
       */
      case 0x18:
         if (op_type == MTS_READ)
            *data = d->wic_select;
         else {
            d->wic_select = *data;
         }
         break;

      /* 
       * Bit 0-7: ???
      case 0x20:
      */

      /* Unknown, read on 1760 */
      case 0x4c:
         if (op_type == MTS_READ)
            *data = 0xFF;
         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;
}
/*
 * 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;
}
Beispiel #21
0
/*
 * dev_c2600_iofpga_access()
 */
static void *
dev_c2600_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 c2600_iofpga_data *d = dev->priv_data;

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

#if DEBUG_ACCESS
   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) {
      case 0x04:
         if (op_type == MTS_READ)
            *data = 0x00;
         break;

      /* 
       * Network Interrupt.
       *
       * Bit 0-3: slot 1.
       * Bit 4: slot 0 (MB), port 0
       * Bit 5: slot 0 (MB), port 1
       * Other: AIM ? (error messages displayed)
       */
      case 0x08:
         if (op_type == MTS_READ)
            *data = d->net_irq_status;
         break;

      case 0x10:
         if (op_type == MTS_READ)
            *data = d->wic_select;
         else {
            d->wic_select = *data;
         }
         break;

      case 0x14:
         if (op_type == MTS_READ)
            *data = 0; //0xFFFFFFFF;
         break;

      /* 
       * Flash Related: 0x1y
       * 
       * Bit 1: card present in slot 0 / WIC 0.
       * Bit 2: card present in slot 0 / WIC 1.
       *
       * Other bits unknown.
       */
      case 0x0c:
         if (op_type == MTS_READ) {
            *data = 0x10;

            /* check WIC 0 */
            if (vm_slot_check_eeprom(d->router->vm,0,0x10))
               *data |= 0x02;

            /* check WIC 1 */
            if (vm_slot_check_eeprom(d->router->vm,0,0x20))
               *data |= 0x04;
         }
         break;

      /* NM EEPROM */
      case 0x1c:
         if (op_type == MTS_WRITE)
            nmc93cX6_write(&d->router->nm_eeprom_group,(u_int)(*data));
         else
            *data = nmc93cX6_read(&d->router->nm_eeprom_group);
         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;
}