📄 dev_c1700.c
字号:
/* * Cisco router simulation platform. * Copyright (c) 2006 Christophe Fillot (cf@utc.fr) * * Generic Cisco 1700 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 "ppc32_mem.h"#include "pci_io.h"#include "cisco_eeprom.h"#include "dev_mpc860.h"#include "dev_rom.h"#include "dev_c1700.h"#include "dev_c1700_iofpga.h"#include "dev_vtty.h"#include "registry.h"/* ======================================================================== *//* EEPROM definitions *//* ======================================================================== *//* Cisco 1700 mainboard EEPROM */static m_uint16_t eeprom_c1700_mb_data[] = { 0x0101, 0x0404, 0x0000, 0x0000, 0x4320, 0x00FF, 0x00B2, 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x3030, 0x3000, 0x0030, 0x3030, 0x3002, 0x0200, 0x0000, 0x0000, 0x00FF, 0xFFFF, 0x5006, 0x490B, 0x1709, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,};struct c1700_mb_id { char *name; char *mb_driver; m_uint16_t id; int supported;};struct c1700_mb_id c1700_mainboard_id[] = { { "1710" , "C1710-MB-1FE-1E" , 0x02F6, TRUE }, { "1720" , "C1700-MB-1ETH" , 0x00B2, TRUE }, { "1721" , "C1700-MB-1ETH" , 0x035A, TRUE }, { "1750" , "C1700-MB-1ETH" , 0x00C9, TRUE }, { "1751" , "C1700-MB-1ETH" , 0x024D, TRUE }, { "1760" , "C1700-MB-1ETH" , 0x0316, TRUE }, { NULL , NULL , 0x0000, 0 },};/* ======================================================================== *//* Network Module Drivers *//* ======================================================================== */static struct cisco_card_driver *nm_drivers[] = { &dev_c1700_mb_eth_driver, &dev_c1710_mb_eth_driver, NULL,};/* ======================================================================== *//* Cisco 1700 router instances *//* ======================================================================== *//* Initialize default parameters for a C1700 */static void c1700_init_defaults(c1700_t *router);/* Directly extract the configuration from the NVRAM device */static ssize_t c1700_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,"nvram"))) dev_sync(nvram_dev); fd = vm_mmap_open_file(vm,"nvram",&base_ptr,&nvram_size); if (fd == -1) return(-1); ios_ptr = base_ptr + vm->nvram_rom_space; 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);}/* Directly push the IOS configuration to the NVRAM device */static int c1700_nvram_push_config(vm_instance_t *vm,u_char *buffer,size_t len){ u_char *base_ptr,*ios_ptr,*cfg_ptr; m_uint32_t cfg_offset,cklen,tmp; m_uint16_t cksum; int fd; fd = vm_mmap_create_file(vm,"nvram",vm->nvram_size*1024,&base_ptr); if (fd == -1) return(-1); cfg_offset = 0x2c; ios_ptr = base_ptr + vm->nvram_rom_space; 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 = (vm->nvram_size*1024) - (vm->nvram_rom_space + 0x08); cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen); *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum); vm_mmap_close_file(fd,base_ptr,vm->nvram_size*1024); return(0);}/* Create a new router instance */static int c1700_create_instance(vm_instance_t *vm){ c1700_t *router; if (!(router = malloc(sizeof(*router)))) { fprintf(stderr,"C1700 '%s': Unable to create new instance!\n",vm->name); return(-1); } memset(router,0,sizeof(*router)); router->vm = vm; vm->hw_data = router; c1700_init_defaults(router); return(0);}/* Free resources used by a router instance */static int c1700_delete_instance(vm_instance_t *vm){ c1700_t *router = VM_C1700(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);}/* Save configuration of a C1700 instance */void c1700_save_config(vm_instance_t *vm,FILE *fd){ c1700_t *router = VM_C1700(vm); fprintf(fd,"c1700 set_chassis %s %s\n\n",vm->name,router->mainboard_type);}/* Get WIC device address for the specified onboard port */int c1700_get_onboard_wic_addr(u_int slot,m_uint64_t *phys_addr){ if (slot >= C1700_MAX_WIC_BAYS) return(-1); *phys_addr = C1700_WIC_ADDR + (slot * C1700_WIC_SIZE); return(0);}/* Set EEPROM for the specified slot */int c1700_set_slot_eeprom(c1700_t *router,u_int slot, struct cisco_eeprom *eeprom){ switch(slot) { case 1: router->nm_eeprom_group.eeprom[0] = eeprom; return(0); default: return(-1); }}/* Get slot/port corresponding to specified network IRQ */static inline void c1700_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port){ irq -= C1700_NETIO_IRQ_BASE; *port = irq & C1700_NETIO_IRQ_PORT_MASK; *slot = irq >> C1700_NETIO_IRQ_PORT_BITS;}/* Get network IRQ for specified slot/port */u_int c1700_net_irq_for_slot_port(u_int slot,u_int port){ u_int irq; irq = (slot << C1700_NETIO_IRQ_PORT_BITS) + port; irq += C1700_NETIO_IRQ_BASE; return(irq);}/* Find Cisco 1700 Mainboard info */static struct c1700_mb_id *c1700_get_mb_info(char *mainboard_type){ int i; for(i=0;c1700_mainboard_id[i].name;i++) if (!strcmp(c1700_mainboard_id[i].name,mainboard_type)) return(&c1700_mainboard_id[i]); return NULL;}/* Show all available mainboards */static void c1700_mainboard_show_drivers(void){ int i; printf("Available C1700 chassis drivers:\n"); for(i=0;c1700_mainboard_id[i].name;i++) printf(" * %s %s\n", c1700_mainboard_id[i].name, !c1700_mainboard_id[i].supported ? "(NOT WORKING)" : ""); printf("\n");}/* Set the base MAC address of the chassis */static int c1700_burn_mac_addr(c1700_t *router,n_eth_addr_t *addr){ int i; for(i=0;i<3;i++) { router->vm->chassis_cookie[i+1] = addr->eth_addr_byte[i*2] << 8; router->vm->chassis_cookie[i+1] |= addr->eth_addr_byte[(i*2)+1]; } return(0);}/* Set mainboard type */int c1700_mainboard_set_type(c1700_t *router,char *mainboard_type){ struct c1700_mb_id *mb_info; if (router->vm->status == VM_STATUS_RUNNING) { vm_error(router->vm,"unable to change mainboard type when online.\n"); return(-1); } if (!(mb_info = c1700_get_mb_info(mainboard_type))) { vm_error(router->vm,"unknown mainboard '%s'\n",mainboard_type); return(-1); } router->mainboard_type = mainboard_type; /* Set the cookie */ memcpy(router->vm->chassis_cookie, eeprom_c1700_mb_data,sizeof(eeprom_c1700_mb_data)); router->vm->chassis_cookie[6] = mb_info->id; /* Set the chassis base MAC address */ c1700_burn_mac_addr(router,&router->mac_addr); /* Set the mainboard driver */ if (vm_slot_active(router->vm,0,0)) vm_slot_remove_binding(router->vm,0,0); vm_slot_add_binding(router->vm,mb_info->mb_driver,0,0); return(0);}/* Set chassis MAC address */int c1700_chassis_set_mac_addr(c1700_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 */ c1700_burn_mac_addr(router,&router->mac_addr); return(0);}/* Initialize a Cisco 1700 */static int c1700_init(c1700_t *router){ vm_instance_t *vm = router->vm; /* Create the PCI bus */ if (!(vm->pci_bus[0] = pci_bus_create("PCI0",0))) { vm_error(vm,"unable to create PCI data.\n"); return(-1); } /* Bind PCI bus to slots 0 and 1 */ vm->slots_pci_bus[0] = vm->pci_bus[0]; vm->slots_pci_bus[1] = vm->pci_bus[0]; vm->elf_machine_id = C1700_ELF_MACHINE_ID; return(0);}/* Show C1700 hardware info */void c1700_show_hardware(c1700_t *router){ vm_instance_t *vm = router->vm; printf("C1700 instance '%s' (id %d):\n",vm->name,vm->instance_id); printf(" VM Status : %d\n",vm->status); printf(" RAM size : %u Mb\n",vm->ram_size); printf(" NVRAM size : %u Kb\n",vm->nvram_size); printf(" IOS image : %s\n\n",vm->ios_image); if (vm->debug_level > 0) { dev_show_list(vm); pci_dev_show_list(vm->pci_bus[0]); pci_dev_show_list(vm->pci_bus[1]); printf("\n"); }}/* Initialize default parameters for a C1700 */static void c1700_init_defaults(c1700_t *router){ vm_instance_t *vm = router->vm; n_eth_addr_t *m; m_uint16_t pid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -