/[dynamips]/trunk/dev_c3725.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/dev_c3725.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

upstream/dynamips-0.2.6-RC5/dev_c3725.c revision 6 by dpavlin, Sat Oct 6 16:09:07 2007 UTC trunk/dev_c3725.c revision 12 by dpavlin, Sat Oct 6 16:45:40 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   * Cisco 3725 simulation platform.   * Cisco router simulation platform.
3   * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)   * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4   *   *
5   * Generic Cisco 3725 routines and definitions (EEPROM,...).   * Generic Cisco 3725 routines and definitions (EEPROM,...).
# Line 12  Line 12 
12  #include <sys/types.h>  #include <sys/types.h>
13  #include <assert.h>  #include <assert.h>
14    
15  #include "mips64.h"  #include "cpu.h"
16    #include "vm.h"
17  #include "dynamips.h"  #include "dynamips.h"
18  #include "memory.h"  #include "memory.h"
19  #include "device.h"  #include "device.h"
20  #include "pci_io.h"  #include "pci_io.h"
21  #include "dev_gt.h"  #include "dev_gt.h"
22  #include "cisco_eeprom.h"  #include "cisco_eeprom.h"
23    #include "dev_rom.h"
24  #include "dev_c3725.h"  #include "dev_c3725.h"
25    #include "dev_c3725_iofpga.h"
26  #include "dev_vtty.h"  #include "dev_vtty.h"
27  #include "registry.h"  #include "registry.h"
28    
# Line 48  struct cisco_eeprom eeprom_c3725_mainboa Line 51  struct cisco_eeprom eeprom_c3725_mainboa
51  /* ======================================================================== */  /* ======================================================================== */
52  /* Network Module Drivers                                                   */  /* Network Module Drivers                                                   */
53  /* ======================================================================== */  /* ======================================================================== */
54  static struct c3725_nm_driver *nm_drivers[] = {  static struct cisco_card_driver *nm_drivers[] = {
55     &dev_c3725_nm_1fe_tx_driver,     &dev_c3725_nm_1fe_tx_driver,
56     &dev_c3725_nm_16esw_driver,     &dev_c3725_nm_16esw_driver,
57     &dev_c3725_gt96100_fe_driver,     &dev_c3725_gt96100_fe_driver,
58     &dev_c3725_nm_4t_driver,     &dev_c3725_nm_4t_driver,
59       &dev_c3725_nm_nam_driver,
60       &dev_c3725_nm_cids_driver,
61     NULL,     NULL,
62  };  };
63    
# Line 60  static struct c3725_nm_driver *nm_driver Line 65  static struct c3725_nm_driver *nm_driver
65  /* Cisco 3725 router instances                                              */  /* Cisco 3725 router instances                                              */
66  /* ======================================================================== */  /* ======================================================================== */
67    
68    /* Initialize default parameters for a C3725 */
69    static void c3725_init_defaults(c3725_t *router);
70    
71  /* Directly extract the configuration from the NVRAM device */  /* Directly extract the configuration from the NVRAM device */
72  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)
73  {    {  
74     u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;     u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;
75     m_uint32_t start,nvlen;     m_uint32_t start,nvlen;
# Line 116  ssize_t c3725_nvram_extract_config(vm_in Line 124  ssize_t c3725_nvram_extract_config(vm_in
124  }  }
125    
126  static int c3725_nvram_push_config_part(vm_instance_t *vm,  static int c3725_nvram_push_config_part(vm_instance_t *vm,
127                                          char *buffer,size_t len,                                          u_char *buffer,size_t len,
128                                          u_char *ios_ptr)                                          u_char *ios_ptr)
129  {  {
130     m_uint32_t cfg_offset,cklen,tmp;     m_uint32_t cfg_offset,cklen,tmp;
# Line 151  static int c3725_nvram_push_config_part( Line 159  static int c3725_nvram_push_config_part(
159  }  }
160    
161  /* Directly push the IOS configuration to the NVRAM device */  /* Directly push the IOS configuration to the NVRAM device */
162  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)
163  {  {
164     u_char *base_ptr,*ios_ptr;     u_char *base_ptr,*ios_ptr;
165     int fd;     int fd;
# Line 174  int c3725_nvram_push_config(vm_instance_ Line 182  int c3725_nvram_push_config(vm_instance_
182  }  }
183    
184  /* Check for empty config */  /* Check for empty config */
185  int c3725_nvram_check_empty_config(vm_instance_t *vm)  static int c3725_nvram_check_empty_config(vm_instance_t *vm)
186  {  {
187     struct vdevice *rom_dev;     struct vdevice *rom_dev;
188     m_uint64_t addr;     m_uint64_t addr;
# Line 201  int c3725_nvram_check_empty_config(vm_in Line 209  int c3725_nvram_check_empty_config(vm_in
209  }  }
210    
211  /* Create a new router instance */  /* Create a new router instance */
212  c3725_t *c3725_create_instance(char *name,int instance_id)  static int c3725_create_instance(vm_instance_t *vm)
213  {  {
214     c3725_t *router;     c3725_t *router;
215    
216     if (!(router = malloc(sizeof(*router)))) {     if (!(router = malloc(sizeof(*router)))) {
217        fprintf(stderr,"C3725 '%s': Unable to create new instance!\n",name);        fprintf(stderr,"C3725 '%s': Unable to create new instance!\n",vm->name);
218        return NULL;        return(-1);
219     }     }
220    
221     memset(router,0,sizeof(*router));     memset(router,0,sizeof(*router));
222       router->vm = vm;
223     if (!(router->vm = vm_create(name,instance_id,VM_TYPE_C3725))) {     vm->hw_data = router;
       fprintf(stderr,"C3725 '%s': unable to create VM instance!\n",name);  
       goto err_vm;  
    }  
224    
225     c3725_init_defaults(router);     c3725_init_defaults(router);
226     router->vm->hw_data = router;     return(0);
    return router;  
   
  err_vm:  
    free(router);  
    return NULL;  
227  }  }
228    
229  /* Free resources used by a router instance */  /* Free resources used by a router instance */
230  static int c3725_free_instance(void *data,void *arg)  static int c3725_delete_instance(vm_instance_t *vm)
231  {  {
232     vm_instance_t *vm = data;     c3725_t *router = VM_C3725(vm);
    c3725_t *router;  
233     int i;     int i;
234    
235     if (vm->type == VM_TYPE_C3725) {     /* Stop all CPUs */
236        router = VM_C3725(vm);     if (vm->cpu_group != NULL) {
237          vm_stop(vm);
       /* Stop all CPUs */  
       if (vm->cpu_group != NULL) {  
          vm_stop(vm);  
238                
239           if (cpu_group_sync_state(vm->cpu_group) == -1) {        if (cpu_group_sync_state(vm->cpu_group) == -1) {
240              vm_error(vm,"unable to sync with system CPUs.\n");           vm_error(vm,"unable to sync with system CPUs.\n");
241              return(FALSE);           return(FALSE);
          }  
242        }        }
243       }
244    
245        /* Remove NIO bindings */     /* Remove NIO bindings */
246        for(i=0;i<C3725_MAX_NM_BAYS;i++)     for(i=0;i<vm->nr_slots;i++)
247           c3725_nm_remove_all_nio_bindings(router,i);        vm_slot_remove_all_nio_bindings(vm,i);
   
       /* Shutdown all Network Modules */  
       c3725_nm_shutdown_all(router);  
248    
249        /* Free mainboard EEPROM */     /* Shutdown all Network Modules */
250        cisco_eeprom_free(&router->mb_eeprom);     vm_slot_shutdown_all(vm);
251    
252        /* Free all resources used by VM */     /* Free mainboard EEPROM */
253        vm_free(vm);     cisco_eeprom_free(&router->mb_eeprom);
254    
255        /* Free the router structure */     /* Free all resources used by VM */
256        free(router);     vm_free(vm);
       return(TRUE);  
    }  
257    
258     return(FALSE);     /* Free the router structure */
259       free(router);
260       return(TRUE);
261  }  }
262    
263  /* Delete a router instance */  /* Get WIC device address for the specified onboard port */
264  int c3725_delete_instance(char *name)  int c3725_get_onboard_wic_addr(u_int slot,m_uint64_t *phys_addr)
265  {  {
266     return(registry_delete_if_unused(name,OBJ_TYPE_VM,     if (slot >= C3725_MAX_WIC_BAYS)
267                                      c3725_free_instance,NULL));        return(-1);
 }  
268    
269  /* Delete all router instances */     *phys_addr = C3725_WIC_ADDR + (slot * C3725_WIC_SIZE);
270  int c3725_delete_all_instances(void)     return(0);
 {  
    return(registry_delete_type(OBJ_TYPE_VM,c3725_free_instance,NULL));  
271  }  }
272    
273  /* Save configuration of a C3725 instance */  /* Set EEPROM for the specified slot */
274  void c3725_save_config(c3725_t *router,FILE *fd)  int c3725_set_slot_eeprom(c3725_t *router,u_int slot,
275                              struct cisco_eeprom *eeprom)
276  {  {
277     vm_instance_t *vm = router->vm;     if ((slot < 1) || (slot >= C3725_MAX_NM_BAYS))
278     struct c3725_nio_binding *nb;        return(-1);
    struct c3725_nm_bay *bay;  
    int i;  
   
    /* General settings */  
    fprintf(fd,"c3725 create %s %u\n",vm->name,vm->instance_id);  
   
    /* VM configuration */  
    vm_save_config(vm,fd);  
   
    /* Network Module settings */  
    for(i=0;i<C3725_MAX_NM_BAYS;i++) {  
       if (!(bay = c3725_nm_get_info(router,i)))  
          continue;  
   
       if (bay->dev_type) {  
          fprintf(fd,"c3725 add_nm_binding %s %u %s\n",  
                  vm->name,i,bay->dev_type);  
       }  
   
       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);  
       }  
    }  
