📄 dev_c3725.c
字号:
/* * Cisco router simulation platform. * Copyright (c) 2006 Christophe Fillot (cf@utc.fr) * * Generic Cisco 3725 routines and definitions (EEPROM,...). */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <assert.h>#include "cpu.h"#include "vm.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "pci_io.h"#include "dev_gt.h"#include "cisco_eeprom.h"#include "dev_rom.h"#include "dev_c3725.h"#include "dev_c3725_iofpga.h"#include "dev_vtty.h"#include "registry.h"/* ======================================================================== *//* EEPROM definitions *//* ======================================================================== *//* Cisco 3725 mainboard EEPROM */static m_uint16_t eeprom_c3725_mainboard_data[] = { 0x04FF, 0xC18B, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0x5809, 0x6140, 0x0259, 0xC046, 0x0320, 0x003F, 0x1302, 0x4244, 0x3085, 0x1C10, 0x8206, 0x80FF, 0xFFFF, 0xFFC4, 0x08FF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFF81, 0xFFFF, 0xFFFF, 0x03FF, 0x04FF, 0xC28B, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0x58C3, 0x0600, 0x1319, 0x5C6F, 0x7043, 0x0030, 0xC508, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x4100, 0x0101, 0x02FF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,};struct cisco_eeprom eeprom_c3725_mainboard = { "C3725 Backplane", eeprom_c3725_mainboard_data, sizeof(eeprom_c3725_mainboard_data)/2,};/* ======================================================================== *//* Network Module Drivers *//* ======================================================================== */static struct cisco_card_driver *nm_drivers[] = { &dev_c3725_nm_1fe_tx_driver, &dev_c3725_nm_16esw_driver, &dev_c3725_gt96100_fe_driver, &dev_c3725_nm_4t_driver, &dev_c3725_nm_nam_driver, &dev_c3725_nm_cids_driver, NULL,};/* ======================================================================== *//* Cisco 3725 router instances *//* ======================================================================== *//* Initialize default parameters for a C3725 */static void c3725_init_defaults(c3725_t *router);/* Directly extract the configuration from the NVRAM device */static ssize_t c3725_nvram_extract_config(vm_instance_t *vm,u_char **buffer){ u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr; m_uint32_t start,nvlen; m_uint16_t magic1,magic2; struct vdevice *nvram_dev; off_t nvram_size; int fd; if ((nvram_dev = dev_get_by_name(vm,"rom"))) dev_sync(nvram_dev); fd = vm_mmap_open_file(vm,"rom",&base_ptr,&nvram_size); if (fd == -1) return(-1); ios_ptr = base_ptr + C3725_NVRAM_OFFSET; end_ptr = base_ptr + nvram_size; if ((ios_ptr + 0x30) >= end_ptr) { vm_error(vm,"NVRAM file too small\n"); return(-1); } magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06)); magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08)); if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) { vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n", magic1,magic2); return(-1); } start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1; nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18)); if (!(*buffer = malloc(nvlen+1))) { vm_error(vm,"unable to allocate config buffer (%u bytes)\n",nvlen); return(-1); } cfg_ptr = ios_ptr + start + 0x08; if ((cfg_ptr + nvlen) > end_ptr) { vm_error(vm,"NVRAM file too small\n"); return(-1); } memcpy(*buffer,cfg_ptr,nvlen-1); (*buffer)[nvlen-1] = 0; return(nvlen-1);}static int c3725_nvram_push_config_part(vm_instance_t *vm, u_char *buffer,size_t len, u_char *ios_ptr){ m_uint32_t cfg_offset,cklen,tmp; m_uint16_t cksum; u_char *cfg_ptr; cfg_offset = 0x2c; cfg_ptr = ios_ptr + cfg_offset; /* Write IOS tag, uncompressed config... */ *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5); *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD); *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001); *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000); *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0c04); /* Store file contents to NVRAM */ memcpy(cfg_ptr,buffer,len); /* Write config addresses + size */ tmp = cfg_offset - 0x08; *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(tmp); *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(tmp + len); *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len); /* Compute the checksum */ cklen = C3725_NVRAM_SIZE - 0x08; cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen); *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum); return(0);}/* Directly push the IOS configuration to the NVRAM device */int c3725_nvram_push_config(vm_instance_t *vm,u_char *buffer,size_t len){ u_char *base_ptr,*ios_ptr; int fd; fd = vm_mmap_create_file(vm,"rom",vm->rom_size*1048576,&base_ptr); if (fd == -1) return(-1); ios_ptr = base_ptr + C3725_NVRAM_OFFSET; /* Normal config */ c3725_nvram_push_config_part(vm,buffer,len,ios_ptr); /* Backup config */ c3725_nvram_push_config_part(vm,buffer,len,ios_ptr + C3725_NVRAM_SIZE); vm_mmap_close_file(fd,base_ptr,vm->rom_size*1048576); return(0);}/* Check for empty config */static int c3725_nvram_check_empty_config(vm_instance_t *vm){ struct vdevice *rom_dev; m_uint64_t addr; size_t len; if (!(rom_dev = dev_get_by_name(vm,"rom"))) return(-1); addr = rom_dev->phys_addr + C3725_NVRAM_OFFSET; len = C3725_NVRAM_SIZE; while(len > 0) { if (physmem_copy_u32_from_vm(vm,addr) != 0) return(0); addr += sizeof(m_uint32_t); len -= sizeof(m_uint32_t); } /* Empty NVRAM */ vm->conf_reg |= 0x0040; printf("NVRAM is empty, setting config register to 0x%x\n",vm->conf_reg); return(0);}/* Create a new router instance */static int c3725_create_instance(vm_instance_t *vm){ c3725_t *router; if (!(router = malloc(sizeof(*router)))) { fprintf(stderr,"C3725 '%s': Unable to create new instance!\n",vm->name); return(-1); } memset(router,0,sizeof(*router)); router->vm = vm; vm->hw_data = router; c3725_init_defaults(router); return(0);}/* Free resources used by a router instance */static int c3725_delete_instance(vm_instance_t *vm){ c3725_t *router = VM_C3725(vm); int i; /* Stop all CPUs */ if (vm->cpu_group != NULL) { vm_stop(vm); if (cpu_group_sync_state(vm->cpu_group) == -1) { vm_error(vm,"unable to sync with system CPUs.\n"); return(FALSE); } } /* Remove NIO bindings */ for(i=0;i<vm->nr_slots;i++) vm_slot_remove_all_nio_bindings(vm,i); /* Shutdown all Network Modules */ vm_slot_shutdown_all(vm); /* Free mainboard EEPROM */ cisco_eeprom_free(&router->mb_eeprom); /* Free all resources used by VM */ vm_free(vm); /* Free the router structure */ free(router); return(TRUE);}/* Get WIC device address for the specified onboard port */int c3725_get_onboard_wic_addr(u_int slot,m_uint64_t *phys_addr){ if (slot >= C3725_MAX_WIC_BAYS) return(-1); *phys_addr = C3725_WIC_ADDR + (slot * C3725_WIC_SIZE); return(0);}/* Set EEPROM for the specified slot */int c3725_set_slot_eeprom(c3725_t *router,u_int slot, struct cisco_eeprom *eeprom){ if ((slot < 1) || (slot >= C3725_MAX_NM_BAYS)) return(-1); router->nm_eeprom_group[slot-1].eeprom[0] = eeprom; return(0);}/* Get slot/port corresponding to specified network IRQ */static inline void c3725_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port){ irq -= C3725_NETIO_IRQ_BASE; *port = irq & C3725_NETIO_IRQ_PORT_MASK; *slot = irq >> C3725_NETIO_IRQ_PORT_BITS;}/* Get network IRQ for specified slot/port */u_int c3725_net_irq_for_slot_port(u_int slot,u_int port){ u_int irq; irq = (slot << C3725_NETIO_IRQ_PORT_BITS) + port; irq += C3725_NETIO_IRQ_BASE; return(irq);}/* Get PCI device for the specified NM bay */int c3725_nm_get_pci_device(u_int nm_bay){ switch(nm_bay) { case 1: return(0x06); case 2: return(0x0A); default: return(-1); }}/* Set the base MAC address of the chassis */static int c3725_burn_mac_addr(c3725_t *router,n_eth_addr_t *addr){ m_uint8_t eeprom_ver; size_t offset; /* Read EEPROM format version */ cisco_eeprom_get_byte(&router->mb_eeprom,0,&eeprom_ver); switch(eeprom_ver) { case 0: cisco_eeprom_set_region(&router->mb_eeprom,2,addr->eth_addr_byte,6); break; case 4: if (!cisco_eeprom_v4_find_field(&router->mb_eeprom,0xC3,&offset)) { cisco_eeprom_set_region(&router->mb_eeprom,offset, addr->eth_addr_byte,6); } break; default: vm_error(router->vm,"c3725_burn_mac_addr: unable to handle " "EEPROM version %u\n",eeprom_ver); return(-1); } return(0);}/* Set chassis MAC address */int c3725_chassis_set_mac_addr(c3725_t *router,char *mac_addr){ if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) { vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr); return(-1); } /* Set the chassis base MAC address */ c3725_burn_mac_addr(router,&router->mac_addr); return(0);}/* Create the two main PCI busses for a GT64120 based system */static int c3725_init_gt96100(c3725_t *router){ vm_instance_t *vm = router->vm; vm_obj_t *obj; vm->pci_bus[0] = pci_bus_create("PCI bus #0",0); vm->pci_bus[1] = pci_bus_create("PCI bus #1",0); if (!vm->pci_bus[0] || !vm->pci_bus[1]) { vm_error(router->vm,"unable to create PCI data.\n"); return(-1); } if (dev_gt96100_init(vm,"gt96100",C3725_GT96K_ADDR,0x200000, C3725_GT96K_IRQ, C3725_EXT_IRQ, c3725_net_irq_for_slot_port(0,0), 255) == -1) return(-1); if (!(obj = vm_object_find(router->vm,"gt96100"))) return(-1); router->gt_data = obj->data; return(0);}/* Initialize a Cisco 3725 */static int c3725_init(c3725_t *router){ vm_instance_t *vm = router->vm; /* Set the processor type: R7000 */ mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R7000); /* Initialize the Galileo GT-96100 PCI controller */ if (c3725_init_gt96100(router) == -1) return(-1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -