📄 cisco_card.c
字号:
/* * Cisco router simulation platform. * Copyright (c) 2007 Christophe Fillot (cf@utc.fr) * * Generic Cisco card routines and definitions. */#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 "cisco_card.h"/* Get cisco card type description */char *cisco_card_get_type_desc(int dev_type){ switch(dev_type) { case CISCO_CARD_TYPE_PA: return("Port Adapter (PA)"); case CISCO_CARD_TYPE_NM: return("Network Module (NM)"); case CISCO_CARD_TYPE_WIC: return("WAN Interface Card (WIC)"); default: return("Unknown"); }}/* Set EEPROM definition for the specified Cisco card */int cisco_card_set_eeprom(vm_instance_t *vm,struct cisco_card *card, const struct cisco_eeprom *eeprom){ if (!eeprom) return(0); if (cisco_eeprom_copy(&card->eeprom,eeprom) == -1) { vm_error(vm,"cisco_card_set_eeprom: no memory (eeprom=%p).\n",eeprom); return(-1); } return(0);}/* Unset EEPROM definition */int cisco_card_unset_eeprom(struct cisco_card *card){ cisco_eeprom_free(&card->eeprom); return(0);}/* Check if a card has a valid EEPROM defined */int cisco_card_check_eeprom(struct cisco_card *card){ return(cisco_eeprom_valid(&card->eeprom));}/* Create a card structure */static inline struct cisco_card *cisco_card_create(u_int card_type){ struct cisco_card *card; if ((card = malloc(sizeof(*card))) != NULL) { memset(card,0,sizeof(*card)); card->card_type = card_type; } return card;}/* Find a NIO binding */static struct cisco_nio_binding *cisco_card_find_nio_binding(struct cisco_card *card,u_int port_id){ struct cisco_nio_binding *nb; if (!card) return NULL; for(nb=card->nio_list;nb;nb=nb->next) if (nb->port_id == port_id) return nb; return NULL;}/* Remove all NIO bindings */static void cisco_card_remove_all_nio_bindings(vm_instance_t *vm,struct cisco_card *card){ struct cisco_nio_binding *nb,*next; for(nb=card->nio_list;nb;nb=next) { next = nb->next; /* tell the slot driver to stop using this NIO */ if (card->driver) card->driver->card_unset_nio(vm,card,nb->port_id); /* unreference NIO object */ netio_release(nb->nio->name); free(nb); } card->nio_list = NULL;}/* Enable all NIO for the specified card */static inlinevoid cisco_card_enable_all_nio(vm_instance_t *vm,struct cisco_card *card){ struct cisco_nio_binding *nb; if (card && card->driver && card->drv_info) for(nb=card->nio_list;nb;nb=nb->next) card->driver->card_set_nio(vm,card,nb->port_id,nb->nio);}/* Disable all NIO for the specified card */static inlinevoid cisco_card_disable_all_nio(vm_instance_t *vm,struct cisco_card *card){ struct cisco_nio_binding *nb; if (card && card->driver && card->drv_info) for(nb=card->nio_list;nb;nb=nb->next) card->driver->card_unset_nio(vm,card,nb->port_id);}/* Initialize a card */static inlineint cisco_card_init(vm_instance_t *vm,struct cisco_card *card,u_int id){ size_t len; /* Check that a device type is defined for this card */ if (!card || !card->dev_type || !card->driver) return(-1); /* Allocate device name */ len = strlen(card->dev_type) + 10; if (!(card->dev_name = malloc(len))) { vm_error(vm,"unable to allocate device name.\n"); return(-1); } snprintf(card->dev_name,len,"%s(%u)",card->dev_type,id); /* Initialize card driver */ if (card->driver->card_init(vm,card) == -1) { vm_error(vm,"unable to initialize card type '%s' (id %u)\n", card->dev_type,id); return(-1); } return(0);}/* Shutdown card */static int cisco_card_shutdown(vm_instance_t *vm,struct cisco_card *card){ /* Check that a device type is defined for this card */ if (!card || !card->dev_type || !card->driver) return(-1); /* Shutdown the NM driver */ if (card->drv_info && (card->driver->card_shutdown(vm,card) == -1)) { vm_error(vm,"unable to shutdown card type '%s' (slot %u/%u)\n", card->dev_type,card->slot_id,card->subslot_id); return(-1); } free(card->dev_name); card->dev_name = NULL; card->drv_info = NULL; return(0);}/* Show info for the specified card */static int cisco_card_show_info(vm_instance_t *vm,struct cisco_card *card){ /* Check that a device type is defined for this card */ if (!card || !card->driver || !card->driver->card_show_info) return(-1); card->driver->card_show_info(vm,card); return(0);}/* Save config for the specified card */static int cisco_card_save_config(vm_instance_t *vm,struct cisco_card *card, FILE *fd){ struct cisco_nio_binding *nb; fprintf(fd,"vm add_slot_binding %s %u %u %s\n", vm->name,card->slot_id,card->subslot_id,card->dev_type); for(nb=card->nio_list;nb;nb=nb->next) { fprintf(fd,"vm add_nio_binding %s %u %u %s\n", vm->name,card->slot_id,nb->orig_port_id,nb->nio->name); } return(0);}/* Find a driver in a driver array */static struct cisco_card_driver *cisco_card_find_driver(struct cisco_card_driver **array,char *dev_type){ int i; for(i=0;array[i]!=NULL;i++) if (!strcmp(array[i]->dev_type,dev_type)) return array[i]; return NULL;}/* ======================================================================== *//* High level routines for managing VM slots. *//* ======================================================================== *//* Get slot info */struct cisco_card *vm_slot_get_card_ptr(vm_instance_t *vm,u_int slot_id){ if (slot_id >= vm->nr_slots) return NULL; return(vm->slots[slot_id]);}/* Get info for a slot/port (with sub-cards) */static int vm_slot_get_info(vm_instance_t *vm,u_int slot_id,u_int port_id, struct cisco_card ***rc,u_int *real_port_id){ struct cisco_card *card; u_int wic_id,card_type; if (slot_id >= VM_MAX_SLOTS) { *rc = NULL; return(-1); } *rc = &vm->slots[slot_id]; card = vm->slots[slot_id]; card_type = (card != NULL) ? card->card_type : CISCO_CARD_TYPE_UNDEF; switch(card_type) { /* * Handle WICs which are sub-slots for Network Modules (NM). * Numbering: wic #0 => port_id = 0x10 * wic #1 => port_id = 0x20 */ case CISCO_CARD_TYPE_NM: wic_id = port_id >> 4; if (wic_id >= (CISCO_CARD_MAX_WIC+1)) { vm_error(vm,"Invalid wic_id %u (slot %u)\n",wic_id,slot_id); return(-1); } if (wic_id >= 0x01) { /* wic card */ *rc = &card->sub_slots[wic_id - 1]; *real_port_id = port_id & 0x0F; } else { /* main card */ *real_port_id = port_id; } return(0); /* No translation for Cisco 7200 Port Adapters and WICs */ case CISCO_CARD_TYPE_PA: case CISCO_CARD_TYPE_WIC: *real_port_id = port_id; return(0); /* Not initialized yet */ default: *real_port_id = port_id; return(0); }}/* Translate a port ID (for sub-cards) */static u_int vm_slot_translate_port_id(vm_instance_t *vm,u_int slot_id,u_int port_id, struct cisco_card **rc){ struct cisco_card **tmp; u_int real_port_id = 0; vm_slot_get_info(vm,slot_id,port_id,&tmp,&real_port_id); *rc = *tmp; return(real_port_id);}/* Check if a slot has an active card */int vm_slot_active(vm_instance_t *vm,u_int slot_id,u_int port_id){ struct cisco_card **rc; u_int real_port_id; if (vm_slot_get_info(vm,slot_id,port_id,&rc,&real_port_id) == -1) return(FALSE); if ((*rc == NULL) || ((*rc)->dev_type == NULL)) return(FALSE); return(TRUE);}/* Set a flag for a card */int vm_slot_set_flag(vm_instance_t *vm,u_int slot_id,u_int port_id,u_int flag){ struct cisco_card **rc; u_int real_port_id; if (vm_slot_get_info(vm,slot_id,port_id,&rc,&real_port_id) == -1) return(FALSE); if (*rc == NULL) return(FALSE); (*rc)->card_flags |= flag; return(TRUE);}/* Add a slot binding */int vm_slot_add_binding(vm_instance_t *vm,char *dev_type, u_int slot_id,u_int port_id){ struct cisco_card_driver *driver,**drv_array; struct cisco_card **rc,*card,*nc,*parent; u_int real_port_id,card_type,card_id; if (vm_slot_get_info(vm,slot_id,port_id,&rc,&real_port_id) == -1) return(-1); /* check that this bay is empty */ if (*rc != NULL) { if ((*rc)->card_flags & CISCO_CARD_FLAG_OVERRIDE) { vm_slot_remove_binding(vm,slot_id,port_id); } else { vm_error(vm,"a card already exists in slot %u/%u (%s)\n", slot_id,port_id,(*rc)->dev_type); return(-1); } } card = vm->slots[slot_id]; if (!card || (card == *rc)) { /* Main slot */ drv_array = vm->slots_drivers; card_type = vm->slots_type; card_id = slot_id; parent = NULL; } else { /* Subslot */ if (!card->driver->card_get_sub_info) { vm_error(vm,"no sub-slot possible for slot %u/%u.\n",slot_id,port_id); return(-1); } if (card->driver->card_get_sub_info(vm,card,port_id, &drv_array,&card_type) == -1) { vm_error(vm,"no sub-slot info for slot %u/%u.\n",slot_id,port_id); return(-1); } card_id = port_id; parent = card; } assert(drv_array != NULL); /* Find the card driver */ if (!(driver = cisco_card_find_driver(drv_array,dev_type))) { vm_error(vm,"unknown card type '%s' for slot %u/%u.\n", dev_type,slot_id,port_id); return(-1); } /* Allocate new card info */ if (!(nc = cisco_card_create(card_type))) return(-1); nc->slot_id = slot_id; nc->subslot_id = port_id; nc->card_id = card_id; nc->dev_type = driver->dev_type; nc->driver = driver; nc->parent = parent; *rc = nc; return(0); }/* Remove a slot binding */int vm_slot_remove_binding(vm_instance_t *vm,u_int slot_id,u_int port_id){ struct cisco_card **rc,*sc; u_int i,real_port_id; if (vm_slot_get_info(vm,slot_id,port_id,&rc,&real_port_id) == -1) return(-1); if (*rc == NULL) return(-1); if ((*rc)->drv_info != NULL) { vm_error(vm,"slot %u/%u is still active\n",slot_id,port_id); return(-1); } for(i=0;i<CISCO_CARD_MAX_SUBSLOTS;i++) { if ((sc = (*rc)->sub_slots[i]) != NULL) { vm_error(vm,"sub-slot %u/%u is still active\n", slot_id,sc->subslot_id); return(-1); } } /* Remove all NIOs bindings */ vm_slot_remove_all_nio_bindings(vm,slot_id); /* Free the card info structure */ free(*rc); *rc = NULL; return(0);}/* Add a network IO binding */int vm_slot_add_nio_binding(vm_instance_t *vm,u_int slot_id,u_int port_id, char *nio_name){ struct cisco_nio_binding *nb; struct cisco_card *card,*rc; u_int real_port_id; netio_desc_t *nio; if (!(card = vm_slot_get_card_ptr(vm,slot_id))) return(-1); /* Get the real card (in case this is a sub-slot) */ real_port_id = vm_slot_translate_port_id(vm,slot_id,port_id,&rc); if (rc == NULL) return(-1); /* check that a NIO is not already bound to this port */ if (cisco_card_find_nio_binding(rc,real_port_id) != NULL) { vm_error(vm,"a NIO already exists for interface %u/%u.\n", slot_id,port_id); return(-1); } /* acquire a reference on the NIO object */ if (!(nio = netio_acquire(nio_name))) { vm_error(vm,"unable to find NIO '%s'.\n",nio_name); return(-1); } /* create a new binding */ if (!(nb = malloc(sizeof(*nb)))) { vm_error(vm,"unable to create NIO binding for interface %u/%u.\n", slot_id,port_id); netio_release(nio_name); return(-1); } memset(nb,0,sizeof(*nb)); nb->nio = nio; nb->port_id = real_port_id; nb->orig_port_id = port_id; nb->next = rc->nio_list; if (nb->next) nb->next->prev = nb; rc->nio_list = nb; return(0);}/* Remove a NIO binding */int vm_slot_remove_nio_binding(vm_instance_t *vm,u_int slot_id,u_int port_id){ struct cisco_nio_binding *nb; struct cisco_card *card,*rc; u_int real_port_id; if (!(card = vm_slot_get_card_ptr(vm,slot_id))) return(-1); /* Get the real card (in case this is a sub-slot) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -