/* * 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; }
/* * 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; }
/* * 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; }
/* 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 } } }
/* 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; } }
/* * 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; }
/* 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 } } }
/* 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; } } }
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; } }
/* 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 {
/* * 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; }
/* * 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); }
/* * 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; }
/* * 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; }