|
|
1.1 ! root 1: /* ! 2: * Cisco router simulation platform. ! 3: * Copyright (c) 2007 Christophe Fillot ([email protected]) ! 4: * ! 5: * Generic MSFC1 routines and definitions (EEPROM,...). ! 6: * ! 7: * This is not a working platform! I only added it to play, since it is very ! 8: * similar to an NPE-200. I think that could work with a functional CatOS SP. ! 9: */ ! 10: ! 11: #include <stdio.h> ! 12: #include <stdlib.h> ! 13: #include <string.h> ! 14: #include <unistd.h> ! 15: #include <sys/types.h> ! 16: #include <assert.h> ! 17: ! 18: #include "cpu.h" ! 19: #include "vm.h" ! 20: #include "dynamips.h" ! 21: #include "memory.h" ! 22: #include "device.h" ! 23: #include "pci_io.h" ! 24: #include "dev_gt.h" ! 25: #include "cisco_eeprom.h" ! 26: #include "dev_rom.h" ! 27: #include "dev_dec21140.h" ! 28: #include "dev_i8254x.h" ! 29: #include "dev_c6msfc1.h" ! 30: #include "dev_c6msfc1_mpfpga.h" ! 31: #include "dev_vtty.h" ! 32: #include "registry.h" ! 33: #include "net.h" ! 34: ! 35: /* MSFC1 EEPROM */ ! 36: static m_uint16_t eeprom_msfc1_data[128] = { ! 37: 0xabab, 0x0190, 0x1262, 0x0100, 0x0002, 0x6003, 0x00cf, 0x4369, ! 38: 0x7363, 0x6f20, 0x5379, 0x7374, 0x656d, 0x732c, 0x2049, 0x6e63, ! 39: 0x2e00, 0x5753, 0x2d46, 0x3630, 0x3031, 0x2d52, 0x5346, 0x4300, ! 40: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 41: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3733, 0x2d37, 0x3135, ! 42: 0x302d, 0x3036, 0x0000, 0x0000, 0x0000, 0x4130, 0x3100, 0x0000, ! 43: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 44: 0x0000, 0x0000, 0x012d, 0x0000, 0x0000, 0x0009, 0x0005, 0x0001, ! 45: 0x0003, 0x0001, 0x0001, 0x0002, 0x00cf, 0xffbf, 0x0000, 0x0000, ! 46: 0x6003, 0x0162, 0x0afd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 47: 0x0000, 0x0000, 0x0000, 0x0005, 0x00e0, 0xaabb, 0xcc00, 0x0100, ! 48: 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 49: 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 50: 0x1401, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, ! 51: 0x1000, 0x4b3c, 0x4132, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, ! 52: 0x8080, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, ! 53: }; ! 54: ! 55: static struct cisco_eeprom msfc1_eeprom = { ! 56: "msfc1", eeprom_msfc1_data, sizeof(eeprom_msfc1_data)/2, ! 57: }; ! 58: ! 59: /* ====================================================================== */ ! 60: /* EOBC - Ethernet Out of Band Channel */ ! 61: /* ====================================================================== */ ! 62: static int dev_c6msfc1_eobc_init(vm_instance_t *vm,struct cisco_card *card) ! 63: { ! 64: struct dec21140_data *data; ! 65: ! 66: /* Create the DEC21140 chip */ ! 67: data = dev_dec21140_init(vm,card->dev_name,vm->pci_bus[0],6, ! 68: c6msfc1_net_irq_for_slot_port(0,0)); ! 69: if (!data) return(-1); ! 70: ! 71: /* Store device info into the router structure */ ! 72: card->drv_info = data; ! 73: return(0); ! 74: } ! 75: ! 76: /* Remove EOBC */ ! 77: static int dev_c6msfc1_eobc_shutdown(vm_instance_t *vm,struct cisco_card *card) ! 78: { ! 79: struct dec21140_data *data = card->drv_info; ! 80: dev_dec21140_remove(data); ! 81: return(0); ! 82: } ! 83: ! 84: /* Bind a Network IO descriptor */ ! 85: static int dev_c6msfc1_eobc_set_nio(vm_instance_t *vm,struct cisco_card *card, ! 86: u_int port_id,netio_desc_t *nio) ! 87: { ! 88: struct dec21140_data *d = card->drv_info; ! 89: ! 90: if (!d || (port_id != 0)) ! 91: return(-1); ! 92: ! 93: return(dev_dec21140_set_nio(d,nio)); ! 94: } ! 95: ! 96: /* Unbind a Network IO descriptor */ ! 97: static int dev_c6msfc1_eobc_unset_nio(vm_instance_t *vm, ! 98: struct cisco_card *card, ! 99: u_int port_id) ! 100: { ! 101: struct dec21140_data *d = card->drv_info; ! 102: ! 103: if (!d || (port_id != 0)) ! 104: return(-1); ! 105: ! 106: dev_dec21140_unset_nio(d); ! 107: return(0); ! 108: } ! 109: ! 110: /* EOBC driver */ ! 111: struct cisco_card_driver dev_c6msfc1_eobc = { ! 112: "C6MSFC1_EOBC", 0, 0, ! 113: dev_c6msfc1_eobc_init, ! 114: dev_c6msfc1_eobc_shutdown, ! 115: NULL, ! 116: dev_c6msfc1_eobc_set_nio, ! 117: dev_c6msfc1_eobc_unset_nio, ! 118: NULL, ! 119: }; ! 120: ! 121: /* ====================================================================== */ ! 122: /* IBC - InBand Channel */ ! 123: /* ====================================================================== */ ! 124: static int dev_c6msfc1_ibc_init(vm_instance_t *vm,struct cisco_card *card) ! 125: { ! 126: struct i8254x_data *data; ! 127: ! 128: /* Create the Intel Wiseman/Livengood chip */ ! 129: data = dev_i8254x_init(vm,card->dev_name,0,vm->pci_bus_pool[24],1, ! 130: c6msfc1_net_irq_for_slot_port(1,0)); ! 131: if (!data) return(-1); ! 132: ! 133: /* Store device info into the router structure */ ! 134: card->drv_info = data; ! 135: return(0); ! 136: } ! 137: ! 138: /* Remove EOBC */ ! 139: static int dev_c6msfc1_ibc_shutdown(vm_instance_t *vm,struct cisco_card *card) ! 140: { ! 141: struct i8254x_data *data = card->drv_info; ! 142: dev_i8254x_remove(data); ! 143: return(0); ! 144: } ! 145: ! 146: /* Bind a Network IO descriptor */ ! 147: static int dev_c6msfc1_ibc_set_nio(vm_instance_t *vm,struct cisco_card *card, ! 148: u_int port_id,netio_desc_t *nio) ! 149: { ! 150: struct i8254x_data *d = card->drv_info; ! 151: ! 152: if (!d || (port_id != 0)) ! 153: return(-1); ! 154: ! 155: return(dev_i8254x_set_nio(d,nio)); ! 156: } ! 157: ! 158: /* Unbind a Network IO descriptor */ ! 159: static int dev_c6msfc1_ibc_unset_nio(vm_instance_t *vm, ! 160: struct cisco_card *card, ! 161: u_int port_id) ! 162: { ! 163: struct i8254x_data *d = card->drv_info; ! 164: ! 165: if (!d || (port_id != 0)) ! 166: return(-1); ! 167: ! 168: dev_i8254x_unset_nio(d); ! 169: return(0); ! 170: } ! 171: ! 172: /* IBC driver */ ! 173: struct cisco_card_driver dev_c6msfc1_ibc = { ! 174: "C6MSFC1_IBC", 0, 0, ! 175: dev_c6msfc1_ibc_init, ! 176: dev_c6msfc1_ibc_shutdown, ! 177: NULL, ! 178: dev_c6msfc1_ibc_set_nio, ! 179: dev_c6msfc1_ibc_unset_nio, ! 180: NULL, ! 181: }; ! 182: ! 183: /* ======================================================================== */ ! 184: /* Port Adapter Drivers */ ! 185: /* ======================================================================== */ ! 186: static struct cisco_card_driver *pa_drivers[] = { ! 187: &dev_c6msfc1_eobc, ! 188: &dev_c6msfc1_ibc, ! 189: NULL, ! 190: }; ! 191: ! 192: /* ======================================================================== */ ! 193: /* C6MSFC1 router instances */ ! 194: /* ======================================================================== */ ! 195: ! 196: /* Initialize default parameters for a MSFC1 */ ! 197: static void c6msfc1_init_defaults(c6msfc1_t *router); ! 198: ! 199: /* Directly extract the configuration from the NVRAM device */ ! 200: static ssize_t c6msfc1_nvram_extract_config(vm_instance_t *vm,u_char **buffer) ! 201: { ! 202: u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr; ! 203: m_uint32_t start,end,nvlen,clen; ! 204: m_uint16_t magic1,magic2; ! 205: struct vdevice *nvram_dev; ! 206: m_uint64_t nvram_addr; ! 207: off_t nvram_size; ! 208: int fd; ! 209: ! 210: if ((nvram_dev = dev_get_by_name(vm,"nvram"))) ! 211: dev_sync(nvram_dev); ! 212: ! 213: fd = vm_mmap_open_file(vm,"nvram",&base_ptr,&nvram_size); ! 214: ! 215: if (fd == -1) ! 216: return(-1); ! 217: ! 218: nvram_addr = C6MSFC1_NVRAM_ADDR; ! 219: ios_ptr = base_ptr + vm->nvram_rom_space; ! 220: end_ptr = base_ptr + nvram_size; ! 221: ! 222: if ((ios_ptr + 0x30) >= end_ptr) { ! 223: vm_error(vm,"NVRAM file too small\n"); ! 224: return(-1); ! 225: } ! 226: ! 227: magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06)); ! 228: magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08)); ! 229: ! 230: if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) { ! 231: vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n", ! 232: magic1,magic2); ! 233: return(-1); ! 234: } ! 235: ! 236: start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1; ! 237: end = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x14)); ! 238: nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18)); ! 239: clen = end - start; ! 240: ! 241: if ((clen + 1) != nvlen) { ! 242: vm_error(vm,"invalid configuration size (0x%x)\n",nvlen); ! 243: return(-1); ! 244: } ! 245: ! 246: if (!(*buffer = malloc(clen+1))) { ! 247: vm_error(vm,"unable to allocate config buffer (%u bytes)\n",clen); ! 248: return(-1); ! 249: } ! 250: ! 251: cfg_ptr = base_ptr + (start - nvram_addr); ! 252: ! 253: if ((start < nvram_addr) || ((cfg_ptr + clen) > end_ptr)) { ! 254: vm_error(vm,"NVRAM file too small\n"); ! 255: return(-1); ! 256: } ! 257: ! 258: memcpy(*buffer,cfg_ptr,clen); ! 259: (*buffer)[clen] = 0; ! 260: return(clen); ! 261: } ! 262: ! 263: /* Directly push the IOS configuration to the NVRAM device */ ! 264: static int c6msfc1_nvram_push_config(vm_instance_t *vm, ! 265: u_char *buffer,size_t len) ! 266: { ! 267: u_char *base_ptr,*ios_ptr,*cfg_ptr; ! 268: m_uint32_t cfg_addr,cfg_offset; ! 269: m_uint32_t nvram_addr,cklen; ! 270: m_uint16_t cksum; ! 271: int fd; ! 272: ! 273: fd = vm_mmap_create_file(vm,"nvram",vm->nvram_size*1024,&base_ptr); ! 274: ! 275: if (fd == -1) ! 276: return(-1); ! 277: ! 278: cfg_offset = 0x2c; ! 279: ios_ptr = base_ptr + vm->nvram_rom_space; ! 280: cfg_ptr = ios_ptr + cfg_offset; ! 281: ! 282: nvram_addr = C6MSFC1_NVRAM_ADDR; ! 283: cfg_addr = nvram_addr + vm->nvram_rom_space + cfg_offset; ! 284: ! 285: /* Write IOS tag, uncompressed config... */ ! 286: *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5); ! 287: *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD); ! 288: *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001); ! 289: *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000); ! 290: *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0000); ! 291: ! 292: /* Store file contents to NVRAM */ ! 293: memcpy(cfg_ptr,buffer,len); ! 294: ! 295: /* Write config addresses + size */ ! 296: *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(cfg_addr); ! 297: *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(cfg_addr + len); ! 298: *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len); ! 299: ! 300: /* Compute the checksum */ ! 301: cklen = (vm->nvram_size*1024) - (vm->nvram_rom_space + 0x08); ! 302: cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen); ! 303: *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum); ! 304: ! 305: vm_mmap_close_file(fd,base_ptr,vm->nvram_size*1024); ! 306: return(0); ! 307: } ! 308: ! 309: /* Get slot/port corresponding to specified network IRQ */ ! 310: static inline void ! 311: c6msfc1_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port) ! 312: { ! 313: *slot = irq - C6MSFC1_NETIO_IRQ_BASE; ! 314: *port = 0; ! 315: } ! 316: ! 317: /* Get network IRQ for specified slot/port */ ! 318: u_int c6msfc1_net_irq_for_slot_port(u_int slot,u_int port) ! 319: { ! 320: u_int irq; ! 321: ! 322: irq = C6MSFC1_NETIO_IRQ_BASE + slot; ! 323: return(irq); ! 324: } ! 325: ! 326: /* Set MSFC eeprom definition */ ! 327: static int c6msfc1_set_eeprom(c6msfc1_t *router) ! 328: { ! 329: if (cisco_eeprom_copy(&router->cpu_eeprom,&msfc1_eeprom) == -1) { ! 330: vm_error(router->vm,"unable to set NPE EEPROM.\n"); ! 331: return(-1); ! 332: } ! 333: ! 334: return(0); ! 335: } ! 336: ! 337: /* Set the base MAC address of the chassis */ ! 338: static int c6msfc1_burn_mac_addr(c6msfc1_t *router,n_eth_addr_t *addr) ! 339: { ! 340: m_uint8_t eeprom_ver; ! 341: ! 342: /* Read EEPROM format version */ ! 343: cisco_eeprom_get_byte(&router->mp_eeprom,0,&eeprom_ver); ! 344: ! 345: if (eeprom_ver != 1) { ! 346: vm_error(router->vm,"c6msfc1_burn_mac_addr: unable to handle " ! 347: "EEPROM version %u\n",eeprom_ver); ! 348: return(-1); ! 349: } ! 350: ! 351: cisco_eeprom_set_region(&router->mp_eeprom,12,addr->eth_addr_byte,6); ! 352: return(0); ! 353: } ! 354: ! 355: /* Create a new router instance */ ! 356: static int c6msfc1_create_instance(vm_instance_t *vm) ! 357: { ! 358: c6msfc1_t *router; ! 359: ! 360: if (!(router = malloc(sizeof(*router)))) { ! 361: fprintf(stderr,"C6MFC1 '%s': Unable to create new instance!\n",vm->name); ! 362: return(-1); ! 363: } ! 364: ! 365: memset(router,0,sizeof(*router)); ! 366: router->vm = vm; ! 367: vm->hw_data = router; ! 368: vm->elf_machine_id = C6MSFC1_ELF_MACHINE_ID; ! 369: ! 370: c6msfc1_init_defaults(router); ! 371: return(0); ! 372: } ! 373: ! 374: /* Free resources used by a router instance */ ! 375: static int c6msfc1_delete_instance(vm_instance_t *vm) ! 376: { ! 377: c6msfc1_t *router = VM_C6MSFC1(vm); ! 378: int i; ! 379: ! 380: /* Stop all CPUs */ ! 381: if (vm->cpu_group != NULL) { ! 382: vm_stop(vm); ! 383: ! 384: if (cpu_group_sync_state(vm->cpu_group) == -1) { ! 385: vm_error(vm,"unable to sync with system CPUs.\n"); ! 386: return(FALSE); ! 387: } ! 388: } ! 389: ! 390: /* Remove NIO bindings */ ! 391: for(i=0;i<C6MSFC1_MAX_PA_BAYS;i++) ! 392: vm_slot_remove_all_nio_bindings(vm,i); ! 393: ! 394: /* Shutdown all Network Modules */ ! 395: vm_slot_shutdown_all(vm); ! 396: ! 397: /* Free EEPROMs */ ! 398: cisco_eeprom_free(&router->cpu_eeprom); ! 399: cisco_eeprom_free(&router->mp_eeprom); ! 400: cisco_eeprom_free(&router->pem_eeprom); ! 401: ! 402: /* Free all resources used by VM */ ! 403: vm_free(vm); ! 404: ! 405: /* Free the router structure */ ! 406: free(router); ! 407: return(TRUE); ! 408: } ! 409: ! 410: /* Create the main PCI bus for a GT64010 based system */ ! 411: static int c6msfc1_init_gt64010(c6msfc1_t *router) ! 412: { ! 413: vm_instance_t *vm = router->vm; ! 414: ! 415: if (!(vm->pci_bus[0] = pci_bus_create("PCI Bus 0",0))) { ! 416: vm_error(vm,"unable to create PCI data.\n"); ! 417: return(-1); ! 418: } ! 419: ! 420: return(dev_gt64010_init(vm,"gt64010",C6MSFC1_GT64K_ADDR,0x1000, ! 421: C6MSFC1_GT64K_IRQ)); ! 422: } ! 423: ! 424: /* Initialize a MSFC1 board */ ! 425: static int c6msfc1_init_hw(c6msfc1_t *router) ! 426: { ! 427: vm_instance_t *vm = router->vm; ! 428: ! 429: /* Set the processor type: R5000 */ ! 430: mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R5000); ! 431: ! 432: /* Initialize the Galileo GT-64010 PCI controller */ ! 433: if (c6msfc1_init_gt64010(router) == -1) ! 434: return(-1); ! 435: ! 436: /* Create PCI bus 1 */ ! 437: vm->pci_bus_pool[24] = pci_bus_create("PCI Bus 1",-1); ! 438: dev_dec21154_init(vm->pci_bus[0],1,vm->pci_bus_pool[24]); ! 439: ! 440: /* Initialize SRAM (4Mb) */ ! 441: dev_c7200_sram_init(vm,"sram",C6MSFC1_SRAM_ADDR,C6MSFC1_SRAM_SIZE, ! 442: vm->pci_bus_pool[24],0); ! 443: ! 444: /* PCI IO space */ ! 445: if (!(vm->pci_io_space = pci_io_data_init(vm,C6MSFC1_PCI_IO_ADDR))) ! 446: return(-1); ! 447: ! 448: /* Cirrus Logic PD6729 (PCI-to-PCMCIA host adapter) */ ! 449: dev_clpd6729_init(vm,vm->pci_bus[0],5,vm->pci_io_space,0x402,0x403); ! 450: ! 451: return(0); ! 452: } ! 453: ! 454: /* Show MSFC1 hardware info */ ! 455: void c6msfc1_show_hardware(c6msfc1_t *router) ! 456: { ! 457: vm_instance_t *vm = router->vm; ! 458: ! 459: printf("C6MSFC1 instance '%s' (id %d):\n",vm->name,vm->instance_id); ! 460: ! 461: printf(" VM Status : %d\n",vm->status); ! 462: printf(" RAM size : %u Mb\n",vm->ram_size); ! 463: printf(" IOMEM size : %u Mb\n",vm->iomem_size); ! 464: printf(" NVRAM size : %u Kb\n",vm->nvram_size); ! 465: printf(" IOS image : %s\n\n",vm->ios_image); ! 466: ! 467: if (vm->debug_level > 0) { ! 468: dev_show_list(vm); ! 469: pci_dev_show_list(vm->pci_bus[0]); ! 470: pci_dev_show_list(vm->pci_bus[1]); ! 471: printf("\n"); ! 472: } ! 473: } ! 474: ! 475: /* Initialize default parameters for a MSFC1 */ ! 476: static void c6msfc1_init_defaults(c6msfc1_t *router) ! 477: { ! 478: vm_instance_t *vm = router->vm; ! 479: n_eth_addr_t *m; ! 480: m_uint16_t pid; ! 481: ! 482: /* Set platform slots characteristics */ ! 483: vm->nr_slots = C6MSFC1_MAX_PA_BAYS; ! 484: vm->slots_type = CISCO_CARD_TYPE_PA; ! 485: vm->slots_drivers = pa_drivers; ! 486: ! 487: pid = (m_uint16_t)getpid(); ! 488: ! 489: /* Generate a chassis MAC address based on the instance ID */ ! 490: m = &router->mac_addr; ! 491: m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm); ! 492: m->eth_addr_byte[1] = vm->instance_id & 0xFF; ! 493: m->eth_addr_byte[2] = pid >> 8; ! 494: m->eth_addr_byte[3] = pid & 0xFF; ! 495: m->eth_addr_byte[4] = 0x00; ! 496: m->eth_addr_byte[5] = 0x00; ! 497: ! 498: /* Default slot: 1 */ ! 499: router->msfc_slot = 1; ! 500: ! 501: c6msfc1_set_eeprom(router); ! 502: c6msfc1_init_eeprom_groups(router); ! 503: ! 504: /* Create EOBC and IBC interfaces */ ! 505: vm_slot_add_binding(vm,"C6MSFC1_EOBC",0,0); ! 506: vm_slot_add_binding(vm,"C6MSFC1_IBC",1,0); ! 507: ! 508: vm->ram_mmap = C6MSFC1_DEFAULT_RAM_MMAP; ! 509: vm->ram_size = C6MSFC1_DEFAULT_RAM_SIZE; ! 510: vm->rom_size = C6MSFC1_DEFAULT_ROM_SIZE; ! 511: vm->nvram_size = C6MSFC1_DEFAULT_NVRAM_SIZE; ! 512: vm->iomem_size = 0; ! 513: vm->conf_reg_setup = C6MSFC1_DEFAULT_CONF_REG; ! 514: vm->clock_divisor = C6MSFC1_DEFAULT_CLOCK_DIV; ! 515: vm->nvram_rom_space = C6MSFC1_NVRAM_ROM_RES_SIZE; ! 516: } ! 517: ! 518: /* Run the checklist */ ! 519: static int c6msfc1_checklist(c6msfc1_t *router) ! 520: { ! 521: struct vm_instance *vm = router->vm; ! 522: int res = 0; ! 523: ! 524: res += vm_object_check(vm,"ram"); ! 525: res += vm_object_check(vm,"rom"); ! 526: res += vm_object_check(vm,"nvram"); ! 527: res += vm_object_check(vm,"zero"); ! 528: ! 529: if (res < 0) ! 530: vm_error(vm,"incomplete initialization (no memory?)\n"); ! 531: ! 532: return(res); ! 533: } ! 534: ! 535: /* Initialize Port Adapters */ ! 536: static int c6msfc1_init_platform_pa(c6msfc1_t *router) ! 537: { ! 538: return(vm_slot_init_all(router->vm)); ! 539: } ! 540: ! 541: /* Initialize the MSFC1 Platform */ ! 542: static int c6msfc1_init_platform(c6msfc1_t *router) ! 543: { ! 544: struct vm_instance *vm = router->vm; ! 545: cpu_mips_t *cpu0; ! 546: cpu_gen_t *gen0; ! 547: vm_obj_t *obj; ! 548: ! 549: /* Copy config register setup into "active" config register */ ! 550: vm->conf_reg = vm->conf_reg_setup; ! 551: ! 552: /* Create Console and AUX ports */ ! 553: vm_init_vtty(vm); ! 554: ! 555: /* Create a CPU group */ ! 556: vm->cpu_group = cpu_group_create("System CPU"); ! 557: ! 558: /* Initialize the virtual MIPS processor */ ! 559: if (!(gen0 = cpu_create(vm,CPU_TYPE_MIPS64,0))) { ! 560: vm_error(vm,"unable to create CPU0!\n"); ! 561: return(-1); ! 562: } ! 563: ! 564: cpu0 = CPU_MIPS64(gen0); ! 565: ! 566: /* Add this CPU to the system CPU group */ ! 567: cpu_group_add(vm->cpu_group,gen0); ! 568: vm->boot_cpu = gen0; ! 569: ! 570: /* Initialize the IRQ routing vectors */ ! 571: vm->set_irq = mips64_vm_set_irq; ! 572: vm->clear_irq = mips64_vm_clear_irq; ! 573: ! 574: /* Mark the Network IO interrupt as high priority */ ! 575: cpu0->irq_idle_preempt[C6MSFC1_NETIO_IRQ] = TRUE; ! 576: cpu0->irq_idle_preempt[C6MSFC1_GT64K_IRQ] = TRUE; ! 577: ! 578: /* Copy some parameters from VM to CPU0 (idle PC, ...) */ ! 579: cpu0->idle_pc = vm->idle_pc; ! 580: ! 581: if (vm->timer_irq_check_itv) ! 582: cpu0->timer_irq_check_itv = vm->timer_irq_check_itv; ! 583: ! 584: /* ! 585: * On the MSFC1, bit 33 of physical addresses is used to bypass L2 cache. ! 586: * We clear it systematically. ! 587: */ ! 588: cpu0->addr_bus_mask = C6MSFC1_ADDR_BUS_MASK; ! 589: ! 590: /* Remote emulator control */ ! 591: dev_remote_control_init(vm,0x16000000,0x1000); ! 592: ! 593: /* Bootflash (8 Mb) */ ! 594: dev_bootflash_init(vm,"bootflash","c7200-bootflash-8mb", ! 595: C6MSFC1_BOOTFLASH_ADDR); ! 596: ! 597: /* NVRAM and calendar */ ! 598: dev_nvram_init(vm,"nvram",C6MSFC1_NVRAM_ADDR, ! 599: vm->nvram_size*1024,&vm->conf_reg); ! 600: ! 601: /* Bit-bucket zone */ ! 602: dev_zero_init(vm,"zero",C6MSFC1_BITBUCKET_ADDR,0xc00000); ! 603: ! 604: /* Initialize the NPE board */ ! 605: if (c6msfc1_init_hw(router) == -1) ! 606: return(-1); ! 607: ! 608: /* Initialize RAM */ ! 609: vm_ram_init(vm,0x00000000ULL); ! 610: ! 611: /* Initialize ROM */ ! 612: if (!vm->rom_filename) { ! 613: /* use embedded ROM */ ! 614: dev_rom_init(vm,"rom",C6MSFC1_ROM_ADDR,vm->rom_size*1048576, ! 615: mips64_microcode,mips64_microcode_len); ! 616: } else { ! 617: /* use alternate ROM */ ! 618: dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE, ! 619: C6MSFC1_ROM_ADDR,vm->rom_size*1048576); ! 620: } ! 621: ! 622: /* Byte swapping */ ! 623: dev_bswap_init(vm,"mem_bswap",C6MSFC1_BSWAP_ADDR,1024*1048576,0x00000000ULL); ! 624: ! 625: /* PCI IO space */ ! 626: if (!(vm->pci_io_space = pci_io_data_init(vm,C6MSFC1_PCI_IO_ADDR))) ! 627: return(-1); ! 628: ! 629: /* Initialize the Port Adapters */ ! 630: if (c6msfc1_init_platform_pa(router) == -1) ! 631: return(-1); ! 632: ! 633: /* Verify the check list */ ! 634: if (c6msfc1_checklist(router) == -1) ! 635: return(-1); ! 636: ! 637: /* Midplane FPGA */ ! 638: if (dev_c6msfc1_mpfpga_init(router,C6MSFC1_MPFPGA_ADDR,0x1000) == -1) ! 639: return(-1); ! 640: ! 641: if (!(obj = vm_object_find(router->vm,"mp_fpga"))) ! 642: return(-1); ! 643: ! 644: router->mpfpga_data = obj->data; ! 645: ! 646: /* IO FPGA */ ! 647: if (dev_c6msfc1_iofpga_init(router,C6MSFC1_IOFPGA_ADDR,0x1000) == -1) ! 648: return(-1); ! 649: ! 650: /* Show device list */ ! 651: c6msfc1_show_hardware(router); ! 652: return(0); ! 653: } ! 654: ! 655: /* Boot the IOS image */ ! 656: static int c6msfc1_boot_ios(c6msfc1_t *router) ! 657: { ! 658: vm_instance_t *vm = router->vm; ! 659: cpu_mips_t *cpu; ! 660: ! 661: if (!vm->boot_cpu) ! 662: return(-1); ! 663: ! 664: /* Suspend CPU activity since we will restart directly from ROM */ ! 665: vm_suspend(vm); ! 666: ! 667: /* Check that CPU activity is really suspended */ ! 668: if (cpu_group_sync_state(vm->cpu_group) == -1) { ! 669: vm_error(vm,"unable to sync with system CPUs.\n"); ! 670: return(-1); ! 671: } ! 672: ! 673: /* Reset the boot CPU */ ! 674: cpu = CPU_MIPS64(vm->boot_cpu); ! 675: mips64_reset(cpu); ! 676: ! 677: /* Load IOS image */ ! 678: if (mips64_load_elf_image(cpu,vm->ios_image, ! 679: (vm->ghost_status == VM_GHOST_RAM_USE), ! 680: &vm->ios_entry_point) < 0) ! 681: { ! 682: vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image); ! 683: return(-1); ! 684: } ! 685: ! 686: /* Launch the simulation */ ! 687: printf("\nC6MSFC1 '%s': starting simulation (CPU0 PC=0x%llx), " ! 688: "JIT %sabled.\n", ! 689: vm->name,cpu->pc,vm->jit_use ? "en":"dis"); ! 690: ! 691: vm_log(vm,"C6MSFC1_BOOT", ! 692: "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n", ! 693: cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off"); ! 694: ! 695: /* Start main CPU */ ! 696: if (vm->ghost_status != VM_GHOST_RAM_GENERATE) { ! 697: vm->status = VM_STATUS_RUNNING; ! 698: cpu_start(vm->boot_cpu); ! 699: } else { ! 700: vm->status = VM_STATUS_SHUTDOWN; ! 701: } ! 702: return(0); ! 703: } ! 704: ! 705: /* Set an IRQ */ ! 706: static void c6msfc1_set_irq(vm_instance_t *vm,u_int irq) ! 707: { ! 708: c6msfc1_t *router = VM_C6MSFC1(vm); ! 709: cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu); ! 710: u_int slot,port; ! 711: ! 712: switch(irq) { ! 713: case 0 ... 7: ! 714: mips64_set_irq(cpu0,irq); ! 715: ! 716: if (cpu0->irq_idle_preempt[irq]) ! 717: cpu_idle_break_wait(cpu0->gen); ! 718: break; ! 719: ! 720: case C6MSFC1_NETIO_IRQ_BASE ... C6MSFC1_NETIO_IRQ_END: ! 721: c6msfc1_net_irq_get_slot_port(irq,&slot,&port); ! 722: dev_c6msfc1_mpfpga_net_set_irq(router->mpfpga_data,slot,port); ! 723: break; ! 724: } ! 725: } ! 726: ! 727: /* Clear an IRQ */ ! 728: static void c6msfc1_clear_irq(vm_instance_t *vm,u_int irq) ! 729: { ! 730: c6msfc1_t *router = VM_C6MSFC1(vm); ! 731: cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu); ! 732: u_int slot,port; ! 733: ! 734: switch(irq) { ! 735: case 0 ... 7: ! 736: mips64_clear_irq(cpu0,irq); ! 737: break; ! 738: ! 739: case C6MSFC1_NETIO_IRQ_BASE ... C6MSFC1_NETIO_IRQ_END: ! 740: c6msfc1_net_irq_get_slot_port(irq,&slot,&port); ! 741: dev_c6msfc1_mpfpga_net_clear_irq(router->mpfpga_data,slot,port); ! 742: break; ! 743: } ! 744: } ! 745: ! 746: /* Initialize a MSFC1 instance */ ! 747: static int c6msfc1_init_instance(vm_instance_t *vm) ! 748: { ! 749: c6msfc1_t *router = VM_C6MSFC1(vm); ! 750: m_uint32_t rom_entry_point; ! 751: cpu_mips_t *cpu0; ! 752: ! 753: /* Initialize the MSFC1 platform */ ! 754: if (c6msfc1_init_platform(router) == -1) { ! 755: vm_error(vm,"unable to initialize the platform hardware.\n"); ! 756: return(-1); ! 757: } ! 758: ! 759: /* IRQ routing */ ! 760: vm->set_irq = c6msfc1_set_irq; ! 761: vm->clear_irq = c6msfc1_clear_irq; ! 762: ! 763: /* Load IOS configuration file */ ! 764: if (vm->ios_config != NULL) { ! 765: vm_nvram_push_config(vm,vm->ios_config); ! 766: vm->conf_reg &= ~0x40; ! 767: } ! 768: ! 769: /* Load ROM (ELF image or embedded) */ ! 770: cpu0 = CPU_MIPS64(vm->boot_cpu); ! 771: rom_entry_point = (m_uint32_t)MIPS_ROM_PC; ! 772: ! 773: if ((vm->rom_filename != NULL) && ! 774: (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0)) ! 775: { ! 776: vm_error(vm,"unable to load alternate ROM '%s', " ! 777: "fallback to embedded ROM.\n\n",vm->rom_filename); ! 778: vm->rom_filename = NULL; ! 779: } ! 780: ! 781: /* Load symbol file */ ! 782: if (vm->sym_filename) { ! 783: mips64_sym_load_file(cpu0,vm->sym_filename); ! 784: cpu0->sym_trace = 1; ! 785: } ! 786: ! 787: return(c6msfc1_boot_ios(router)); ! 788: } ! 789: ! 790: /* Stop a MSFC1 instance */ ! 791: static int c6msfc1_stop_instance(vm_instance_t *vm) ! 792: { ! 793: printf("\nC6MSFC1 '%s': stopping simulation.\n",vm->name); ! 794: vm_log(vm,"C6MSFC1_STOP","stopping simulation.\n"); ! 795: ! 796: /* Stop all CPUs */ ! 797: if (vm->cpu_group != NULL) { ! 798: vm_stop(vm); ! 799: ! 800: if (cpu_group_sync_state(vm->cpu_group) == -1) { ! 801: vm_error(vm,"unable to sync with system CPUs.\n"); ! 802: return(-1); ! 803: } ! 804: } ! 805: ! 806: /* Free resources that were used during execution to emulate hardware */ ! 807: vm_slot_shutdown_all(vm); ! 808: vm_hardware_shutdown(vm); ! 809: return(0); ! 810: } ! 811: ! 812: /* Get MAC address MSB */ ! 813: static u_int c6msfc1_get_mac_addr_msb(void) ! 814: { ! 815: return(0xC6); ! 816: } ! 817: ! 818: /* Show specific CLI options */ ! 819: static void c6msfc1_cli_show_options(vm_instance_t *vm) ! 820: { ! 821: printf(" -s <pa_nio> : Bind a Network IO interface to a " ! 822: "Port Adapter\n"); ! 823: } ! 824: ! 825: /* Platform definition */ ! 826: static vm_platform_t c6msfc1_platform = { ! 827: "c6msfc1", "C6MSFC1", "C6MSFC1", ! 828: c6msfc1_create_instance, ! 829: c6msfc1_delete_instance, ! 830: c6msfc1_init_instance, ! 831: c6msfc1_stop_instance, ! 832: c6msfc1_nvram_extract_config, ! 833: c6msfc1_nvram_push_config, ! 834: c6msfc1_get_mac_addr_msb, ! 835: NULL, ! 836: NULL, ! 837: c6msfc1_cli_show_options, ! 838: NULL, ! 839: }; ! 840: ! 841: /* Register the C6-MSFC1 platform */ ! 842: int c6msfc1_platform_register(void) ! 843: { ! 844: return(vm_platform_register(&c6msfc1_platform)); ! 845: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.