📄 dev_c2600.c
字号:
/* Set the cookie */ memcpy(router->vm->chassis_cookie, eeprom_c2600_mb_data,sizeof(eeprom_c2600_mb_data)); router->vm->chassis_cookie[6] = mb_info->id; /* Set the chassis base MAC address */ c2600_burn_mac_addr(router,&router->mac_addr); /* Set the mainboard driver */ if (vm_slot_active(router->vm,0,0)) vm_slot_remove_binding(router->vm,0,0); vm_slot_add_binding(router->vm,mb_info->mb_driver,0,0); return(0);}/* Set chassis MAC address */int c2600_chassis_set_mac_addr(c2600_t *router,char *mac_addr){ if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) { vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr); return(-1); } /* Set the chassis base MAC address */ c2600_burn_mac_addr(router,&router->mac_addr); return(0);}/* Initialize a Cisco 2600 */static int c2600_init(c2600_t *router){ vm_instance_t *vm = router->vm; /* Create the PCI bus */ if (!(vm->pci_bus[0] = pci_bus_create("PCI0",0))) { vm_error(vm,"unable to create PCI data.\n"); return(-1); } /* Create the PCI controller */ if (dev_c2600_pci_init(vm,"c2600_pci",C2600_PCICTRL_ADDR,0x10000, vm->pci_bus[0]) == -1) return(-1); /* Bind PCI bus to slots 0 and 1 */ vm->slots_pci_bus[0] = vm->pci_bus[0]; vm->slots_pci_bus[1] = vm->pci_bus[0]; vm->elf_machine_id = C2600_ELF_MACHINE_ID; return(0);}/* Show C2600 hardware info */void c2600_show_hardware(c2600_t *router){ vm_instance_t *vm = router->vm; printf("C2600 instance '%s' (id %d):\n",vm->name,vm->instance_id); printf(" VM Status : %d\n",vm->status); printf(" RAM size : %u Mb\n",vm->ram_size); printf(" NVRAM size : %u Kb\n",vm->nvram_size); printf(" IOS image : %s\n\n",vm->ios_image); if (vm->debug_level > 0) { dev_show_list(vm); pci_dev_show_list(vm->pci_bus[0]); pci_dev_show_list(vm->pci_bus[1]); printf("\n"); }}/* Initialize default parameters for a C2600 */static void c2600_init_defaults(c2600_t *router){ vm_instance_t *vm = router->vm; n_eth_addr_t *m; m_uint16_t pid; /* Set platform slots characteristics */ vm->nr_slots = C2600_MAX_NM_BAYS; vm->slots_type = CISCO_CARD_TYPE_NM; vm->slots_drivers = nm_drivers; pid = (m_uint16_t)getpid(); /* Generate a chassis MAC address based on the instance ID */ m = &router->mac_addr; m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm); m->eth_addr_byte[1] = vm->instance_id & 0xFF; m->eth_addr_byte[2] = pid >> 8; m->eth_addr_byte[3] = pid & 0xFF; m->eth_addr_byte[4] = 0x00; m->eth_addr_byte[5] = 0x00; c2600_init_eeprom_groups(router); c2600_mainboard_set_type(router,C2600_DEFAULT_MAINBOARD); c2600_burn_mac_addr(router,&router->mac_addr); vm->ram_mmap = C2600_DEFAULT_RAM_MMAP; vm->ram_size = C2600_DEFAULT_RAM_SIZE; vm->rom_size = C2600_DEFAULT_ROM_SIZE; vm->nvram_size = C2600_DEFAULT_NVRAM_SIZE; vm->conf_reg_setup = C2600_DEFAULT_CONF_REG; vm->clock_divisor = C2600_DEFAULT_CLOCK_DIV; vm->nvram_rom_space = C2600_NVRAM_ROM_RES_SIZE; vm->nm_iomem_size = C2600_DEFAULT_IOMEM_SIZE; vm->pcmcia_disk_size[0] = C2600_DEFAULT_DISK0_SIZE; vm->pcmcia_disk_size[1] = C2600_DEFAULT_DISK1_SIZE;}/* Set an IRQ */static void c2600_set_irq(vm_instance_t *vm,u_int irq){ c2600_t *router = VM_C2600(vm); cpu_ppc_t *cpu = CPU_PPC32(vm->boot_cpu); u_int slot,port; switch(irq) { case C2600_VTIMER_IRQ: mpc860_set_pending_irq(router->mpc_data,30); break; case C2600_DUART_IRQ: mpc860_set_pending_irq(router->mpc_data,29); break; case C2600_NETIO_IRQ: mpc860_set_pending_irq(router->mpc_data,25); break; case C2600_PA_MGMT_IRQ: mpc860_set_pending_irq(router->mpc_data,27); break; case C2600_NETIO_IRQ_BASE ... C2600_NETIO_IRQ_END: c2600_net_irq_get_slot_port(irq,&slot,&port); dev_c2600_iofpga_net_set_irq(router->iofpga_data,slot,port); break; /* IRQ test */ case 255: mpc860_set_pending_irq(router->mpc_data,24); break; } if (vm->irq_idle_preempt[irq]) cpu_idle_break_wait(cpu->gen);}/* Clear an IRQ */static void c2600_clear_irq(vm_instance_t *vm,u_int irq){ c2600_t *router = VM_C2600(vm); u_int slot,port; switch(irq) { case C2600_VTIMER_IRQ: mpc860_clear_pending_irq(router->mpc_data,30); break; case C2600_DUART_IRQ: mpc860_clear_pending_irq(router->mpc_data,29); break; case C2600_NETIO_IRQ: mpc860_clear_pending_irq(router->mpc_data,25); break; case C2600_PA_MGMT_IRQ: mpc860_clear_pending_irq(router->mpc_data,27); break; case C2600_NETIO_IRQ_BASE ... C2600_NETIO_IRQ_END: c2600_net_irq_get_slot_port(irq,&slot,&port); dev_c2600_iofpga_net_clear_irq(router->iofpga_data,slot,port); break; /* IRQ test */ case 255: mpc860_clear_pending_irq(router->mpc_data,24); break; }}/* Initialize the C2600 Platform */static int c2600_init_platform(c2600_t *router){ vm_instance_t *vm = router->vm; vm_obj_t *obj; cpu_ppc_t *cpu; cpu_gen_t *gen; /* Copy config register setup into "active" config register */ vm->conf_reg = vm->conf_reg_setup; /* Create Console and AUX ports */ vm_init_vtty(vm); /* Create a CPU group */ vm->cpu_group = cpu_group_create("System CPU"); /* Initialize the virtual PowerPC processor */ if (!(gen = cpu_create(vm,CPU_TYPE_PPC32,0))) { vm_error(vm,"unable to create CPU!\n"); return(-1); } cpu = CPU_PPC32(gen); /* Add this CPU to the system CPU group */ cpu_group_add(vm->cpu_group,gen); vm->boot_cpu = gen; /* Set processor ID */ ppc32_set_pvr(cpu,0x00500202); /* Mark the Network IO interrupt as high priority */ vm->irq_idle_preempt[C2600_NETIO_IRQ] = TRUE; vm->irq_idle_preempt[C2600_DUART_IRQ] = TRUE; /* Copy some parameters from VM to CPU (idle PC, ...) */ cpu->idle_pc = vm->idle_pc; if (vm->timer_irq_check_itv) cpu->timer_irq_check_itv = vm->timer_irq_check_itv; /* Remote emulator control */ dev_remote_control_init(vm,0xf6000000,0x1000); /* MPC860 */ cpu->mpc860_immr = C2600_MPC860_ADDR; if (dev_mpc860_init(vm,"MPC860",C2600_MPC860_ADDR,0x10000) == -1) return(-1); if (!(obj = vm_object_find(router->vm,"MPC860"))) return(-1); router->mpc_data = obj->data; /* IO FPGA */ if (dev_c2600_iofpga_init(router,C2600_IOFPGA_ADDR,0x10000) == -1) return(-1); if (!(obj = vm_object_find(router->vm,"io_fpga"))) return(-1); router->iofpga_data = obj->data; /* Initialize the chassis */ if (c2600_init(router) == -1) return(-1); /* Initialize RAM */ vm_ram_init(vm,0x00000000ULL); /* Initialize ROM */ if (!vm->rom_filename) { /* use embedded ROM */ dev_rom_init(vm,"rom",C2600_ROM_ADDR,512*1024, ppc32_microcode,ppc32_microcode_len); } else { /* use alternate ROM */ dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE,C2600_ROM_ADDR,512*1024); } /* RAM aliasing */ dev_create_ram_alias(vm,"ram_alias","ram",0x80000000,vm->ram_size*1048576); /* NVRAM */ dev_ram_init(vm,"nvram",TRUE,FALSE,NULL,FALSE, C2600_NVRAM_ADDR,vm->nvram_size*4096); c2600_nvram_check_empty_config(vm); /* Bootflash */ dev_bootflash_init(vm,"flash0","c2600-bootflash-8mb", C2600_FLASH_ADDR); dev_bootflash_init(vm,"flash1","c2600-bootflash-8mb", C2600_FLASH_ADDR+0x800000); /* Initialize the NS16552 DUART */ dev_ns16552_init(vm,C2600_DUART_ADDR,0x1000,0,C2600_DUART_IRQ, vm->vtty_con,vm->vtty_aux); /* Initialize Network Modules */ if (vm_slot_init_all(vm) == -1) return(-1); /* Show device list */ c2600_show_hardware(router); return(0);}static struct ppc32_bat_prog bat_array[] = { { PPC32_IBAT_IDX, 0, 0xfff0001e, 0xfff00001 }, { PPC32_IBAT_IDX, 1, 0x00001ffe, 0x00000001 }, { PPC32_IBAT_IDX, 2, 0x00000000, 0xee3e0072 }, { PPC32_IBAT_IDX, 3, 0x80001ffe, 0x00000001 }, { PPC32_DBAT_IDX, 0, 0x80001ffe, 0x00000042 }, { PPC32_DBAT_IDX, 1, 0x00001ffe, 0x0000002a }, { PPC32_DBAT_IDX, 2, 0x40007ffe, 0x4000002a }, { PPC32_DBAT_IDX, 3, 0xf0001ffe, 0xf000002a }, { -1, -1, 0, 0 },};/* Boot the IOS image */int c2600_boot_ios(c2600_t *router){ vm_instance_t *vm = router->vm; cpu_ppc_t *cpu; if (!vm->boot_cpu) return(-1); /* Suspend CPU activity since we will restart directly from ROM */ vm_suspend(vm); /* Check that CPU activity is really suspended */ if (cpu_group_sync_state(vm->cpu_group) == -1) { vm_error(vm,"unable to sync with system CPUs.\n"); return(-1); } /* Reset the boot CPU */ cpu = CPU_PPC32(vm->boot_cpu); ppc32_reset(cpu); /* Adjust stack pointer */ cpu->gpr[1] |= 0x80000000; /* Load BAT registers */ printf("Loading BAT registers\n"); ppc32_load_bat_array(cpu,bat_array); cpu->msr |= PPC32_MSR_IR|PPC32_MSR_DR; /* IRQ routing */ vm->set_irq = c2600_set_irq; vm->clear_irq = c2600_clear_irq; /* Load IOS image */ if (ppc32_load_elf_image(cpu,vm->ios_image, (vm->ghost_status == VM_GHOST_RAM_USE), &vm->ios_entry_point) < 0) { vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image); return(-1); } /* Launch the simulation */ printf("\nC2600 '%s': starting simulation (CPU0 IA=0x%8.8x), " "JIT %sabled.\n", vm->name,cpu->ia,vm->jit_use ? "en":"dis"); vm_log(vm,"C2600_BOOT", "starting instance (CPU0 PC=0x%8.8x,idle_pc=0x%8.8x,JIT %s)\n", cpu->ia,cpu->idle_pc,vm->jit_use ? "on":"off"); /* Start main CPU */ if (vm->ghost_status != VM_GHOST_RAM_GENERATE) { vm->status = VM_STATUS_RUNNING; cpu_start(vm->boot_cpu); } else { vm->status = VM_STATUS_SHUTDOWN; } return(0);}/* Initialize a Cisco 2600 instance */static int c2600_init_instance(vm_instance_t *vm){ c2600_t *router = VM_C2600(vm); m_uint32_t rom_entry_point; cpu_ppc_t *cpu0; if (!vm->ios_image) { vm_error(vm,"no Cisco IOS image defined."); return(-1); } /* Initialize the C2600 platform */ if (c2600_init_platform(router) == -1) { vm_error(vm,"unable to initialize the platform hardware.\n"); return(-1); } /* Load IOS configuration file */ if (vm->ios_config != NULL) { vm_nvram_push_config(vm,vm->ios_config); vm->conf_reg &= ~0x40; } /* Load ROM (ELF image or embedded) */ cpu0 = CPU_PPC32(vm->boot_cpu); rom_entry_point = (m_uint32_t)PPC32_ROM_START; if ((vm->rom_filename != NULL) && (ppc32_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0)) { vm_error(vm,"unable to load alternate ROM '%s', " "fallback to embedded ROM.\n\n",vm->rom_filename); vm->rom_filename = NULL; } return(c2600_boot_ios(router));}/* Stop a Cisco 2600 instance */int c2600_stop_instance(vm_instance_t *vm){ printf("\nC2600 '%s': stopping simulation.\n",vm->name); vm_log(vm,"C2600_STOP","stopping simulation.\n"); /* Stop all CPUs */ if (vm->cpu_group != NULL) { vm_stop(vm); if (cpu_group_sync_state(vm->cpu_group) == -1) { vm_error(vm,"unable to sync with system CPUs.\n"); return(-1); } } /* Free resources that were used during execution to emulate hardware */ vm_slot_shutdown_all(vm); vm_hardware_shutdown(vm); /* Cleanup */ VM_C2600(vm)->iofpga_data = NULL; VM_C2600(vm)->mpc_data = NULL; return(0);}/* Get MAC address MSB */static u_int c2600_get_mac_addr_msb(void){ return(0xC8);}/* Parse specific options for the Cisco 2600 platform */static int c2600_cli_parse_options(vm_instance_t *vm,int option){ c2600_t *router = VM_C2600(vm); switch(option) { /* IO memory reserved for NMs (in percents!) */ case OPT_IOMEM_SIZE: vm->nm_iomem_size = 0x8000 | atoi(optarg); break; /* Mainboard type */ case 't': c2600_mainboard_set_type(router,optarg); break; /* Unknown option */ default: return(-1); } return(0);}/* Show specific CLI options */static void c2600_cli_show_options(vm_instance_t *vm){ printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n" " -p <nm_desc> : Define a Network Module\n" " -s <nm_nio> : Bind a Network IO interface to a " "Network Module\n", vm->nm_iomem_size);}/* Platform definition */static vm_platform_t c2600_platform = { "c2600", "C2600", "2600", c2600_create_instance, c2600_delete_instance, c2600_init_instance, c2600_stop_instance, c2600_nvram_extract_config, c2600_nvram_push_config, c2600_get_mac_addr_msb, c2600_save_config, c2600_cli_parse_options, c2600_cli_show_options, c2600_mainboard_show_drivers,};/* Register the c2600 platform */int c2600_platform_register(void){ if (vm_platform_register(&c2600_platform) == -1) return(-1); return(hypervisor_c2600_init(&c2600_platform));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -