Annotation of cf/dev_c6msfc1.c, revision 1.1

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: }

unix.superglobalmegacorp.com

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