Annotation of cf/dev_c6msfc1.c, revision 1.1.1.2

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: 
                    401:    /* Free all resources used by VM */
                    402:    vm_free(vm);
                    403: 
                    404:    /* Free the router structure */
                    405:    free(router);
                    406:    return(TRUE);
                    407: }
                    408: 
                    409: /* Create the main PCI bus for a GT64010 based system */
                    410: static int c6msfc1_init_gt64010(c6msfc1_t *router)
                    411: {   
                    412:    vm_instance_t *vm = router->vm;
                    413: 
                    414:    if (!(vm->pci_bus[0] = pci_bus_create("PCI Bus 0",0))) {
                    415:       vm_error(vm,"unable to create PCI data.\n");
                    416:       return(-1);
                    417:    }
                    418:    
                    419:    return(dev_gt64010_init(vm,"gt64010",C6MSFC1_GT64K_ADDR,0x1000,
                    420:                            C6MSFC1_GT64K_IRQ));
                    421: }
                    422: 
                    423: /* Initialize a MSFC1 board */
                    424: static int c6msfc1_init_hw(c6msfc1_t *router)
                    425: {
                    426:    vm_instance_t *vm = router->vm;
                    427: 
                    428:    /* Set the processor type: R5000 */
                    429:    mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R5000);
                    430: 
                    431:    /* Initialize the Galileo GT-64010 PCI controller */
                    432:    if (c6msfc1_init_gt64010(router) == -1)
                    433:       return(-1);
                    434: 
                    435:    /* Create PCI bus 1 */
                    436:    vm->pci_bus_pool[24] = pci_bus_create("PCI Bus 1",-1);
                    437:    dev_dec21154_init(vm->pci_bus[0],1,vm->pci_bus_pool[24]);
                    438: 
                    439:    /* Initialize SRAM (4Mb) */
                    440:    dev_c7200_sram_init(vm,"sram",C6MSFC1_SRAM_ADDR,C6MSFC1_SRAM_SIZE,
                    441:                        vm->pci_bus_pool[24],0);
                    442: 
                    443:    /* PCI IO space */
                    444:    if (!(vm->pci_io_space = pci_io_data_init(vm,C6MSFC1_PCI_IO_ADDR)))
                    445:       return(-1);
                    446: 
                    447:    /* Cirrus Logic PD6729 (PCI-to-PCMCIA host adapter) */
                    448:    dev_clpd6729_init(vm,vm->pci_bus[0],5,vm->pci_io_space,0x402,0x403);
                    449: 
                    450:    return(0);
                    451: }
                    452: 
                    453: /* Show MSFC1 hardware info */
                    454: void c6msfc1_show_hardware(c6msfc1_t *router)
                    455: {
                    456:    vm_instance_t *vm = router->vm;
                    457: 
                    458:    printf("C6MSFC1 instance '%s' (id %d):\n",vm->name,vm->instance_id);
                    459: 
                    460:    printf("  VM Status  : %d\n",vm->status);
                    461:    printf("  RAM size   : %u Mb\n",vm->ram_size);
                    462:    printf("  IOMEM size : %u Mb\n",vm->iomem_size);
                    463:    printf("  NVRAM size : %u Kb\n",vm->nvram_size);
                    464:    printf("  IOS image  : %s\n\n",vm->ios_image);
                    465: 
                    466:    if (vm->debug_level > 0) {
                    467:       dev_show_list(vm);
                    468:       pci_dev_show_list(vm->pci_bus[0]);
                    469:       pci_dev_show_list(vm->pci_bus[1]);
                    470:       printf("\n");
                    471:    }
                    472: }
                    473: 
                    474: /* Initialize default parameters for a MSFC1 */
                    475: static void c6msfc1_init_defaults(c6msfc1_t *router)
                    476: {
                    477:    vm_instance_t *vm = router->vm;
                    478:    n_eth_addr_t *m;
                    479:    m_uint16_t pid;
                    480: 
                    481:    /* Set platform slots characteristics */
                    482:    vm->nr_slots   = C6MSFC1_MAX_PA_BAYS;
                    483:    vm->slots_type = CISCO_CARD_TYPE_PA;
                    484:    vm->slots_drivers = pa_drivers;
                    485:       
                    486:    pid = (m_uint16_t)getpid();
                    487: 
                    488:    /* Generate a chassis MAC address based on the instance ID */
                    489:    m = &router->mac_addr;
                    490:    m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
                    491:    m->eth_addr_byte[1] = vm->instance_id & 0xFF;
                    492:    m->eth_addr_byte[2] = pid >> 8;
                    493:    m->eth_addr_byte[3] = pid & 0xFF;
                    494:    m->eth_addr_byte[4] = 0x00;
                    495:    m->eth_addr_byte[5] = 0x00;
                    496: 
                    497:    /* Default slot: 1 */
                    498:    router->msfc_slot = 1;
                    499: 
                    500:    c6msfc1_set_eeprom(router);
                    501:    c6msfc1_init_eeprom_groups(router);
                    502:    
                    503:    /* Create EOBC and IBC interfaces */
                    504:    vm_slot_add_binding(vm,"C6MSFC1_EOBC",0,0);
                    505:    vm_slot_add_binding(vm,"C6MSFC1_IBC",1,0);
                    506: 
                    507:    vm->ram_mmap        = C6MSFC1_DEFAULT_RAM_MMAP;
                    508:    vm->ram_size        = C6MSFC1_DEFAULT_RAM_SIZE;
                    509:    vm->rom_size        = C6MSFC1_DEFAULT_ROM_SIZE;
                    510:    vm->nvram_size      = C6MSFC1_DEFAULT_NVRAM_SIZE;
                    511:    vm->iomem_size      = 0;
                    512:    vm->conf_reg_setup  = C6MSFC1_DEFAULT_CONF_REG;
                    513:    vm->clock_divisor   = C6MSFC1_DEFAULT_CLOCK_DIV;
                    514:    vm->nvram_rom_space = C6MSFC1_NVRAM_ROM_RES_SIZE;
                    515: }
                    516: 
                    517: /* Run the checklist */
                    518: static int c6msfc1_checklist(c6msfc1_t *router)
                    519: {
                    520:    struct vm_instance *vm = router->vm;
                    521:    int res = 0;
                    522: 
                    523:    res += vm_object_check(vm,"ram");
                    524:    res += vm_object_check(vm,"rom");
                    525:    res += vm_object_check(vm,"nvram");
                    526:    res += vm_object_check(vm,"zero");
                    527: 
                    528:    if (res < 0)
                    529:       vm_error(vm,"incomplete initialization (no memory?)\n");
                    530: 
                    531:    return(res);
                    532: }
                    533: 
                    534: /* Initialize Port Adapters */
                    535: static int c6msfc1_init_platform_pa(c6msfc1_t *router)
                    536: {
                    537:    return(vm_slot_init_all(router->vm));
                    538: }
                    539: 
                    540: /* Initialize the MSFC1 Platform */
                    541: static int c6msfc1_init_platform(c6msfc1_t *router)
                    542: {
                    543:    struct vm_instance *vm = router->vm;
                    544:    cpu_mips_t *cpu0; 
                    545:    cpu_gen_t *gen0;
                    546:    vm_obj_t *obj;
                    547: 
                    548:    /* Copy config register setup into "active" config register */
                    549:    vm->conf_reg = vm->conf_reg_setup;
                    550: 
                    551:    /* Create Console and AUX ports */
                    552:    vm_init_vtty(vm);
                    553: 
                    554:    /* Create a CPU group */
                    555:    vm->cpu_group = cpu_group_create("System CPU");
                    556: 
                    557:    /* Initialize the virtual MIPS processor */
                    558:    if (!(gen0 = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
                    559:       vm_error(vm,"unable to create CPU0!\n");
                    560:       return(-1);
                    561:    }
                    562: 
                    563:    cpu0 = CPU_MIPS64(gen0);
                    564: 
                    565:    /* Add this CPU to the system CPU group */
                    566:    cpu_group_add(vm->cpu_group,gen0);
                    567:    vm->boot_cpu = gen0;
                    568: 
                    569:    /* Initialize the IRQ routing vectors */
                    570:    vm->set_irq = mips64_vm_set_irq;
                    571:    vm->clear_irq = mips64_vm_clear_irq;
                    572: 
                    573:    /* Mark the Network IO interrupt as high priority */
                    574:    cpu0->irq_idle_preempt[C6MSFC1_NETIO_IRQ] = TRUE;
                    575:    cpu0->irq_idle_preempt[C6MSFC1_GT64K_IRQ] = TRUE;
                    576: 
                    577:    /* Copy some parameters from VM to CPU0 (idle PC, ...) */
                    578:    cpu0->idle_pc = vm->idle_pc;
                    579: 
                    580:    if (vm->timer_irq_check_itv)
                    581:       cpu0->timer_irq_check_itv = vm->timer_irq_check_itv;
                    582: 
                    583:    /*
                    584:     * On the MSFC1, bit 33 of physical addresses is used to bypass L2 cache.
                    585:     * We clear it systematically.
                    586:     */
                    587:    cpu0->addr_bus_mask = C6MSFC1_ADDR_BUS_MASK;
                    588: 
                    589:    /* Remote emulator control */
                    590:    dev_remote_control_init(vm,0x16000000,0x1000);
                    591: 
                    592:    /* Bootflash (8 Mb) */
                    593:    dev_bootflash_init(vm,"bootflash","c7200-bootflash-8mb",
                    594:                       C6MSFC1_BOOTFLASH_ADDR);
                    595: 
                    596:    /* NVRAM and calendar */
                    597:    dev_nvram_init(vm,"nvram",C6MSFC1_NVRAM_ADDR,
                    598:                   vm->nvram_size*1024,&vm->conf_reg);
                    599: 
                    600:    /* Bit-bucket zone */
                    601:    dev_zero_init(vm,"zero",C6MSFC1_BITBUCKET_ADDR,0xc00000);
                    602: 
                    603:    /* Initialize the NPE board */
                    604:    if (c6msfc1_init_hw(router) == -1)
                    605:       return(-1);
                    606: 
                    607:    /* Initialize RAM */
                    608:    vm_ram_init(vm,0x00000000ULL);
                    609: 
                    610:    /* Initialize ROM */
                    611:    if (!vm->rom_filename) {
                    612:       /* use embedded ROM */
                    613:       dev_rom_init(vm,"rom",C6MSFC1_ROM_ADDR,vm->rom_size*1048576,
                    614:                    mips64_microcode,mips64_microcode_len);
                    615:    } else {
                    616:       /* use alternate ROM */
                    617:       dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE,
                    618:                    C6MSFC1_ROM_ADDR,vm->rom_size*1048576);
                    619:    }
                    620: 
                    621:    /* Byte swapping */
                    622:    dev_bswap_init(vm,"mem_bswap",C6MSFC1_BSWAP_ADDR,1024*1048576,0x00000000ULL);
                    623: 
                    624:    /* PCI IO space */
                    625:    if (!(vm->pci_io_space = pci_io_data_init(vm,C6MSFC1_PCI_IO_ADDR)))
                    626:       return(-1);
                    627: 
                    628:    /* Initialize the Port Adapters */
                    629:    if (c6msfc1_init_platform_pa(router) == -1)
                    630:       return(-1);
                    631: 
                    632:    /* Verify the check list */
                    633:    if (c6msfc1_checklist(router) == -1)
                    634:       return(-1);
                    635: 
                    636:    /* Midplane FPGA */
                    637:    if (dev_c6msfc1_mpfpga_init(router,C6MSFC1_MPFPGA_ADDR,0x1000) == -1)
                    638:       return(-1);
                    639: 
                    640:    if (!(obj = vm_object_find(router->vm,"mp_fpga")))
                    641:       return(-1);
                    642:    
                    643:    router->mpfpga_data = obj->data;
                    644:    
                    645:    /* IO FPGA */
                    646:    if (dev_c6msfc1_iofpga_init(router,C6MSFC1_IOFPGA_ADDR,0x1000) == -1)
                    647:       return(-1);
                    648: 
                    649:    /* Show device list */
                    650:    c6msfc1_show_hardware(router);
                    651:    return(0);
                    652: }
                    653: 
                    654: /* Boot the IOS image */
                    655: static int c6msfc1_boot_ios(c6msfc1_t *router)
                    656: {   
                    657:    vm_instance_t *vm = router->vm;
                    658:    cpu_mips_t *cpu;
                    659: 
                    660:    if (!vm->boot_cpu)
                    661:       return(-1);
                    662: 
                    663:    /* Suspend CPU activity since we will restart directly from ROM */
                    664:    vm_suspend(vm);
                    665: 
                    666:    /* Check that CPU activity is really suspended */
                    667:    if (cpu_group_sync_state(vm->cpu_group) == -1) {
                    668:       vm_error(vm,"unable to sync with system CPUs.\n");
                    669:       return(-1);
                    670:    }
                    671: 
                    672:    /* Reset the boot CPU */
                    673:    cpu = CPU_MIPS64(vm->boot_cpu);
                    674:    mips64_reset(cpu);
                    675: 
                    676:    /* Load IOS image */
                    677:    if (mips64_load_elf_image(cpu,vm->ios_image,
                    678:                              (vm->ghost_status == VM_GHOST_RAM_USE),
                    679:                              &vm->ios_entry_point) < 0)
                    680:    {
                    681:       vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
                    682:       return(-1);
                    683:    }
                    684: 
                    685:    /* Launch the simulation */
                    686:    printf("\nC6MSFC1 '%s': starting simulation (CPU0 PC=0x%llx), "
                    687:           "JIT %sabled.\n",
                    688:           vm->name,cpu->pc,vm->jit_use ? "en":"dis");
                    689: 
                    690:    vm_log(vm,"C6MSFC1_BOOT",
                    691:           "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
                    692:           cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
                    693:    
                    694:    /* Start main CPU */
                    695:    if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
                    696:       vm->status = VM_STATUS_RUNNING;
                    697:       cpu_start(vm->boot_cpu);
                    698:    } else {
                    699:       vm->status = VM_STATUS_SHUTDOWN;
                    700:    }
                    701:    return(0);
                    702: }
                    703: 
                    704: /* Set an IRQ */
                    705: static void c6msfc1_set_irq(vm_instance_t *vm,u_int irq)
                    706: {
                    707:    c6msfc1_t *router = VM_C6MSFC1(vm);
                    708:    cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
                    709:    u_int slot,port;
                    710:    
                    711:    switch(irq) {
                    712:       case 0 ... 7:
                    713:          mips64_set_irq(cpu0,irq);
                    714:          
                    715:          if (cpu0->irq_idle_preempt[irq])
                    716:             cpu_idle_break_wait(cpu0->gen);
                    717:          break;
                    718:          
                    719:       case C6MSFC1_NETIO_IRQ_BASE ... C6MSFC1_NETIO_IRQ_END:
                    720:          c6msfc1_net_irq_get_slot_port(irq,&slot,&port);
                    721:          dev_c6msfc1_mpfpga_net_set_irq(router->mpfpga_data,slot,port);
                    722:          break;
                    723:    }
                    724: }
                    725: 
                    726: /* Clear an IRQ */
                    727: static void c6msfc1_clear_irq(vm_instance_t *vm,u_int irq)
                    728: {
                    729:    c6msfc1_t *router = VM_C6MSFC1(vm);
                    730:    cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
                    731:    u_int slot,port;
                    732:    
                    733:    switch(irq) {
                    734:       case 0 ... 7:
                    735:          mips64_clear_irq(cpu0,irq);
                    736:          break;
                    737:          
                    738:       case C6MSFC1_NETIO_IRQ_BASE ... C6MSFC1_NETIO_IRQ_END:
                    739:          c6msfc1_net_irq_get_slot_port(irq,&slot,&port);
                    740:          dev_c6msfc1_mpfpga_net_clear_irq(router->mpfpga_data,slot,port);
                    741:          break;
                    742:    }
                    743: }
                    744: 
                    745: /* Initialize a MSFC1 instance */
                    746: static int c6msfc1_init_instance(vm_instance_t *vm)
                    747: {
                    748:    c6msfc1_t *router = VM_C6MSFC1(vm);
                    749:    m_uint32_t rom_entry_point;
                    750:    cpu_mips_t *cpu0;
                    751: 
                    752:    /* Initialize the MSFC1 platform */
                    753:    if (c6msfc1_init_platform(router) == -1) {
                    754:       vm_error(vm,"unable to initialize the platform hardware.\n");
                    755:       return(-1);
                    756:    }
                    757: 
                    758:    /* IRQ routing */
                    759:    vm->set_irq = c6msfc1_set_irq;
                    760:    vm->clear_irq = c6msfc1_clear_irq;   
                    761:    
                    762:    /* Load IOS configuration file */
                    763:    if (vm->ios_config != NULL) {
                    764:       vm_nvram_push_config(vm,vm->ios_config);
                    765:       vm->conf_reg &= ~0x40;
                    766:    }
                    767: 
                    768:    /* Load ROM (ELF image or embedded) */
                    769:    cpu0 = CPU_MIPS64(vm->boot_cpu);
                    770:    rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
                    771:    
                    772:    if ((vm->rom_filename != NULL) &&
                    773:        (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
                    774:    {
                    775:       vm_error(vm,"unable to load alternate ROM '%s', "
                    776:                "fallback to embedded ROM.\n\n",vm->rom_filename);
                    777:       vm->rom_filename = NULL;
                    778:    }
                    779: 
                    780:    /* Load symbol file */
                    781:    if (vm->sym_filename) {
                    782:       mips64_sym_load_file(cpu0,vm->sym_filename);
                    783:       cpu0->sym_trace = 1;
                    784:    }
                    785: 
                    786:    return(c6msfc1_boot_ios(router));
                    787: }
                    788: 
                    789: /* Stop a MSFC1 instance */
                    790: static int c6msfc1_stop_instance(vm_instance_t *vm)
                    791: {
                    792:    printf("\nC6MSFC1 '%s': stopping simulation.\n",vm->name);
                    793:    vm_log(vm,"C6MSFC1_STOP","stopping simulation.\n");
                    794: 
                    795:    /* Stop all CPUs */
                    796:    if (vm->cpu_group != NULL) {
                    797:       vm_stop(vm);
                    798:       
                    799:       if (cpu_group_sync_state(vm->cpu_group) == -1) {
                    800:          vm_error(vm,"unable to sync with system CPUs.\n");
                    801:          return(-1);
                    802:       }
                    803:    }
                    804: 
                    805:    /* Free resources that were used during execution to emulate hardware */
                    806:    vm_slot_shutdown_all(vm);
                    807:    vm_hardware_shutdown(vm);
                    808:    return(0);
                    809: }
                    810: 
                    811: /* Get MAC address MSB */
                    812: static u_int c6msfc1_get_mac_addr_msb(void)
                    813: {
                    814:    return(0xC6);
                    815: }
                    816: 
                    817: /* Show specific CLI options */
                    818: static void c6msfc1_cli_show_options(vm_instance_t *vm)
                    819: {
                    820:    printf("  -s <pa_nio>        : Bind a Network IO interface to a "
                    821:           "Port Adapter\n");
                    822: }
                    823: 
                    824: /* Platform definition */
                    825: static vm_platform_t c6msfc1_platform = {
                    826:    "c6msfc1", "C6MSFC1", "C6MSFC1",
                    827:    c6msfc1_create_instance,
                    828:    c6msfc1_delete_instance,
                    829:    c6msfc1_init_instance,
                    830:    c6msfc1_stop_instance,
1.1.1.2 ! root      831:    NULL,
        !           832:    NULL,
1.1       root      833:    c6msfc1_nvram_extract_config,
                    834:    c6msfc1_nvram_push_config,
                    835:    c6msfc1_get_mac_addr_msb,
                    836:    NULL,
                    837:    NULL,
                    838:    c6msfc1_cli_show_options,
                    839:    NULL,
                    840: };
                    841: 
                    842: /* Register the C6-MSFC1 platform */
                    843: int c6msfc1_platform_register(void)
                    844: {
                    845:    return(vm_platform_register(&c6msfc1_platform));
                    846: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.