--- upstream/dynamips-0.2.7/dev_c3725.c 2007/10/06 16:29:14 10 +++ upstream/dynamips-0.2.8-RC1/dev_c3725.c 2007/10/06 16:33:40 11 @@ -51,11 +51,13 @@ /* ======================================================================== */ /* Network Module Drivers */ /* ======================================================================== */ -static struct c3725_nm_driver *nm_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, }; @@ -63,8 +65,11 @@ /* 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 */ -ssize_t c3725_nvram_extract_config(vm_instance_t *vm,char **buffer) +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; @@ -119,7 +124,7 @@ } static int c3725_nvram_push_config_part(vm_instance_t *vm, - char *buffer,size_t len, + u_char *buffer,size_t len, u_char *ios_ptr) { m_uint32_t cfg_offset,cklen,tmp; @@ -154,7 +159,7 @@ } /* Directly push the IOS configuration to the NVRAM device */ -int c3725_nvram_push_config(vm_instance_t *vm,char *buffer,size_t len) +int c3725_nvram_push_config(vm_instance_t *vm,u_char *buffer,size_t len) { u_char *base_ptr,*ios_ptr; int fd; @@ -177,7 +182,7 @@ } /* Check for empty config */ -int c3725_nvram_check_empty_config(vm_instance_t *vm) +static int c3725_nvram_check_empty_config(vm_instance_t *vm) { struct vdevice *rom_dev; m_uint64_t addr; @@ -204,131 +209,76 @@ } /* Create a new router instance */ -c3725_t *c3725_create_instance(char *name,int instance_id) +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",name); - return NULL; + fprintf(stderr,"C3725 '%s': Unable to create new instance!\n",vm->name); + return(-1); } memset(router,0,sizeof(*router)); - - if (!(router->vm = vm_create(name,instance_id,VM_TYPE_C3725))) { - fprintf(stderr,"C3725 '%s': unable to create VM instance!\n",name); - goto err_vm; - } + router->vm = vm; + vm->hw_data = router; c3725_init_defaults(router); - router->vm->hw_data = router; - return router; - - err_vm: - free(router); - return NULL; + return(0); } /* Free resources used by a router instance */ -static int c3725_free_instance(void *data,void *arg) +static int c3725_delete_instance(vm_instance_t *vm) { - vm_instance_t *vm = data; - c3725_t *router; + c3725_t *router = VM_C3725(vm); int i; - if (vm->type == VM_TYPE_C3725) { - router = VM_C3725(vm); - - /* Stop all CPUs */ - if (vm->cpu_group != NULL) { - vm_stop(vm); + /* 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); - } + 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;imb_eeprom); - - /* Free all resources used by VM */ - vm_free(vm); - - /* Free the router structure */ - free(router); - return(TRUE); } - return(FALSE); -} + /* Remove NIO bindings */ + for(i=0;inr_slots;i++) + vm_slot_remove_all_nio_bindings(vm,i); -/* Delete a router instance */ -int c3725_delete_instance(char *name) -{ - return(registry_delete_if_unused(name,OBJ_TYPE_VM, - c3725_free_instance,NULL)); -} - -/* Delete all router instances */ -int c3725_delete_all_instances(void) -{ - return(registry_delete_type(OBJ_TYPE_VM,c3725_free_instance,NULL)); -} - -/* Save configuration of a C3725 instance */ -void c3725_save_config(c3725_t *router,FILE *fd) -{ - vm_instance_t *vm = router->vm; - struct c3725_nio_binding *nb; - struct c3725_nm_bay *bay; - int i; - - /* General settings */ - fprintf(fd,"c3725 create %s %u\n",vm->name,vm->instance_id); + /* Shutdown all Network Modules */ + vm_slot_shutdown_all(vm); - /* VM configuration */ - vm_save_config(vm,fd); + /* Free mainboard EEPROM */ + cisco_eeprom_free(&router->mb_eeprom); - /* Network Module settings */ - for(i=0;idev_type) { - fprintf(fd,"c3725 add_nm_binding %s %u %s\n", - vm->name,i,bay->dev_type); - } + /* Free all resources used by VM */ + vm_free(vm); - for(nb=bay->nio_list;nb;nb=nb->next) { - fprintf(fd,"c3725 add_nio_binding %s %u %u %s\n", - vm->name,i,nb->port_id,nb->nio->name); - } - } - - fprintf(fd,"\n"); + /* Free the router structure */ + free(router); + return(TRUE); } -/* Save configurations of all C3725 instances */ -static void c3725_reg_save_config(registry_entry_t *entry,void *opt,int *err) +/* Get WIC device address for the specified onboard port */ +int c3725_get_onboard_wic_addr(u_int slot,m_uint64_t *phys_addr) { - vm_instance_t *vm = entry->data; - c3725_t *router = VM_C3725(vm); + if (slot >= C3725_MAX_WIC_BAYS) + return(-1); - if (vm->type == VM_TYPE_C3725) - c3725_save_config(router,(FILE *)opt); + *phys_addr = C3725_WIC_ADDR + (slot * C3725_WIC_SIZE); + return(0); } -void c3725_save_config_all(FILE *fd) +/* Set EEPROM for the specified slot */ +int c3725_set_slot_eeprom(c3725_t *router,u_int slot, + struct cisco_eeprom *eeprom) { - registry_foreach_type(OBJ_TYPE_VM,c3725_reg_save_config,fd,NULL); + 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 */ @@ -364,628 +314,6 @@ } } -/* Set NM EEPROM definition */ -int c3725_nm_set_eeprom(c3725_t *router,u_int nm_bay, - const struct cisco_eeprom *eeprom) -{ - if (!nm_bay || (nm_bay >= C3725_MAX_NM_BAYS)) { - vm_error(router->vm,"c3725_nm_set_eeprom: invalid NM Bay %u.\n",nm_bay); - return(-1); - } - - if (cisco_eeprom_copy(&router->nm_bay[nm_bay].eeprom,eeprom) == -1) { - vm_error(router->vm,"c3725_nm_set_eeprom: no memory.\n"); - return(-1); - } - - return(0); -} - -/* Unset NM EEPROM definition (empty bay) */ -int c3725_nm_unset_eeprom(c3725_t *router,u_int nm_bay) -{ - if (!nm_bay || (nm_bay >= C3725_MAX_NM_BAYS)) { - vm_error(router->vm,"c3725_nm_set_eeprom: invalid NM Bay %u.\n",nm_bay); - return(-1); - } - - cisco_eeprom_free(&router->nm_bay[nm_bay].eeprom); - return(0); -} - -/* Check if a bay has a port adapter */ -int c3725_nm_check_eeprom(c3725_t *router,u_int nm_bay) -{ - if (!nm_bay || (nm_bay >= C3725_MAX_NM_BAYS)) - return(FALSE); - - return(cisco_eeprom_valid(&router->nm_bay[nm_bay].eeprom)); -} - -/* Get bay info */ -struct c3725_nm_bay *c3725_nm_get_info(c3725_t *router,u_int nm_bay) -{ - if (nm_bay >= C3725_MAX_NM_BAYS) - return NULL; - - return(&router->nm_bay[nm_bay]); -} - -/* Get NM type */ -char *c3725_nm_get_type(c3725_t *router,u_int nm_bay) -{ - struct c3725_nm_bay *bay; - - bay = c3725_nm_get_info(router,nm_bay); - return((bay != NULL) ? bay->dev_type : NULL); -} - -/* Get driver info about the specified slot */ -void *c3725_nm_get_drvinfo(c3725_t *router,u_int nm_bay) -{ - struct c3725_nm_bay *bay; - - bay = c3725_nm_get_info(router,nm_bay); - return((bay != NULL) ? bay->drv_info : NULL); -} - -/* Set driver info for the specified slot */ -int c3725_nm_set_drvinfo(c3725_t *router,u_int nm_bay,void *drv_info) -{ - struct c3725_nm_bay *bay; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return(-1); - - bay->drv_info = drv_info; - return(0); -} - -/* Get a NM driver */ -static struct c3725_nm_driver *c3725_nm_get_driver(char *dev_type) -{ - int i; - - for(i=0;nm_drivers[i];i++) - if (!strcmp(nm_drivers[i]->dev_type,dev_type)) - return nm_drivers[i]; - - return NULL; -} - -/* Add a NM binding */ -int c3725_nm_add_binding(c3725_t *router,char *dev_type,u_int nm_bay) -{ - struct c3725_nm_driver *nm_driver; - struct c3725_nm_bay *bay; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return(-1); - - /* check that this bay is empty */ - if (bay->dev_type != NULL) { - vm_error(router->vm,"a NM already exists in slot %u.\n",nm_bay); - return(-1); - } - - /* find the NM driver */ - if (!(nm_driver = c3725_nm_get_driver(dev_type))) { - vm_error(router->vm,"unknown NM type '%s'.\n",dev_type); - return(-1); - } - - bay->dev_type = nm_driver->dev_type; - bay->nm_driver = nm_driver; - return(0); -} - -/* Remove a NM binding */ -int c3725_nm_remove_binding(c3725_t *router,u_int nm_bay) -{ - struct c3725_nm_bay *bay; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return(-1); - - /* stop if this bay is still active */ - if (bay->drv_info != NULL) { - vm_error(router->vm,"slot %u still active.\n",nm_bay); - return(-1); - } - - /* check that this bay is not empty */ - if (bay->dev_type == NULL) { - vm_error(router->vm,"slot %u is empty.\n",nm_bay); - return(-1); - } - - /* remove all NIOs bindings */ - c3725_nm_remove_all_nio_bindings(router,nm_bay); - - bay->dev_type = NULL; - bay->nm_driver = NULL; - return(0); -} - -/* Find a NIO binding */ -struct c3725_nio_binding * -c3725_nm_find_nio_binding(c3725_t *router,u_int nm_bay,u_int port_id) -{ - struct c3725_nio_binding *nb; - struct c3725_nm_bay *bay; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return NULL; - - for(nb=bay->nio_list;nb;nb=nb->next) - if (nb->port_id == port_id) - return nb; - - return NULL; -} - -/* Add a network IO binding */ -int c3725_nm_add_nio_binding(c3725_t *router,u_int nm_bay,u_int port_id, - char *nio_name) -{ - struct c3725_nio_binding *nb; - struct c3725_nm_bay *bay; - netio_desc_t *nio; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return(-1); - - /* check that a NIO is not already bound to this port */ - if (c3725_nm_find_nio_binding(router,nm_bay,port_id) != NULL) { - vm_error(router->vm,"a NIO already exists for interface %u/%u.\n", - nm_bay,port_id); - return(-1); - } - - /* acquire a reference on the NIO object */ - if (!(nio = netio_acquire(nio_name))) { - vm_error(router->vm,"unable to find NIO '%s'.\n",nio_name); - return(-1); - } - - /* create a new binding */ - if (!(nb = malloc(sizeof(*nb)))) { - vm_error(router->vm,"unable to create NIO binding " - "for interface %u/%u.\n",nm_bay,port_id); - netio_release(nio_name); - return(-1); - } - - memset(nb,0,sizeof(*nb)); - nb->nio = nio; - nb->port_id = port_id; - nb->next = bay->nio_list; - if (nb->next) nb->next->prev = nb; - bay->nio_list = nb; - return(0); -} - -/* Remove a NIO binding */ -int c3725_nm_remove_nio_binding(c3725_t *router,u_int nm_bay,u_int port_id) -{ - struct c3725_nio_binding *nb; - struct c3725_nm_bay *bay; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return(-1); - - if (!(nb = c3725_nm_find_nio_binding(router,nm_bay,port_id))) - return(-1); /* no nio binding for this slot/port */ - - /* tell the NM driver to stop using this NIO */ - if (bay->nm_driver) - bay->nm_driver->nm_unset_nio(router,nm_bay,port_id); - - /* remove this entry from the double linked list */ - if (nb->next) - nb->next->prev = nb->prev; - - if (nb->prev) { - nb->prev->next = nb->next; - } else { - bay->nio_list = nb->next; - } - - /* unreference NIO object */ - netio_release(nb->nio->name); - free(nb); - return(0); -} - -/* Remove all NIO bindings for the specified NM */ -int c3725_nm_remove_all_nio_bindings(c3725_t *router,u_int nm_bay) -{ - struct c3725_nio_binding *nb,*next; - struct c3725_nm_bay *bay; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return(-1); - - for(nb=bay->nio_list;nb;nb=next) { - next = nb->next; - - /* tell the NM driver to stop using this NIO */ - if (bay->nm_driver) - bay->nm_driver->nm_unset_nio(router,nm_bay,nb->port_id); - - /* unreference NIO object */ - netio_release(nb->nio->name); - free(nb); - } - - bay->nio_list = NULL; - return(0); -} - -/* Enable a Network IO descriptor for a Network Module */ -int c3725_nm_enable_nio(c3725_t *router,u_int nm_bay,u_int port_id) -{ - struct c3725_nio_binding *nb; - struct c3725_nm_bay *bay; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return(-1); - - /* check that we have an NIO binding for this interface */ - if (!(nb = c3725_nm_find_nio_binding(router,nm_bay,port_id))) - return(-1); - - /* check that the driver is defined and successfully initialized */ - if (!bay->nm_driver || !bay->drv_info) - return(-1); - - return(bay->nm_driver->nm_set_nio(router,nm_bay,port_id,nb->nio)); -} - -/* Disable Network IO descriptor of a Network Module */ -int c3725_nm_disable_nio(c3725_t *router,u_int nm_bay,u_int port_id) -{ - struct c3725_nm_bay *bay; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return(-1); - - /* check that the driver is defined and successfully initialized */ - if (!bay->nm_driver || !bay->drv_info) - return(-1); - - return(bay->nm_driver->nm_unset_nio(router,nm_bay,port_id)); -} - -/* Enable all NIO of the specified NM */ -int c3725_nm_enable_all_nio(c3725_t *router,u_int nm_bay) -{ - struct c3725_nio_binding *nb; - struct c3725_nm_bay *bay; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return(-1); - - /* check that the driver is defined and successfully initialized */ - if (!bay->nm_driver || !bay->drv_info) - return(-1); - - for(nb=bay->nio_list;nb;nb=nb->next) - bay->nm_driver->nm_set_nio(router,nm_bay,nb->port_id,nb->nio); - - return(0); -} - -/* Disable all NIO of the specified NM */ -int c3725_nm_disable_all_nio(c3725_t *router,u_int nm_bay) -{ - struct c3725_nio_binding *nb; - struct c3725_nm_bay *bay; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return(-1); - - /* check that the driver is defined and successfully initialized */ - if (!bay->nm_driver || !bay->drv_info) - return(-1); - - for(nb=bay->nio_list;nb;nb=nb->next) - bay->nm_driver->nm_unset_nio(router,nm_bay,nb->port_id); - - return(0); -} - -/* Initialize a Network Module */ -int c3725_nm_init(c3725_t *router,u_int nm_bay) -{ - struct c3725_nm_bay *bay; - size_t len; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return(-1); - - /* Check that a device type is defined for this bay */ - if (!bay->dev_type || !bay->nm_driver) { - vm_error(router->vm,"trying to init empty slot %u.\n",nm_bay); - return(-1); - } - - /* Allocate device name */ - len = strlen(bay->dev_type) + 10; - if (!(bay->dev_name = malloc(len))) { - vm_error(router->vm,"unable to allocate device name.\n"); - return(-1); - } - - snprintf(bay->dev_name,len,"%s(%u)",bay->dev_type,nm_bay); - - /* Initialize NM driver */ - if (bay->nm_driver->nm_init(router,bay->dev_name,nm_bay) == -1) { - vm_error(router->vm,"unable to initialize NM %u.\n",nm_bay); - return(-1); - } - - /* Enable all NIO */ - c3725_nm_enable_all_nio(router,nm_bay); - return(0); -} - -/* Shutdown a Network Module */ -int c3725_nm_shutdown(c3725_t *router,u_int nm_bay) -{ - struct c3725_nm_bay *bay; - - if (!(bay = c3725_nm_get_info(router,nm_bay))) - return(-1); - - /* Check that a device type is defined for this bay */ - if (!bay->dev_type || !bay->nm_driver) { - vm_error(router->vm,"trying to shut down empty slot %u.\n",nm_bay); - return(-1); - } - - /* Disable all NIO */ - c3725_nm_disable_all_nio(router,nm_bay); - - /* Shutdown the NM driver */ - if (bay->drv_info && (bay->nm_driver->nm_shutdown(router,nm_bay) == -1)) { - vm_error(router->vm,"unable to shutdown NM %u.\n",nm_bay); - return(-1); - } - - free(bay->dev_name); - bay->dev_name = NULL; - bay->drv_info = NULL; - return(0); -} - -/* Shutdown all NM of a router */ -int c3725_nm_shutdown_all(c3725_t *router) -{ - int i; - - for(i=0;inm_bay[i].dev_type) - continue; - - c3725_nm_shutdown(router,i); - } - - return(0); -} - -/* Show info about all NMs */ -int c3725_nm_show_all_info(c3725_t *router) -{ - struct c3725_nm_bay *bay; - int i; - - for(i=0;inm_driver) - continue; - - if (bay->nm_driver->nm_show_info != NULL) - bay->nm_driver->nm_show_info(router,i); - } - - return(0); -} - -/* Maximum number of tokens in a NM description */ -#define NM_DESC_MAX_TOKENS 8 - -/* Create a Network Module (command line) */ -int c3725_cmd_nm_create(c3725_t *router,char *str) -{ - char *tokens[NM_DESC_MAX_TOKENS]; - int i,count,res; - u_int nm_bay; - - /* A port adapter description is like "1:NM-1FE" */ - if ((count = m_strsplit(str,':',tokens,NM_DESC_MAX_TOKENS)) != 2) { - vm_error(router->vm,"unable to parse NM description '%s'.\n",str); - return(-1); - } - - /* Parse the NM bay id */ - nm_bay = atoi(tokens[0]); - - /* Add this new NM to the current NM list */ - res = c3725_nm_add_binding(router,tokens[1],nm_bay); - - /* The complete array was cleaned by strsplit */ - for(i=0;ivm,"unable to parse NIO description '%s'.\n",str); - return(-1); - } - - /* Parse the NM bay */ - nm_bay = atoi(tokens[0]); - - /* Parse the NM port id */ - port_id = atoi(tokens[1]); - - /* Autogenerate a NIO name */ - snprintf(nio_name,sizeof(nio_name),"c3725-i%u/%u/%u", - router->vm->instance_id,nm_bay,port_id); - - /* Create the Network IO descriptor */ - nio = NULL; - nio_type = netio_get_type(tokens[2]); - - switch(nio_type) { - case NETIO_TYPE_UNIX: - if (count != 5) { - vm_error(router->vm, - "invalid number of arguments for UNIX NIO '%s'\n",str); - goto done; - } - - nio = netio_desc_create_unix(nio_name,tokens[3],tokens[4]); - break; - - case NETIO_TYPE_VDE: - if (count != 5) { - vm_error(router->vm, - "invalid number of arguments for VDE NIO '%s'\n",str); - goto done; - } - - nio = netio_desc_create_vde(nio_name,tokens[3],tokens[4]); - break; - - case NETIO_TYPE_TAP: - if (count != 4) { - vm_error(router->vm, - "invalid number of arguments for TAP NIO '%s'\n",str); - goto done; - } - - nio = netio_desc_create_tap(nio_name,tokens[3]); - break; - - case NETIO_TYPE_UDP: - if (count != 6) { - vm_error(router->vm, - "invalid number of arguments for UDP NIO '%s'\n",str); - goto done; - } - - nio = netio_desc_create_udp(nio_name,atoi(tokens[3]), - tokens[4],atoi(tokens[5])); - break; - - case NETIO_TYPE_TCP_CLI: - if (count != 5) { - vm_error(router->vm, - "invalid number of arguments for TCP CLI NIO '%s'\n",str); - goto done; - } - - nio = netio_desc_create_tcp_cli(nio_name,tokens[3],tokens[4]); - break; - - case NETIO_TYPE_TCP_SER: - if (count != 4) { - vm_error(router->vm, - "invalid number of arguments for TCP SER NIO '%s'\n",str); - goto done; - } - - nio = netio_desc_create_tcp_ser(nio_name,tokens[3]); - break; - - case NETIO_TYPE_NULL: - nio = netio_desc_create_null(nio_name); - break; - -#ifdef LINUX_ETH - case NETIO_TYPE_LINUX_ETH: - if (count != 4) { - vm_error(router->vm, - "invalid number of arguments for Linux Eth NIO '%s'\n", - str); - goto done; - } - - nio = netio_desc_create_lnxeth(nio_name,tokens[3]); - break; -#endif - -#ifdef GEN_ETH - case NETIO_TYPE_GEN_ETH: - if (count != 4) { - vm_error(router->vm, - "invalid number of arguments for Generic Eth NIO '%s'\n", - str); - goto done; - } - - nio = netio_desc_create_geneth(nio_name,tokens[3]); - break; -#endif - - default: - vm_error(router->vm,"unknown NETIO type '%s'\n",tokens[2]); - goto done; - } - - if (!nio) { - vm_error(router->vm,"unable to create NETIO " - "descriptor for NM slot %u\n",nm_bay); - goto done; - } - - if (c3725_nm_add_nio_binding(router,nm_bay,port_id,nio_name) == -1) { - vm_error(router->vm,"unable to add NETIO binding for slot %u\n",nm_bay); - netio_release(nio_name); - netio_delete(nio_name); - goto done; - } - - netio_release(nio_name); - res = 0; - - done: - /* The complete array was cleaned by strsplit */ - for(i=0;idev_type, - !nm_drivers[i]->supported ? "(NOT WORKING)" : ""); - } - - printf("\n"); -} - /* Set the base MAC address of the chassis */ static int c3725_burn_mac_addr(c3725_t *router,n_eth_addr_t *addr) { @@ -1033,6 +361,7 @@ 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); @@ -1042,8 +371,18 @@ return(-1); } - return(dev_gt96100_init(vm,"gt96100",C3725_GT96K_ADDR,0x200000, - C3725_GT96K_IRQ,c3725_net_irq_for_slot_port(0,0))); + 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 */ @@ -1058,9 +397,9 @@ if (c3725_init_gt96100(router) == -1) return(-1); - /* Initialize PCI map (NM slot 1 & 2) */ - router->nm_bay[1].pci_map = vm->pci_bus[1]; - router->nm_bay[2].pci_map = vm->pci_bus[1]; + /* Initialize PCI map (NM slots 1 & 2) */ + vm->slots_pci_bus[1] = vm->pci_bus[1]; + vm->slots_pci_bus[2] = vm->pci_bus[1]; vm->elf_machine_id = C3725_ELF_MACHINE_ID; return(0); @@ -1087,12 +426,17 @@ } /* Initialize default parameters for a C3725 */ -void c3725_init_defaults(c3725_t *router) +static void c3725_init_defaults(c3725_t *router) { vm_instance_t *vm = router->vm; n_eth_addr_t *m; m_uint16_t pid; + /* Set platform slots characteristics */ + vm->nr_slots = C3725_MAX_NM_BAYS; + vm->slots_type = CISCO_CARD_TYPE_NM; + vm->slots_drivers = nm_drivers; + pid = (m_uint16_t)getpid(); /* Generate a chassis MAC address based on the instance ID */ @@ -1108,6 +452,9 @@ cisco_eeprom_copy(&router->mb_eeprom,&eeprom_c3725_mainboard); c3725_burn_mac_addr(router,&router->mac_addr); + /* The GT96100 system controller has 2 integrated FastEthernet ports */ + vm_slot_add_binding(vm,"GT96100-FE",0,0); + vm->ram_mmap = C3725_DEFAULT_RAM_MMAP; vm->ram_size = C3725_DEFAULT_RAM_SIZE; vm->rom_size = C3725_DEFAULT_ROM_SIZE; @@ -1115,25 +462,19 @@ vm->conf_reg_setup = C3725_DEFAULT_CONF_REG; vm->clock_divisor = C3725_DEFAULT_CLOCK_DIV; vm->nvram_rom_space = C3725_NVRAM_ROM_RES_SIZE; - router->nm_iomem_size = C3725_DEFAULT_IOMEM_SIZE; + vm->nm_iomem_size = C3725_DEFAULT_IOMEM_SIZE; vm->pcmcia_disk_size[0] = C3725_DEFAULT_DISK0_SIZE; vm->pcmcia_disk_size[1] = C3725_DEFAULT_DISK1_SIZE; - - /* Enable NVRAM operations to load/store configs */ - vm->nvram_extract_config = c3725_nvram_extract_config; - vm->nvram_push_config = c3725_nvram_push_config; } /* Initialize the C3725 Platform */ -int c3725_init_platform(c3725_t *router) +static int c3725_init_platform(c3725_t *router) { vm_instance_t *vm = router->vm; - struct c3725_nm_bay *nm_bay; cpu_mips_t *cpu; cpu_gen_t *gen; vm_obj_t *obj; - int i; /* Copy config register setup into "active" config register */ vm->conf_reg = vm->conf_reg_setup; @@ -1206,6 +547,9 @@ dev_flash_copy_data(obj,0,mips64_microcode,mips64_microcode_len); c3725_nvram_check_empty_config(vm); + /* Byte swapping */ + dev_bswap_init(vm,"mem_bswap",C3725_BSWAP_ADDR,1024*1048576,0x00000000ULL); + /* Initialize the NS16552 DUART */ dev_ns16552_init(vm,C3725_DUART_ADDR,0x1000,3,C3725_DUART_IRQ, vm->vtty_con,vm->vtty_aux); @@ -1218,22 +562,9 @@ dev_pcmcia_disk_init(vm,"slot1",C3725_SLOT1_ADDR,0x200000, vm->pcmcia_disk_size[1],1); - /* The GT96100 system controller has 2 integrated FastEthernet ports */ - c3725_nm_add_binding(router,"GT96100-FE",0); - /* Initialize Network Modules */ - for(i=0;inm_bay[i]; - - if (!nm_bay->dev_type) - continue; - - if (c3725_nm_init(router,i) == -1) { - vm_error(vm,"unable to create Network Module \"%s\"\n", - nm_bay->dev_type); - return(-1); - } - } + if (vm_slot_init_all(vm) == -1) + return(-1); /* Show device list */ c3725_show_hardware(router); @@ -1241,7 +572,7 @@ } /* Boot the IOS image */ -int c3725_boot_ios(c3725_t *router) +static int c3725_boot_ios(c3725_t *router) { vm_instance_t *vm = router->vm; cpu_mips_t *cpu; @@ -1332,9 +663,9 @@ } /* Initialize a Cisco 3725 instance */ -int c3725_init_instance(c3725_t *router) +static int c3725_init_instance(vm_instance_t *vm) { - vm_instance_t *vm = router->vm; + c3725_t *router = VM_C3725(vm); m_uint32_t rom_entry_point; cpu_mips_t *cpu0; @@ -1381,10 +712,8 @@ } /* Stop a Cisco 3725 instance */ -int c3725_stop_instance(c3725_t *router) +static int c3725_stop_instance(vm_instance_t *vm) { - vm_instance_t *vm = router->vm; - printf("\nC3725 '%s': stopping simulation.\n",vm->name); vm_log(vm,"C3725_STOP","stopping simulation.\n"); @@ -1399,7 +728,65 @@ } /* Free resources that were used during execution to emulate hardware */ - c3725_nm_shutdown_all(router); + vm_slot_shutdown_all(vm); vm_hardware_shutdown(vm); return(0); } + +/* Get MAC address MSB */ +static u_int c3725_get_mac_addr_msb(void) +{ + return(0xC2); +} + +/* Parse specific options for the Cisco 3725 platform */ +static int c3725_cli_parse_options(vm_instance_t *vm,int option) +{ + switch(option) { + /* IO memory reserved for NMs (in percents!) */ + case OPT_IOMEM_SIZE: + vm->nm_iomem_size = 0x8000 | atoi(optarg); + break; + + /* Unknown option */ + default: + return(-1); + } + + return(0); +} + +/* Show specific CLI options */ +static void c3725_cli_show_options(vm_instance_t *vm) +{ + printf(" --iomem-size : IO memory (in percents, default: %u)\n" + " -p : Define a Network Module\n" + " -s : Bind a Network IO interface to a " + "Network Module\n", + vm->nm_iomem_size); +} + +/* Platform definition */ +static vm_platform_t c3725_platform = { + "c3725", "C3725", "3725", + c3725_create_instance, + c3725_delete_instance, + c3725_init_instance, + c3725_stop_instance, + c3725_nvram_extract_config, + c3725_nvram_push_config, + c3725_get_mac_addr_msb, + NULL, + c3725_cli_parse_options, + c3725_cli_show_options, + NULL, +}; + +/* Register the c3725 platform */ +int c3725_platform_register(void) +{ + if (vm_platform_register(&c3725_platform) == -1) + return(-1); + + return(hypervisor_c3725_init(&c3725_platform)); +}