279    
280     fprintf(fd,"\n");     router->nm_eeprom_group[slot-1].eeprom[0] = eeprom;
281       return(0);
282  }  }
283    
284  /* Save configurations of all C3725 instances */  /* Get slot/port corresponding to specified network IRQ */
285  static void c3725_reg_save_config(registry_entry_t *entry,void *opt,int *err)  static inline void
286    c3725_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port)
287  {  {
288     vm_instance_t *vm = entry->data;     irq -= C3725_NETIO_IRQ_BASE;
289     c3725_t *router = VM_C3725(vm);     *port = irq & C3725_NETIO_IRQ_PORT_MASK;
290       *slot = irq >> C3725_NETIO_IRQ_PORT_BITS;
    if (vm->type == VM_TYPE_C3725)  
       c3725_save_config(router,(FILE *)opt);  
291  }  }
292    
293  void c3725_save_config_all(FILE *fd)  /* Get network IRQ for specified slot/port */
294    u_int c3725_net_irq_for_slot_port(u_int slot,u_int port)
295  {  {
296     registry_foreach_type(OBJ_TYPE_VM,c3725_reg_save_config,fd,NULL);     u_int irq;
297    
298       irq = (slot << C3725_NETIO_IRQ_PORT_BITS) + port;
299       irq += C3725_NETIO_IRQ_BASE;
300    
301       return(irq);
302  }  }
303    
304  /* Get PCI device for the specified NM bay */  /* Get PCI device for the specified NM bay */
# Line 341  int c3725_nm_get_pci_device(u_int nm_bay Line 314  int c3725_nm_get_pci_device(u_int nm_bay
314     }     }
315  }  }
316    
 /* 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;i<C3725_MAX_NM_BAYS;i++) {  
       if (!router->nm_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;i<C3725_MAX_NM_BAYS;i++) {  
       if (!(bay = c3725_nm_get_info(router,i)) || !bay->nm_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;i<NM_DESC_MAX_TOKENS;i++)  
       free(tokens[i]);  
   
    return(res);  
 }  
   
 /* Add a Network IO descriptor binding (command line) */  
 int c3725_cmd_add_nio(c3725_t *router,char *str)  
 {  
    char *tokens[NM_DESC_MAX_TOKENS];  
    int i,count,nio_type,res=-1;  
    u_int nm_bay,port_id;  
    netio_desc_t *nio;  
    char nio_name[128];  
   
    /* A port adapter description is like "1:3:tap:tap0" */  
    if ((count = m_strsplit(str,':',tokens,NM_DESC_MAX_TOKENS)) < 3) {  
       vm_error(router->vm,"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;i<NM_DESC_MAX_TOKENS;i++)  
       free(tokens[i]);  
   
    return(res);  
 }  
   
 /* Show the list of available NM drivers */  
 void c3725_nm_show_drivers(void)  
 {  
    int i;  
   
    printf("Available C3725 Network Module drivers:\n");  
   
    for(i=0;nm_drivers[i];i++) {  
       printf("  * %s %s\n",  
              nm_drivers[i]->dev_type,  
              !nm_drivers[i]->supported ? "(NOT WORKING)" : "");  
    }  
     
    printf("\n");  
 }  
   
317  /* Set the base MAC address of the chassis */  /* Set the base MAC address of the chassis */
318  static int c3725_burn_mac_addr(c3725_t *router,n_eth_addr_t *addr)  static int c3725_burn_mac_addr(c3725_t *router,n_eth_addr_t *addr)
319  {  {
# Line 1010  int c3725_chassis_set_mac_addr(c3725_t * Line 361  int c3725_chassis_set_mac_addr(c3725_t *
361  static int c3725_init_gt96100(c3725_t *router)  static int c3725_init_gt96100(c3725_t *router)
362  {  {
363     vm_instance_t *vm = router->vm;     vm_instance_t *vm = router->vm;
364       vm_obj_t *obj;
365    
366     vm->pci_bus[0] = pci_bus_create("PCI bus #0",0);     vm->pci_bus[0] = pci_bus_create("PCI bus #0",0);
367     vm->pci_bus[1] = pci_bus_create("PCI bus #1",0);     vm->pci_bus[1] = pci_bus_create("PCI bus #1",0);
# Line 1019  static int c3725_init_gt96100(c3725_t *r Line 371  static int c3725_init_gt96100(c3725_t *r
371        return(-1);        return(-1);
372     }     }
373        
374     return(dev_gt96100_init(vm,"gt96100",C3725_GT96K_ADDR,0x200000,     if (dev_gt96100_init(vm,"gt96100",C3725_GT96K_ADDR,0x200000,
375                             C3725_GT96K_IRQ,C3725_NETIO_IRQ));                          C3725_GT96K_IRQ,
376                            C3725_EXT_IRQ,
377                            c3725_net_irq_for_slot_port(0,0),
378                            255) == -1)
379          return(-1);
380    
381       if (!(obj = vm_object_find(router->vm,"gt96100")))
382          return(-1);
383    
384       router->gt_data = obj->data;
385       return(0);
386  }  }
387    
388  /* Initialize a Cisco 3725 */  /* Initialize a Cisco 3725 */
# Line 1029  static int c3725_init(c3725_t *router) Line 391  static int c3725_init(c3725_t *router)
391     vm_instance_t *vm = router->vm;     vm_instance_t *vm = router->vm;
392    
393     /* Set the processor type: R7000 */     /* Set the processor type: R7000 */
394     mips64_set_prid(vm->boot_cpu,MIPS_PRID_R7000);     mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R7000);
395    
396     /* Initialize the Galileo GT-96100 PCI controller */     /* Initialize the Galileo GT-96100 PCI controller */
397     if (c3725_init_gt96100(router) == -1)     if (c3725_init_gt96100(router) == -1)
398        return(-1);        return(-1);
399    
400     /* Initialize PCI map (NM slot 1 & 2) */     /* Initialize PCI map (NM slots 1 & 2) */
401     router->nm_bay[1].pci_map = vm->pci_bus[1];     vm->slots_pci_bus[1] = vm->pci_bus[1];
402     router->nm_bay[2].pci_map = vm->pci_bus[1];     vm->slots_pci_bus[2] = vm->pci_bus[1];
403    
404     vm->elf_machine_id = C3725_ELF_MACHINE_ID;     vm->elf_machine_id = C3725_ELF_MACHINE_ID;
405     return(0);     return(0);
# Line 1064  void c3725_show_hardware(c3725_t *router Line 426  void c3725_show_hardware(c3725_t *router
426  }  }
427    
428  /* Initialize default parameters for a C3725 */  /* Initialize default parameters for a C3725 */
429  void c3725_init_defaults(c3725_t *router)  static void c3725_init_defaults(c3725_t *router)
430  {    {  
431     vm_instance_t *vm = router->vm;       vm_instance_t *vm = router->vm;  
432     n_eth_addr_t *m;     n_eth_addr_t *m;
433     m_uint16_t pid;     m_uint16_t pid;
434    
435       /* Set platform slots characteristics */
436       vm->nr_slots   = C3725_MAX_NM_BAYS;
437       vm->slots_type = CISCO_CARD_TYPE_NM;
438       vm->slots_drivers = nm_drivers;
439    
440     pid = (m_uint16_t)getpid();     pid = (m_uint16_t)getpid();
441    
442     /* Generate a chassis MAC address based on the instance ID */     /* Generate a chassis MAC address based on the instance ID */
# Line 1085  void c3725_init_defaults(c3725_t *router Line 452  void c3725_init_defaults(c3725_t *router
452     cisco_eeprom_copy(&router->mb_eeprom,&eeprom_c3725_mainboard);     cisco_eeprom_copy(&router->mb_eeprom,&eeprom_c3725_mainboard);
453     c3725_burn_mac_addr(router,&router->mac_addr);     c3725_burn_mac_addr(router,&router->mac_addr);
454    
455       /* The GT96100 system controller has 2 integrated FastEthernet ports */
456       vm_slot_add_binding(vm,"GT96100-FE",0,0);
457    
458     vm->ram_mmap          = C3725_DEFAULT_RAM_MMAP;     vm->ram_mmap          = C3725_DEFAULT_RAM_MMAP;
459     vm->ram_size          = C3725_DEFAULT_RAM_SIZE;     vm->ram_size          = C3725_DEFAULT_RAM_SIZE;
460     vm->rom_size          = C3725_DEFAULT_ROM_SIZE;     vm->rom_size          = C3725_DEFAULT_ROM_SIZE;
# Line 1092  void c3725_init_defaults(c3725_t *router Line 462  void c3725_init_defaults(c3725_t *router
462     vm->conf_reg_setup    = C3725_DEFAULT_CONF_REG;     vm->conf_reg_setup    = C3725_DEFAULT_CONF_REG;
463     vm->clock_divisor     = C3725_DEFAULT_CLOCK_DIV;     vm->clock_divisor     = C3725_DEFAULT_CLOCK_DIV;
464     vm->nvram_rom_space   = C3725_NVRAM_ROM_RES_SIZE;     vm->nvram_rom_space   = C3725_NVRAM_ROM_RES_SIZE;
465     router->nm_iomem_size = C3725_DEFAULT_IOMEM_SIZE;     vm->nm_iomem_size     = C3725_DEFAULT_IOMEM_SIZE;
466    
467     vm->pcmcia_disk_size[0] = C3725_DEFAULT_DISK0_SIZE;     vm->pcmcia_disk_size[0] = C3725_DEFAULT_DISK0_SIZE;
468     vm->pcmcia_disk_size[1] = C3725_DEFAULT_DISK1_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;  
469  }  }
470    
471  /* Initialize the C3725 Platform */  /* Initialize the C3725 Platform */
472  int c3725_init_platform(c3725_t *router)  static int c3725_init_platform(c3725_t *router)
473  {  {
    extern m_uint8_t microcode[];  
    extern ssize_t microcode_len;  
474     vm_instance_t *vm = router->vm;     vm_instance_t *vm = router->vm;
    struct c3725_nm_bay *nm_bay;  
475     cpu_mips_t *cpu;     cpu_mips_t *cpu;
476       cpu_gen_t *gen;
477     vm_obj_t *obj;     vm_obj_t *obj;
    int i;  
478    
479     /* Copy config register setup into "active" config register */     /* Copy config register setup into "active" config register */
480     vm->conf_reg = vm->conf_reg_setup;     vm->conf_reg = vm->conf_reg_setup;
# Line 1123  int c3725_init_platform(c3725_t *router) Line 486  int c3725_init_platform(c3725_t *router)
486     vm->cpu_group = cpu_group_create("System CPU");     vm->cpu_group = cpu_group_create("System CPU");
487    
488     /* Initialize the virtual MIPS processor */     /* Initialize the virtual MIPS processor */
489     if (!(cpu = cpu_create(vm,0))) {     if (!(gen = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
490        vm_error(vm,"unable to create CPU!\n");        vm_error(vm,"unable to create CPU!\n");
491        return(-1);        return(-1);
492     }     }
493    
494       cpu = CPU_MIPS64(gen);
495    
496     /* Add this CPU to the system CPU group */     /* Add this CPU to the system CPU group */
497     cpu_group_add(vm->cpu_group,cpu);     cpu_group_add(vm->cpu_group,gen);
498     vm->boot_cpu = cpu;     vm->boot_cpu = gen;
499    
500       /* Initialize the IRQ routing vectors */
501       vm->set_irq = mips64_vm_set_irq;
502       vm->clear_irq = mips64_vm_clear_irq;
503    
504     /* Mark the Network IO interrupt as high priority */     /* Mark the Network IO interrupt as high priority */
505     cpu->irq_idle_preempt[C3725_NETIO_IRQ] = TRUE;     cpu->irq_idle_preempt[C3725_NETIO_IRQ] = TRUE;
# Line 1147  int c3725_init_platform(c3725_t *router) Line 516  int c3725_init_platform(c3725_t *router)
516     dev_remote_control_init(vm,0x16000000,0x1000);     dev_remote_control_init(vm,0x16000000,0x1000);
517    
518     /* Specific Storage Area (SSA) */     /* Specific Storage Area (SSA) */
519     dev_ram_init(vm,"ssa",TRUE,FALSE,NULL,0x16001000ULL,0x7000);     dev_ram_init(vm,"ssa",TRUE,FALSE,NULL,FALSE,0x16001000ULL,0x7000);
520    
521     /* IO FPGA */     /* IO FPGA */
522     if (dev_c3725_iofpga_init(router,C3725_IOFPGA_ADDR,0x40000) == -1)     if (dev_c3725_iofpga_init(router,C3725_IOFPGA_ADDR,0x40000) == -1)
523        return(-1);        return(-1);
524    
525       if (!(obj = vm_object_find(router->vm,"io_fpga")))
526          return(-1);
527    
528       router->iofpga_data = obj->data;
529    
530  #if 0  #if 0
531     /* PCI IO space */     /* PCI IO space */
532     if (!(vm->pci_io_space = pci_io_data_init(vm,C3725_PCI_IO_ADDR)))     if (!(vm->pci_io_space = pci_io_data_init(vm,C3725_PCI_IO_ADDR)))
# Line 1170  int c3725_init_platform(c3725_t *router) Line 544  int c3725_init_platform(c3725_t *router)
544     if (!(obj = dev_flash_init(vm,"rom",C3725_ROM_ADDR,vm->rom_size*1048576)))     if (!(obj = dev_flash_init(vm,"rom",C3725_ROM_ADDR,vm->rom_size*1048576)))
545        return(-1);        return(-1);
546    
547     dev_flash_copy_data(obj,0,microcode,microcode_len);     dev_flash_copy_data(obj,0,mips64_microcode,mips64_microcode_len);
548     c3725_nvram_check_empty_config(vm);     c3725_nvram_check_empty_config(vm);
549    
550       /* Byte swapping */
551       dev_bswap_init(vm,"mem_bswap",C3725_BSWAP_ADDR,1024*1048576,0x00000000ULL);
552    
553     /* Initialize the NS16552 DUART */     /* Initialize the NS16552 DUART */
554     dev_ns16552_init(vm,C3725_DUART_ADDR,0x1000,3,C3725_DUART_IRQ,     dev_ns16552_init(vm,C3725_DUART_ADDR,0x1000,3,C3725_DUART_IRQ,
555                      vm->vtty_con,vm->vtty_aux);                      vm->vtty_con,vm->vtty_aux);
# Line 1185  int c3725_init_platform(c3725_t *router) Line 562  int c3725_init_platform(c3725_t *router)
562     dev_pcmcia_disk_init(vm,"slot1",C3725_SLOT1_ADDR,0x200000,     dev_pcmcia_disk_init(vm,"slot1",C3725_SLOT1_ADDR,0x200000,
563                          vm->pcmcia_disk_size[1],1);                          vm->pcmcia_disk_size[1],1);
564    
    /* The GT96100 system controller has 2 integrated FastEthernet ports */  
    c3725_nm_add_binding(router,"GT96100-FE",0);  
   
565     /* Initialize Network Modules */     /* Initialize Network Modules */
566     for(i=0;i<C3725_MAX_NM_BAYS;i++) {     if (vm_slot_init_all(vm) == -1)
567        nm_bay = &router->nm_bay[i];        return(-1);
   
       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);  
       }  
    }  
568    
569     /* Show device list */     /* Show device list */
570     c3725_show_hardware(router);     c3725_show_hardware(router);
# Line 1208  int c3725_init_platform(c3725_t *router) Line 572  int c3725_init_platform(c3725_t *router)
572  }  }
573    
574  /* Boot the IOS image */  /* Boot the IOS image */
575  int c3725_boot_ios(c3725_t *router)  static int c3725_boot_ios(c3725_t *router)
576  {    {  
577     vm_instance_t *vm = router->vm;     vm_instance_t *vm = router->vm;
578       cpu_mips_t *cpu;
579    
580     if (!vm->boot_cpu)     if (!vm->boot_cpu)
581        return(-1);        return(-1);
# Line 1225  int c3725_boot_ios(c3725_t *router) Line 590  int c3725_boot_ios(c3725_t *router)
590     }     }
591    
592     /* Reset the boot CPU */     /* Reset the boot CPU */
593     mips64_reset(vm->boot_cpu);     cpu = CPU_MIPS64(vm->boot_cpu);
594       mips64_reset(cpu);
595    
596     /* Load IOS image */     /* Load IOS image */
597     if (mips64_load_elf_image(vm->boot_cpu,vm->ios_image,     if (mips64_load_elf_image(cpu,vm->ios_image,
598                               (vm->ghost_status == VM_GHOST_RAM_USE),                               (vm->ghost_status == VM_GHOST_RAM_USE),
599                               &vm->ios_entry_point) < 0)                               &vm->ios_entry_point) < 0)
600     {     {
# Line 1239  int c3725_boot_ios(c3725_t *router) Line 605  int c3725_boot_ios(c3725_t *router)
605     /* Launch the simulation */     /* Launch the simulation */
606     printf("\nC3725 '%s': starting simulation (CPU0 PC=0x%llx), "     printf("\nC3725 '%s': starting simulation (CPU0 PC=0x%llx), "
607            "JIT %sabled.\n",            "JIT %sabled.\n",
608            vm->name,vm->boot_cpu->pc,vm->jit_use ? "en":"dis");            vm->name,cpu->pc,vm->jit_use ? "en":"dis");
609    
610     vm_log(vm,"C3725_BOOT",     vm_log(vm,"C3725_BOOT",
611            "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",            "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
612            vm->boot_cpu->pc,vm->boot_cpu->idle_pc,vm->jit_use ? "on":"off");            cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
613    
614     /* Start main CPU */     /* Start main CPU */
615     if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {     if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
# Line 1255  int c3725_boot_ios(c3725_t *router) Line 621  int c3725_boot_ios(c3725_t *router)
621     return(0);     return(0);
622  }  }
623    
624    /* Set an IRQ */
625    static void c3725_set_irq(vm_instance_t *vm,u_int irq)
626    {
627       c3725_t *router = VM_C3725(vm);
628       cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
629       u_int slot,port;
630    
631       switch(irq) {
632          case 0 ... 7:
633             mips64_set_irq(cpu0,irq);
634    
635             if (cpu0->irq_idle_preempt[irq])
636                cpu_idle_break_wait(cpu0->gen);
637             break;
638    
639          case C3725_NETIO_IRQ_BASE ... C3725_NETIO_IRQ_END:
640             c3725_net_irq_get_slot_port(irq,&slot,&port);
641             dev_c3725_iofpga_net_set_irq(router->iofpga_data,slot,port);
642             break;
643       }
644    }
645    
646    /* Clear an IRQ */
647    static void c3725_clear_irq(vm_instance_t *vm,u_int irq)
648    {
649       c3725_t *router = VM_C3725(vm);
650       cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
651       u_int slot,port;
652    
653       switch(irq) {
654          case 0 ... 7:
655             mips64_clear_irq(cpu0,irq);
656             break;
657    
658          case C3725_NETIO_IRQ_BASE ... C3725_NETIO_IRQ_END:
659             c3725_net_irq_get_slot_port(irq,&slot,&port);
660             dev_c3725_iofpga_net_clear_irq(router->iofpga_data,slot,port);
661             break;
662       }
663    }
664    
665  /* Initialize a Cisco 3725 instance */  /* Initialize a Cisco 3725 instance */
666  int c3725_init_instance(c3725_t *router)  static int c3725_init_instance(vm_instance_t *vm)
667  {    {  
668     vm_instance_t *vm = router->vm;     c3725_t *router = VM_C3725(vm);
669     m_uint32_t rom_entry_point;     m_uint32_t rom_entry_point;
670     cpu_mips_t *cpu0;     cpu_mips_t *cpu0;
671    
# Line 1273  int c3725_init_instance(c3725_t *router) Line 680  int c3725_init_instance(c3725_t *router)
680        return(-1);        return(-1);
681     }     }
682    
683       /* IRQ routing */
684       vm->set_irq = c3725_set_irq;
685       vm->clear_irq = c3725_clear_irq;
686    
687     /* Load IOS configuration file */     /* Load IOS configuration file */
688     if (vm->ios_config != NULL) {     if (vm->ios_config != NULL) {
689        vm_nvram_push_config(vm,vm->ios_config);        vm_nvram_push_config(vm,vm->ios_config);
# Line 1280  int c3725_init_instance(c3725_t *router) Line 691  int c3725_init_instance(c3725_t *router)
691     }     }
692    
693     /* Load ROM (ELF image or embedded) */     /* Load ROM (ELF image or embedded) */
694     cpu0 = vm->boot_cpu;     cpu0 = CPU_MIPS64(vm->boot_cpu);
695     rom_entry_point = (m_uint32_t)MIPS_ROM_PC;     rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
696    
697     if ((vm->rom_filename != NULL) &&     if ((vm->rom_filename != NULL) &&
# Line 1301  int c3725_init_instance(c3725_t *router) Line 712  int c3725_init_instance(c3725_t *router)
712  }  }
713    
714  /* Stop a Cisco 3725 instance */  /* Stop a Cisco 3725 instance */
715  int c3725_stop_instance(c3725_t *router)  static int c3725_stop_instance(vm_instance_t *vm)
716  {  {
    vm_instance_t *vm = router->vm;  
   
717     printf("\nC3725 '%s': stopping simulation.\n",vm->name);     printf("\nC3725 '%s': stopping simulation.\n",vm->name);
718     vm_log(vm,"C3725_STOP","stopping simulation.\n");     vm_log(vm,"C3725_STOP","stopping simulation.\n");
719    
# Line 1319  int c3725_stop_instance(c3725_t *router) Line 728  int c3725_stop_instance(c3725_t *router)
728     }     }
729    
730     /* Free resources that were used during execution to emulate hardware */     /* Free resources that were used during execution to emulate hardware */
731     c3725_nm_shutdown_all(router);     vm_slot_shutdown_all(vm);
732     vm_hardware_shutdown(vm);     vm_hardware_shutdown(vm);
733     return(0);     return(0);
734  }  }
735    
736    /* Get MAC address MSB */
737    static u_int c3725_get_mac_addr_msb(void)
738    {
739       return(0xC2);
740    }
741    
742    /* Parse specific options for the Cisco 3725 platform */
743    static int c3725_cli_parse_options(vm_instance_t *vm,int option)
744    {
745       switch(option) {
746          /* IO memory reserved for NMs (in percents!) */
747          case OPT_IOMEM_SIZE:
748             vm->nm_iomem_size = 0x8000 | atoi(optarg);
749             break;
750    
751          /* Unknown option */
752          default:
753             return(-1);
754       }
755    
756       return(0);
757    }
758    
759    /* Show specific CLI options */
760    static void c3725_cli_show_options(vm_instance_t *vm)
761    {
762       printf("  --iomem-size <val> : IO memory (in percents, default: %u)\n"
763              "  -p <nm_desc>       : Define a Network Module\n"
764              "  -s <nm_nio>        : Bind a Network IO interface to a "
765              "Network Module\n",
766              vm->nm_iomem_size);
767    }
768    
769    /* Platform definition */
770    static vm_platform_t c3725_platform = {
771       "c3725", "C3725", "3725",
772       c3725_create_instance,
773       c3725_delete_instance,
774       c3725_init_instance,
775       c3725_stop_instance,
776       c3725_nvram_extract_config,
777       c3725_nvram_push_config,
778       c3725_get_mac_addr_msb,
779       NULL,
780       c3725_cli_parse_options,
781       c3725_cli_show_options,
782       NULL,
783    };
784    
785    /* Register the c3725 platform */
786    int c3725_platform_register(void)
787    {
788       if (vm_platform_register(&c3725_platform) == -1)
789          return(-1);
790    
791       return(hypervisor_c3725_init(&c3725_platform));
792    }

Legend:
Removed from v.6  
changed lines
  Added in v.12

  ViewVC Help
Powered by ViewVC 1.1.26