/[dynamips]/upstream/dynamips-0.2.8-RC1/dev_c2600.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 /upstream/dynamips-0.2.8-RC1/dev_c2600.c

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

upstream/dynamips-0.2.7/dev_c2600.c revision 10 by dpavlin, Sat Oct 6 16:29:14 2007 UTC upstream/dynamips-0.2.8-RC1/dev_c2600.c revision 11 by dpavlin, Sat Oct 6 16:33:40 2007 UTC
# Line 47  struct c2600_mb_id { Line 47  struct c2600_mb_id {
47     char *name;     char *name;
48     char *mb_driver;     char *mb_driver;
49     m_uint16_t id;     m_uint16_t id;
50       int xm_model;
51     int supported;     int supported;
52  };  };
53    
54  struct c2600_mb_id c2600_mainboard_id[] = {  struct c2600_mb_id c2600_mainboard_id[] = {
55     { "2610"   , "CISCO2600-MB-1E"  , 0x0091, TRUE  },     { "2610"   , "CISCO2600-MB-1E"  , 0x0091, FALSE, TRUE  },
56     { "2611"   , "CISCO2600-MB-2E"  , 0x0092, TRUE  },     { "2611"   , "CISCO2600-MB-2E"  , 0x0092, FALSE, TRUE  },
57     { "2620"   , "CISCO2600-MB-1FE" , 0x0094, TRUE  },     { "2620"   , "CISCO2600-MB-1FE" , 0x0094, FALSE, TRUE  },
58     { "2621"   , "CISCO2600-MB-2FE" , 0x00a2, TRUE  },     { "2621"   , "CISCO2600-MB-2FE" , 0x00a2, FALSE, TRUE  },
59     { "2610XM" , "CISCO2600-MB-1FE" , 0x036a, TRUE  },     { "2610XM" , "CISCO2600-MB-1FE" , 0x036a, TRUE,  TRUE  },
60     { "2611XM" , "CISCO2600-MB-2FE" , 0x036b, FALSE },     { "2611XM" , "CISCO2600-MB-2FE" , 0x036b, TRUE,  FALSE },
61     { "2620XM" , "CISCO2600-MB-1FE" , 0x036c, TRUE  },     { "2620XM" , "CISCO2600-MB-1FE" , 0x036c, TRUE,  TRUE  },
62     { "2621XM" , "CISCO2600-MB-2FE" , 0x036d, FALSE },     { "2621XM" , "CISCO2600-MB-2FE" , 0x036d, TRUE,  FALSE },
63     { "2650XM" , "CISCO2600-MB-1FE" , 0x036e, TRUE  },     { "2650XM" , "CISCO2600-MB-1FE" , 0x036e, TRUE,  TRUE  },
64     { "2651XM" , "CISCO2600-MB-2FE" , 0x036f, FALSE },     { "2651XM" , "CISCO2600-MB-2FE" , 0x036f, TRUE,  FALSE },
65     { NULL     , NULL               , 0x0000, 0     },     { NULL     , NULL               , 0x0000, FALSE, FALSE },
66  };  };
67    
68  /* ======================================================================== */  /* ======================================================================== */
69  /* Network Module Drivers                                                   */  /* Network Module Drivers                                                   */
70  /* ======================================================================== */  /* ======================================================================== */
71  static struct c2600_nm_driver *nm_drivers[] = {  static struct cisco_card_driver *nm_drivers[] = {
72     &dev_c2600_mb1e_eth_driver,     &dev_c2600_mb1e_eth_driver,
73     &dev_c2600_mb2e_eth_driver,     &dev_c2600_mb2e_eth_driver,
74     &dev_c2600_mb1fe_eth_driver,     &dev_c2600_mb1fe_eth_driver,
# Line 78  static struct c2600_nm_driver *nm_driver Line 79  static struct c2600_nm_driver *nm_driver
79     &dev_c2600_nm_1fe_tx_driver,     &dev_c2600_nm_1fe_tx_driver,
80     &dev_c2600_nm_16esw_driver,     &dev_c2600_nm_16esw_driver,
81    
82       &dev_c2600_nm_nam_driver,
83       &dev_c2600_nm_cids_driver,
84    
85     NULL,     NULL,
86  };  };
87    
# Line 85  static struct c2600_nm_driver *nm_driver Line 89  static struct c2600_nm_driver *nm_driver
89  /* Cisco 2600 router instances                                              */  /* Cisco 2600 router instances                                              */
90  /* ======================================================================== */  /* ======================================================================== */
91    
92    /* Initialize default parameters for a C2600 */
93    static void c2600_init_defaults(c2600_t *router);
94    
95  /* Read a byte from the NVRAM */  /* Read a byte from the NVRAM */
96  static inline m_uint8_t nvram_read_byte(u_char *base,u_int offset)  static inline m_uint8_t nvram_read_byte(u_char *base,u_int offset)
97  {  {
# Line 162  static void nvram_memcpy_to(u_char *base Line 169  static void nvram_memcpy_to(u_char *base
169  }  }
170    
171  /* Directly extract the configuration from the NVRAM device */  /* Directly extract the configuration from the NVRAM device */
172  ssize_t c2600_nvram_extract_config(vm_instance_t *vm,char **buffer)  ssize_t c2600_nvram_extract_config(vm_instance_t *vm,u_char **buffer)
173  {  {
174     u_char *base_ptr;     u_char *base_ptr;
175     u_int ios_ptr,cfg_ptr,end_ptr;     u_int ios_ptr,cfg_ptr,end_ptr;
# Line 241  static m_uint16_t c2600_nvram_cksum(u_ch Line 248  static m_uint16_t c2600_nvram_cksum(u_ch
248  }  }
249    
250  /* Directly push the IOS configuration to the NVRAM device */  /* Directly push the IOS configuration to the NVRAM device */
251  int c2600_nvram_push_config(vm_instance_t *vm,char *buffer,size_t len)  int c2600_nvram_push_config(vm_instance_t *vm,u_char *buffer,size_t len)
252  {  {
253     m_uint32_t cfg_offset,cklen,tmp,ios_ptr,cfg_ptr;     m_uint32_t cfg_offset,cklen,tmp,ios_ptr,cfg_ptr;
254     m_uint16_t cksum;     m_uint16_t cksum;
# Line 311  int c2600_nvram_check_empty_config(vm_in Line 318  int c2600_nvram_check_empty_config(vm_in
318  }  }
319    
320  /* Create a new router instance */  /* Create a new router instance */
321  c2600_t *c2600_create_instance(char *name,int instance_id)  static int c2600_create_instance(vm_instance_t *vm)
322  {  {
323     c2600_t *router;     c2600_t *router;
324    
325     if (!(router = malloc(sizeof(*router)))) {     if (!(router = malloc(sizeof(*router)))) {
326        fprintf(stderr,"C2600 '%s': Unable to create new instance!\n",name);        fprintf(stderr,"C2600 '%s': Unable to create new instance!\n",vm->name);
327        return NULL;        return(-1);
328     }     }
329    
330     memset(router,0,sizeof(*router));     memset(router,0,sizeof(*router));
331       router->vm = vm;
332     if (!(router->vm = vm_create(name,instance_id,VM_TYPE_C2600))) {     vm->hw_data = router;
       fprintf(stderr,"C2600 '%s': unable to create VM instance!\n",name);  
       goto err_vm;  
    }  
333    
334     c2600_init_defaults(router);     c2600_init_defaults(router);
335     router->vm->hw_data = router;     return(0);
    return router;  
   
  err_vm:  
    free(router);  
    return NULL;  
336  }  }
337    
338  /* Free resources used by a router instance */  /* Free resources used by a router instance */
339  static int c2600_free_instance(void *data,void *arg)  static int c2600_delete_instance(vm_instance_t *vm)
340  {  {
341     vm_instance_t *vm = data;     c2600_t *router = VM_C2600(vm);
    c2600_t *router;  
342     int i;     int i;
343    
344     if (vm->type == VM_TYPE_C2600) {     /* Stop all CPUs */
345        router = VM_C2600(vm);     if (vm->cpu_group != NULL) {
346          vm_stop(vm);
       /* Stop all CPUs */  
       if (vm->cpu_group != NULL) {  
          vm_stop(vm);  
347                
348           if (cpu_group_sync_state(vm->cpu_group) == -1) {        if (cpu_group_sync_state(vm->cpu_group) == -1) {
349              vm_error(vm,"unable to sync with system CPUs.\n");           vm_error(vm,"unable to sync with system CPUs.\n");
350              return(FALSE);           return(FALSE);
          }  
351        }        }
   
       /* Remove NIO bindings */  
       for(i=0;i<C2600_MAX_NM_BAYS;i++)  
          c2600_nm_remove_all_nio_bindings(router,i);  
   
       /* Shutdown all Network Modules */  
       c2600_nm_shutdown_all(router);  
   
       /* 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);  
352     }     }
353    
354     return(FALSE);     /* Remove NIO bindings */
355  }     for(i=0;i<vm->nr_slots;i++)
356          vm_slot_remove_all_nio_bindings(vm,i);
357    
358  /* Delete a router instance */     /* Shutdown all Network Modules */
359  int c2600_delete_instance(char *name)     vm_slot_shutdown_all(vm);
360  {    
361     return(registry_delete_if_unused(name,OBJ_TYPE_VM,     /* Free mainboard EEPROM */
362                                      c2600_free_instance,NULL));     cisco_eeprom_free(&router->mb_eeprom);
 }  
363    
364  /* Delete all router instances */     /* Free all resources used by VM */
365  int c2600_delete_all_instances(void)     vm_free(vm);
366  {  
367     return(registry_delete_type(OBJ_TYPE_VM,c2600_free_instance,NULL));     /* Free the router structure */
368       free(router);
369       return(TRUE);
370  }  }
371    
372  /* Save configuration of a C2600 instance */  /* Save configuration of a C2600 instance */
373  void c2600_save_config(c2600_t *router,FILE *fd)  void c2600_save_config(vm_instance_t *vm,FILE *fd)
374  {  {
375     vm_instance_t *vm = router->vm;     c2600_t *router = VM_C2600(vm);
    struct c2600_nio_binding *nb;  
    struct c2600_nm_bay *bay;  
    int i;  
   
    /* General settings */  
    fprintf(fd,"c2600 create %s %u\n",vm->name,vm->instance_id);  
    fprintf(fd,"c2600 set_chassis %s %s\n",vm->name,router->mainboard_type);  
   
    /* VM configuration */  
    vm_save_config(vm,fd);  
   
    /* Network Module settings */  
    for(i=0;i<C2600_MAX_NM_BAYS;i++) {  
       if (!(bay = c2600_nm_get_info(router,i)))  
          continue;  
   
       if (bay->dev_type) {  
          fprintf(fd,"c2600 add_nm_binding %s %u %s\n",  
                  vm->name,i,bay->dev_type);  
       }  
   
       for(nb=bay->nio_list;nb;nb=nb->next) {  
          fprintf(fd,"c2600 add_nio_binding %s %u %u %s\n",  
                  vm->name,i,nb->port_id,nb->nio->name);  
       }  
    }  
376    
377     fprintf(fd,"\n");     fprintf(fd,"c2600 set_chassis %s %s\n\n",vm->name,router->mainboard_type);
378  }  }
379    
380  /* Save configurations of all C2600 instances */  /* Get WIC device address for the specified onboard port */
381  static void c2600_reg_save_config(registry_entry_t *entry,void *opt,int *err)  int c2600_get_onboard_wic_addr(u_int slot,m_uint64_t *phys_addr)
382  {  {
383     vm_instance_t *vm = entry->data;     if (slot >= C2600_MAX_WIC_BAYS)
384     c2600_t *router = VM_C2600(vm);        return(-1);
385    
386     if (vm->type == VM_TYPE_C2600)     *phys_addr = C2600_WIC_ADDR + (slot * C2600_WIC_SIZE);
387        c2600_save_config(router,(FILE *)opt);     return(0);
388  }  }
389    
390  void c2600_save_config_all(FILE *fd)  /* Set EEPROM for the specified slot */
391    int c2600_set_slot_eeprom(c2600_t *router,u_int slot,
392                              struct cisco_eeprom *eeprom)
393  {  {
394     registry_foreach_type(OBJ_TYPE_VM,c2600_reg_save_config,fd,NULL);     switch(slot) {
395          case 1:
396             router->nm_eeprom_group.eeprom[0] = eeprom;
397             return(0);
398          default:
399             return(-1);
400       }
401  }  }
402    
403  /* Get slot/port corresponding to specified network IRQ */  /* Get slot/port corresponding to specified network IRQ */
# Line 486  void c2600_mainboard_show_drivers(void) Line 447  void c2600_mainboard_show_drivers(void)
447     printf("\n");     printf("\n");
448  }  }
449    
 /* Set NM EEPROM definition */  
 int c2600_nm_set_eeprom(c2600_t *router,u_int nm_bay,  
                         const struct cisco_eeprom *eeprom)  
 {  
    if (nm_bay == 0)  
       return(0);  
   
    if (nm_bay != 1) {  
       vm_error(router->vm,"c2600_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,"c2600_nm_set_eeprom: no memory.\n");  
       return(-1);  
    }  
     
    return(0);  
 }  
   
 /* Unset NM EEPROM definition (empty bay) */  
 int c2600_nm_unset_eeprom(c2600_t *router,u_int nm_bay)  
 {  
    if (nm_bay == 0)  
       return(0);  
   
    if (nm_bay != 1) {  
       vm_error(router->vm,"c2600_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 c2600_nm_check_eeprom(c2600_t *router,u_int nm_bay)  
 {  
    if (nm_bay != 1)  
       return(FALSE);  
   
    return(cisco_eeprom_valid(&router->nm_bay[nm_bay].eeprom));  
 }  
   
 /* Get bay info */  
 struct c2600_nm_bay *c2600_nm_get_info(c2600_t *router,u_int nm_bay)  
 {  
    if (nm_bay >= C2600_MAX_NM_BAYS)  
       return NULL;  
   
    return(&router->nm_bay[nm_bay]);  
 }  
   
 /* Get NM type */  
 char *c2600_nm_get_type(c2600_t *router,u_int nm_bay)  
 {  
    struct c2600_nm_bay *bay;  
   
    bay = c2600_nm_get_info(router,nm_bay);  
    return((bay != NULL) ? bay->dev_type : NULL);  
 }  
   
 /* Get driver info about the specified slot */  
 void *c2600_nm_get_drvinfo(c2600_t *router,u_int nm_bay)  
 {  
    struct c2600_nm_bay *bay;  
   
    bay = c2600_nm_get_info(router,nm_bay);  
    return((bay != NULL) ? bay->drv_info : NULL);  
 }  
   
 /* Set driver info for the specified slot */  
 int c2600_nm_set_drvinfo(c2600_t *router,u_int nm_bay,void *drv_info)  
 {  
    struct c2600_nm_bay *bay;  
   
    if (!(bay = c2600_nm_get_info(router,nm_bay)))  
       return(-1);  
   
    bay->drv_info = drv_info;  
    return(0);  
 }  
   
 /* Get a NM driver */  
 static struct c2600_nm_driver *c2600_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 c2600_nm_add_binding(c2600_t *router,char *dev_type,u_int nm_bay)  
 {    
    struct c2600_nm_driver *nm_driver;  
    struct c2600_nm_bay *bay;  
   
    if (!(bay = c2600_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 = c2600_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 c2600_nm_remove_binding(c2600_t *router,u_int nm_bay)  
 {    
    struct c2600_nm_bay *bay;  
   
    if (!(bay = c2600_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 */  
    c2600_nm_remove_all_nio_bindings(router,nm_bay);  
   
    bay->dev_type  = NULL;  
    bay->nm_driver = NULL;  
    return(0);  
 }  
   
 /* Find a NIO binding */  
 struct c2600_nio_binding *  
 c2600_nm_find_nio_binding(c2600_t *router,u_int nm_bay,u_int port_id)  
 {    
    struct c2600_nio_binding *nb;  
    struct c2600_nm_bay *bay;  
   
    if (!(bay = c2600_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 c2600_nm_add_nio_binding(c2600_t *router,u_int nm_bay,u_int port_id,  
                              char *nio_name)  
 {  
    struct c2600_nio_binding *nb;  
    struct c2600_nm_bay *bay;  
    netio_desc_t *nio;  
   
    if (!(bay = c2600_nm_get_info(router,nm_bay)))  
       return(-1);  
   
    /* check that a NIO is not already bound to this port */  
    if (c2600_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 c2600_nm_remove_nio_binding(c2600_t *router,u_int nm_bay,u_int port_id)  
 {  
    struct c2600_nio_binding *nb;  
    struct c2600_nm_bay *bay;  
     
    if (!(bay = c2600_nm_get_info(router,nm_bay)))  
       return(-1);  
   
    if (!(nb = c2600_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 c2600_nm_remove_all_nio_bindings(c2600_t *router,u_int nm_bay)  
 {    
    struct c2600_nio_binding *nb,*next;  
    struct c2600_nm_bay *bay;  
   
    if (!(bay = c2600_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 c2600_nm_enable_nio(c2600_t *router,u_int nm_bay,u_int port_id)  
 {  
    struct c2600_nio_binding *nb;  
    struct c2600_nm_bay *bay;  
   
    if (!(bay = c2600_nm_get_info(router,nm_bay)))  
       return(-1);  
   
    /* check that we have an NIO binding for this interface */  
    if (!(nb = c2600_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 c2600_nm_disable_nio(c2600_t *router,u_int nm_bay,u_int port_id)  
 {  
    struct c2600_nm_bay *bay;  
   
    if (!(bay = c2600_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 c2600_nm_enable_all_nio(c2600_t *router,u_int nm_bay)  
 {  
    struct c2600_nio_binding *nb;  
    struct c2600_nm_bay *bay;  
   
    if (!(bay = c2600_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 c2600_nm_disable_all_nio(c2600_t *router,u_int nm_bay)  
 {  
    struct c2600_nio_binding *nb;  
    struct c2600_nm_bay *bay;  
   
    if (!(bay = c2600_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 c2600_nm_init(c2600_t *router,u_int nm_bay)  
 {    
    struct c2600_nm_bay *bay;  
    size_t len;  
   
    if (!(bay = c2600_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 */  
    c2600_nm_enable_all_nio(router,nm_bay);  
    return(0);  
 }  
   
 /* Shutdown a Network Module */  
 int c2600_nm_shutdown(c2600_t *router,u_int nm_bay)  
 {  
    struct c2600_nm_bay *bay;  
   
    if (!(bay = c2600_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 */  
    c2600_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 c2600_nm_shutdown_all(c2600_t *router)  
 {  
    int i;  
   
    for(i=0;i<C2600_MAX_NM_BAYS;i++) {  
       if (!router->nm_bay[i].dev_type)  
          continue;  
   
       c2600_nm_shutdown(router,i);  
    }  
   
    return(0);  
 }  
   
 /* Show info about all NMs */  
 int c2600_nm_show_all_info(c2600_t *router)  
 {  
    struct c2600_nm_bay *bay;  
    int i;  
   
    for(i=0;i<C2600_MAX_NM_BAYS;i++) {  
       if (!(bay = c2600_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 c2600_cmd_nm_create(c2600_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 = c2600_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 c2600_cmd_add_nio(c2600_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),"c2600-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 (c2600_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);  
 }  
   
450  /* Show the list of available NM drivers */  /* Show the list of available NM drivers */
451  void c2600_nm_show_drivers(void)  void c2600_nm_show_drivers(void)
452  {  {
# Line 1143  int c2600_mainboard_set_type(c2600_t *ro Line 492  int c2600_mainboard_set_type(c2600_t *ro
492     }     }
493    
494     router->mainboard_type = mainboard_type;     router->mainboard_type = mainboard_type;
495       router->xm_model = mb_info->xm_model;
496    
497     /* Set the cookie */     /* Set the cookie */
498     memcpy(router->vm->chassis_cookie,     memcpy(router->vm->chassis_cookie,
# Line 1152  int c2600_mainboard_set_type(c2600_t *ro Line 502  int c2600_mainboard_set_type(c2600_t *ro
502    
503     /* Set the chassis base MAC address */     /* Set the chassis base MAC address */
504     c2600_burn_mac_addr(router,&router->mac_addr);     c2600_burn_mac_addr(router,&router->mac_addr);
505    
506       /* Set the mainboard driver */
507       if (vm_slot_active(router->vm,0,0))
508          vm_slot_remove_binding(router->vm,0,0);
509    
510       vm_slot_add_binding(router->vm,mb_info->mb_driver,0,0);
511     return(0);     return(0);
512  }  }
513    
# Line 1180  static int c2600_init(c2600_t *router) Line 536  static int c2600_init(c2600_t *router)
536     }     }
537        
538     /* Create the PCI controller */     /* Create the PCI controller */
539     if (dev_c2600_pci_init(vm,"c2600_pci",C2600_PCICTRL_ADDR,0x1000,     if (dev_c2600_pci_init(vm,"c2600_pci",C2600_PCICTRL_ADDR,0x10000,
540                            vm->pci_bus[0]) == -1)                            vm->pci_bus[0]) == -1)
541        return(-1);        return(-1);
542    
543     /* Bind PCI bus to slots 0 and 1 */     /* Bind PCI bus to slots 0 and 1 */
544     router->nm_bay[0].pci_map = vm->pci_bus[0];     vm->slots_pci_bus[0] = vm->pci_bus[0];
545     router->nm_bay[1].pci_map = vm->pci_bus[0];     vm->slots_pci_bus[1] = vm->pci_bus[0];
546    
547     vm->elf_machine_id = C2600_ELF_MACHINE_ID;     vm->elf_machine_id = C2600_ELF_MACHINE_ID;
548     return(0);     return(0);
# Line 1213  void c2600_show_hardware(c2600_t *router Line 569  void c2600_show_hardware(c2600_t *router
569  }  }
570    
571  /* Initialize default parameters for a C2600 */  /* Initialize default parameters for a C2600 */
572  void c2600_init_defaults(c2600_t *router)  static void c2600_init_defaults(c2600_t *router)
573  {    {  
574     vm_instance_t *vm = router->vm;       vm_instance_t *vm = router->vm;  
575     n_eth_addr_t *m;     n_eth_addr_t *m;
576     m_uint16_t pid;     m_uint16_t pid;
577    
578       /* Set platform slots characteristics */
579       vm->nr_slots   = C2600_MAX_NM_BAYS;
580       vm->slots_type = CISCO_CARD_TYPE_NM;
581       vm->slots_drivers = nm_drivers;
582    
583     pid = (m_uint16_t)getpid();     pid = (m_uint16_t)getpid();
584    
585     /* Generate a chassis MAC address based on the instance ID */     /* Generate a chassis MAC address based on the instance ID */
# Line 1241  void c2600_init_defaults(c2600_t *router Line 602  void c2600_init_defaults(c2600_t *router
602     vm->conf_reg_setup    = C2600_DEFAULT_CONF_REG;     vm->conf_reg_setup    = C2600_DEFAULT_CONF_REG;
603     vm->clock_divisor     = C2600_DEFAULT_CLOCK_DIV;     vm->clock_divisor     = C2600_DEFAULT_CLOCK_DIV;
604     vm->nvram_rom_space   = C2600_NVRAM_ROM_RES_SIZE;     vm->nvram_rom_space   = C2600_NVRAM_ROM_RES_SIZE;
605     router->nm_iomem_size = C2600_DEFAULT_IOMEM_SIZE;     vm->nm_iomem_size     = C2600_DEFAULT_IOMEM_SIZE;
606    
607     vm->pcmcia_disk_size[0] = C2600_DEFAULT_DISK0_SIZE;     vm->pcmcia_disk_size[0] = C2600_DEFAULT_DISK0_SIZE;
608     vm->pcmcia_disk_size[1] = C2600_DEFAULT_DISK1_SIZE;     vm->pcmcia_disk_size[1] = C2600_DEFAULT_DISK1_SIZE;
   
    /* Enable NVRAM operations to load/store configs */  
    vm->nvram_extract_config = c2600_nvram_extract_config;  
    vm->nvram_push_config = c2600_nvram_push_config;  
609  }  }
610    
611  /* Set an IRQ */  /* Set an IRQ */
# Line 1320  static void c2600_clear_irq(vm_instance_ Line 677  static void c2600_clear_irq(vm_instance_
677  }  }
678    
679  /* Initialize the C2600 Platform */  /* Initialize the C2600 Platform */
680  int c2600_init_platform(c2600_t *router)  static int c2600_init_platform(c2600_t *router)
681  {  {
682     vm_instance_t *vm = router->vm;     vm_instance_t *vm = router->vm;
    struct c2600_mb_id *mb_info;  
    struct c2600_nm_bay *nm_bay;  
683     vm_obj_t *obj;     vm_obj_t *obj;
684     cpu_ppc_t *cpu;     cpu_ppc_t *cpu;
685     cpu_gen_t *gen;     cpu_gen_t *gen;
    int i;  
686    
687     /* Copy config register setup into "active" config register */     /* Copy config register setup into "active" config register */
688     vm->conf_reg = vm->conf_reg_setup;     vm->conf_reg = vm->conf_reg_setup;
# Line 1368  int c2600_init_platform(c2600_t *router) Line 722  int c2600_init_platform(c2600_t *router)
722     dev_remote_control_init(vm,0xf6000000,0x1000);     dev_remote_control_init(vm,0xf6000000,0x1000);
723    
724     /* MPC860 */     /* MPC860 */
725       cpu->mpc860_immr = C2600_MPC860_ADDR;
726    
727     if (dev_mpc860_init(vm,"MPC860",C2600_MPC860_ADDR,0x10000) == -1)     if (dev_mpc860_init(vm,"MPC860",C2600_MPC860_ADDR,0x10000) == -1)
728        return(-1);        return(-1);
729    
# Line 1411  int c2600_init_platform(c2600_t *router) Line 767  int c2600_init_platform(c2600_t *router)
767     c2600_nvram_check_empty_config(vm);     c2600_nvram_check_empty_config(vm);
768    
769     /* Bootflash */     /* Bootflash */
770     dev_bootflash_init(vm,"flash0",C2600_FLASH_ADDR,8*1048576);     dev_bootflash_init(vm,"flash0","c2600-bootflash-8mb",
771     dev_bootflash_init(vm,"flash1",C2600_FLASH_ADDR+0x800000,8*1048576);                        C2600_FLASH_ADDR);
772       dev_bootflash_init(vm,"flash1","c2600-bootflash-8mb",
773                          C2600_FLASH_ADDR+0x800000);
774    
775     /* Initialize the NS16552 DUART */     /* Initialize the NS16552 DUART */
776     dev_ns16552_init(vm,C2600_DUART_ADDR,0x1000,0,C2600_DUART_IRQ,     dev_ns16552_init(vm,C2600_DUART_ADDR,0x1000,0,C2600_DUART_IRQ,
777                      vm->vtty_con,vm->vtty_aux);                      vm->vtty_con,vm->vtty_aux);
778    
    /* Initialize the mainboard ports */  
    if ((mb_info = c2600_get_mb_info(router->mainboard_type)) != NULL)  
       c2600_nm_add_binding(router,mb_info->mb_driver,0);  
   
779     /* Initialize Network Modules */     /* Initialize Network Modules */
780     for(i=0;i<C2600_MAX_NM_BAYS;i++) {     if (vm_slot_init_all(vm) == -1)
781        nm_bay = &router->nm_bay[i];        return(-1);
   
       if (!nm_bay->dev_type)  
          continue;  
   
       if (c2600_nm_init(router,i) == -1) {  
          vm_error(vm,"unable to create Network Module \"%s\"\n",  
                   nm_bay->dev_type);  
          return(-1);  
       }  
    }  
782    
783     /* Show device list */     /* Show device list */
784     c2600_show_hardware(router);     c2600_show_hardware(router);
# Line 1517  int c2600_boot_ios(c2600_t *router) Line 861  int c2600_boot_ios(c2600_t *router)
861  }  }
862    
863  /* Initialize a Cisco 2600 instance */  /* Initialize a Cisco 2600 instance */
864  int c2600_init_instance(c2600_t *router)  static int c2600_init_instance(vm_instance_t *vm)
865  {    {  
866     vm_instance_t *vm = router->vm;     c2600_t *router = VM_C2600(vm);
867     m_uint32_t rom_entry_point;     m_uint32_t rom_entry_point;
868     cpu_ppc_t *cpu0;     cpu_ppc_t *cpu0;
869    
# Line 1556  int c2600_init_instance(c2600_t *router) Line 900  int c2600_init_instance(c2600_t *router)
900  }  }
901    
902  /* Stop a Cisco 2600 instance */  /* Stop a Cisco 2600 instance */
903  int c2600_stop_instance(c2600_t *router)  int c2600_stop_instance(vm_instance_t *vm)
904  {  {
    vm_instance_t *vm = router->vm;  
   
905     printf("\nC2600 '%s': stopping simulation.\n",vm->name);     printf("\nC2600 '%s': stopping simulation.\n",vm->name);
906     vm_log(vm,"C2600_STOP","stopping simulation.\n");     vm_log(vm,"C2600_STOP","stopping simulation.\n");
907    
# Line 1574  int c2600_stop_instance(c2600_t *router) Line 916  int c2600_stop_instance(c2600_t *router)
916     }     }
917    
918     /* Free resources that were used during execution to emulate hardware */     /* Free resources that were used during execution to emulate hardware */
919     c2600_nm_shutdown_all(router);     vm_slot_shutdown_all(vm);
920     vm_hardware_shutdown(vm);     vm_hardware_shutdown(vm);
921     return(0);     return(0);
922  }  }
923    
924    /* Get MAC address MSB */
925    static u_int c2600_get_mac_addr_msb(void)
926    {
927       return(0xC8);
928    }
929    
930    /* Parse specific options for the Cisco 2600 platform */
931    static int c2600_cli_parse_options(vm_instance_t *vm,int option)
932    {
933       c2600_t *router = VM_C2600(vm);
934    
935       switch(option) {
936          /* IO memory reserved for NMs (in percents!) */
937          case OPT_IOMEM_SIZE:
938             vm->nm_iomem_size = 0x8000 | atoi(optarg);
939             break;
940    
941          /* Mainboard type */
942          case 't':
943             c2600_mainboard_set_type(router,optarg);
944             break;
945    
946          /* Unknown option */
947          default:
948             return(-1);
949       }
950    
951       return(0);
952    }
953    
954    /* Show specific CLI options */
955    static void c2600_cli_show_options(vm_instance_t *vm)
956    {
957       printf("  --iomem-size <val> : IO memory (in percents, default: %u)\n"
958              "  -p <nm_desc>       : Define a Network Module\n"
959              "  -s <nm_nio>        : Bind a Network IO interface to a "
960              "Network Module\n",
961              vm->nm_iomem_size);
962    }
963    
964    /* Platform definition */
965    static vm_platform_t c2600_platform = {
966       "c2600", "C2600", "2600",
967       c2600_create_instance,
968       c2600_delete_instance,
969       c2600_init_instance,
970       c2600_stop_instance,
971       c2600_nvram_extract_config,
972       c2600_nvram_push_config,
973       c2600_get_mac_addr_msb,
974       c2600_save_config,
975       c2600_cli_parse_options,
976       c2600_cli_show_options,
977       c2600_mainboard_show_drivers,
978    };
979    
980    /* Register the c2600 platform */
981    int c2600_platform_register(void)
982    {
983       if (vm_platform_register(&c2600_platform) == -1)
984          return(-1);
985    
986       return(hypervisor_c2600_init(&c2600_platform));
987    }

Legend:
Removed from v.10  
changed lines
  Added in v.11

  ViewVC Help
Powered by ViewVC 1.1.26