/[dynamips]/upstream/dynamips-0.2.7-RC1/dev_c3745.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

Annotation of /upstream/dynamips-0.2.7-RC1/dev_c3745.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (hide annotations)
Sat Oct 6 16:23:47 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 37486 byte(s)
dynamips-0.2.7-RC1

1 dpavlin 4 /*
2     * Cisco 3745 simulation platform.
3     * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4     *
5     * Generic Cisco 3745 routines and definitions (EEPROM,...).
6     */
7    
8     #include <stdio.h>
9     #include <stdlib.h>
10     #include <string.h>
11     #include <unistd.h>
12     #include <sys/types.h>
13     #include <assert.h>
14    
15 dpavlin 7 #include "cpu.h"
16     #include "vm.h"
17 dpavlin 4 #include "dynamips.h"
18     #include "memory.h"
19     #include "device.h"
20     #include "pci_io.h"
21     #include "dev_gt.h"
22     #include "cisco_eeprom.h"
23 dpavlin 7 #include "dev_rom.h"
24 dpavlin 4 #include "dev_c3745.h"
25     #include "dev_vtty.h"
26     #include "registry.h"
27    
28     /* ======================================================================== */
29     /* EEPROM definitions */
30     /* ======================================================================== */
31    
32     /* Cisco 3745 motherboard EEPROM */
33     static m_uint16_t eeprom_c3745_motherboard_data[] = {
34     0x04FF, 0xC18B, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0x5809,
35     0x6940, 0x02F7, 0xC046, 0x0320, 0x003E, 0x3E03, 0x4241, 0x3085,
36     0x1C12, 0x4004, 0x80FF, 0xFFFF, 0xFFC4, 0x08FF, 0xFFFF, 0xFFFF,
37     0xFFFF, 0xFF81, 0x0000, 0x0000, 0x0400, 0x0300, 0xC508, 0xFFFF,
38     0xFFFF, 0xFFFF, 0xFFFF, 0x4102, 0x0002, 0x04C2, 0x8B58, 0x5858,
39     0x5858, 0x5858, 0x5858, 0x5858, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
40     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
41     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
42     };
43    
44     struct cisco_eeprom eeprom_c3745_motherboard = {
45     "C3745 Motherboard",
46     eeprom_c3745_motherboard_data,
47     sizeof(eeprom_c3745_motherboard_data)/2,
48     };
49    
50     /* Cisco 3745 I/O board EEPROM */
51     static m_uint16_t eeprom_c3745_ioboard_data[] = {
52     0x04FF, 0x4002, 0xF841, 0x0200, 0xC046, 0x0320, 0x0038, 0x7E01,
53     0x4242, 0x3080, 0x0000, 0x0000, 0x0203, 0xC18B, 0x5858, 0x5858,
54     0x5858, 0x5858, 0x5858, 0x5803, 0x0081, 0x0000, 0x0000, 0x0400,
55     0xC809, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFC2, 0x8B58, 0x5858,
56     0x5858, 0x5858, 0x5858, 0x5858, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
57     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
58     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
59     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
60     };
61    
62     struct cisco_eeprom eeprom_c3745_ioboard = {
63     "C3745 I/O board",
64     eeprom_c3745_ioboard_data,
65     sizeof(eeprom_c3745_ioboard_data)/2,
66     };
67    
68     /* Cisco 3745 midplane EEPROM */
69     static m_uint16_t eeprom_c3745_midplane_data[] = {
70     0x04FF, 0x4003, 0x3E41, 0x0200, 0xC046, 0x0320, 0x0030, 0x0101,
71     0x4241, 0x3080, 0x0000, 0x0000, 0x0205, 0xC18B, 0x5858, 0x5858,
72     0x5858, 0x5858, 0x5858, 0x5803, 0x0081, 0x0000, 0x0000, 0x0400,
73     0xC809, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFC3, 0x0600, 0x0DED,
74     0xCD7D, 0x8043, 0x0050, 0xC28B, 0x5858, 0x5858, 0x5858, 0x5858,
75     0x5858, 0x58FF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
76     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
77     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
78     };
79    
80     struct cisco_eeprom eeprom_c3745_midplane = {
81     "C3745 Midplane",
82     eeprom_c3745_midplane_data,
83     sizeof(eeprom_c3745_midplane_data)/2,
84     };
85    
86    
87     /* ======================================================================== */
88     /* Network Module Drivers */
89     /* ======================================================================== */
90     static struct c3745_nm_driver *nm_drivers[] = {
91     &dev_c3745_nm_1fe_tx_driver,
92     &dev_c3745_nm_16esw_driver,
93     &dev_c3745_gt96100_fe_driver,
94     &dev_c3745_nm_4t_driver,
95     NULL,
96     };
97    
98     /* ======================================================================== */
99     /* Cisco 3745 router instances */
100     /* ======================================================================== */
101    
102     /* Directly extract the configuration from the NVRAM device */
103     ssize_t c3745_nvram_extract_config(vm_instance_t *vm,char **buffer)
104     {
105     u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;
106     m_uint32_t start,nvlen;
107     m_uint16_t magic1,magic2;
108     struct vdevice *nvram_dev;
109     off_t nvram_size;
110     int fd;
111    
112     if ((nvram_dev = dev_get_by_name(vm,"rom")))
113     dev_sync(nvram_dev);
114    
115     fd = vm_mmap_open_file(vm,"rom",&base_ptr,&nvram_size);
116    
117     if (fd == -1)
118     return(-1);
119    
120     ios_ptr = base_ptr + C3745_NVRAM_OFFSET;
121     end_ptr = base_ptr + nvram_size;
122    
123     if ((ios_ptr + 0x30) >= end_ptr) {
124     vm_error(vm,"NVRAM file too small\n");
125     return(-1);
126     }
127    
128     magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06));
129     magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08));
130    
131     if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) {
132     vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n",
133     magic1,magic2);
134     return(-1);
135     }
136    
137     start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1;
138     nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18));
139    
140     if (!(*buffer = malloc(nvlen+1))) {
141     vm_error(vm,"unable to allocate config buffer (%u bytes)\n",nvlen);
142     return(-1);
143     }
144    
145     cfg_ptr = ios_ptr + start + 0x08;
146    
147     if ((cfg_ptr + nvlen) > end_ptr) {
148     vm_error(vm,"NVRAM file too small\n");
149     return(-1);
150     }
151    
152     memcpy(*buffer,cfg_ptr,nvlen-1);
153     (*buffer)[nvlen-1] = 0;
154     return(nvlen-1);
155     }
156    
157     static int c3745_nvram_push_config_part(vm_instance_t *vm,
158     char *buffer,size_t len,
159     u_char *ios_ptr)
160     {
161     m_uint32_t cfg_offset,cklen,tmp;
162     m_uint16_t cksum;
163     u_char *cfg_ptr;
164    
165     cfg_offset = 0x2c;
166     cfg_ptr = ios_ptr + cfg_offset;
167    
168     /* Write IOS tag, uncompressed config... */
169     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5);
170     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD);
171     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001);
172     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000);
173     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0c04);
174    
175     /* Store file contents to NVRAM */
176     memcpy(cfg_ptr,buffer,len);
177    
178     /* Write config addresses + size */
179     tmp = cfg_offset - 0x08;
180    
181     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(tmp);
182     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(tmp + len);
183     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len);
184    
185     /* Compute the checksum */
186     cklen = C3745_NVRAM_SIZE - 0x08;
187     cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen);
188     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum);
189     return(0);
190     }
191    
192     /* Directly push the IOS configuration to the NVRAM device */
193     int c3745_nvram_push_config(vm_instance_t *vm,char *buffer,size_t len)
194     {
195     u_char *base_ptr,*ios_ptr;
196     int fd;
197    
198     fd = vm_mmap_create_file(vm,"rom",vm->rom_size*1048576,&base_ptr);
199    
200     if (fd == -1)
201     return(-1);
202    
203     ios_ptr = base_ptr + C3745_NVRAM_OFFSET;
204    
205     /* Normal config */
206     c3745_nvram_push_config_part(vm,buffer,len,ios_ptr);
207    
208     /* Backup config */
209     c3745_nvram_push_config_part(vm,buffer,len,ios_ptr + C3745_NVRAM_SIZE);
210    
211     vm_mmap_close_file(fd,base_ptr,vm->rom_size*1048576);
212     return(0);
213     }
214    
215     /* Check for empty config */
216     int c3745_nvram_check_empty_config(vm_instance_t *vm)
217     {
218     struct vdevice *rom_dev;
219     m_uint64_t addr;
220     size_t len;
221    
222     if (!(rom_dev = dev_get_by_name(vm,"rom")))
223     return(-1);
224    
225     addr = rom_dev->phys_addr + C3745_NVRAM_OFFSET;
226     len = C3745_NVRAM_SIZE;
227    
228     while(len > 0) {
229     if (physmem_copy_u32_from_vm(vm,addr) != 0)
230     return(0);
231    
232     addr += sizeof(m_uint32_t);
233     len -= sizeof(m_uint32_t);
234     }
235    
236     /* Empty NVRAM */
237     vm->conf_reg |= 0x0040;
238     printf("NVRAM is empty, setting config register to 0x%x\n",vm->conf_reg);
239     return(0);
240     }
241    
242     /* Create a new router instance */
243     c3745_t *c3745_create_instance(char *name,int instance_id)
244     {
245     c3745_t *router;
246    
247     if (!(router = malloc(sizeof(*router)))) {
248     fprintf(stderr,"C3745 '%s': Unable to create new instance!\n",name);
249     return NULL;
250     }
251    
252     memset(router,0,sizeof(*router));
253    
254     if (!(router->vm = vm_create(name,instance_id,VM_TYPE_C3745))) {
255     fprintf(stderr,"C3745 '%s': unable to create VM instance!\n",name);
256     goto err_vm;
257     }
258    
259     c3745_init_defaults(router);
260     router->vm->hw_data = router;
261     return router;
262    
263     err_vm:
264     free(router);
265     return NULL;
266     }
267    
268     /* Free resources used by a router instance */
269     static int c3745_free_instance(void *data,void *arg)
270     {
271     vm_instance_t *vm = data;
272     c3745_t *router;
273     int i;
274    
275     if (vm->type == VM_TYPE_C3745) {
276     router = VM_C3745(vm);
277    
278     /* Stop all CPUs */
279     if (vm->cpu_group != NULL) {
280     vm_stop(vm);
281    
282     if (cpu_group_sync_state(vm->cpu_group) == -1) {
283     vm_error(vm,"unable to sync with system CPUs.\n");
284     return(FALSE);
285     }
286     }
287    
288     /* Remove NIO bindings */
289     for(i=0;i<C3745_MAX_NM_BAYS;i++)
290     c3745_nm_remove_all_nio_bindings(router,i);
291    
292     /* Shutdown all Network Modules */
293     c3745_nm_shutdown_all(router);
294    
295     /* Free mainboard EEPROM */
296     for(i=0;i<3;i++)
297     cisco_eeprom_free(&router->sys_eeprom[i]);
298    
299     /* Free all resources used by VM */
300     vm_free(vm);
301    
302     /* Free the router structure */
303     free(router);
304     return(TRUE);
305     }
306    
307     return(FALSE);
308     }
309    
310     /* Delete a router instance */
311     int c3745_delete_instance(char *name)
312     {
313     return(registry_delete_if_unused(name,OBJ_TYPE_VM,
314     c3745_free_instance,NULL));
315     }
316    
317     /* Delete all router instances */
318     int c3745_delete_all_instances(void)
319     {
320     return(registry_delete_type(OBJ_TYPE_VM,c3745_free_instance,NULL));
321     }
322    
323     /* Save configuration of a C3745 instance */
324     void c3745_save_config(c3745_t *router,FILE *fd)
325     {
326     vm_instance_t *vm = router->vm;
327     struct c3745_nio_binding *nb;
328     struct c3745_nm_bay *bay;
329     int i;
330    
331     /* General settings */
332     fprintf(fd,"c3745 create %s %u\n",vm->name,vm->instance_id);
333    
334     /* VM configuration */
335     vm_save_config(vm,fd);
336    
337     /* Network Module settings */
338     for(i=0;i<C3745_MAX_NM_BAYS;i++) {
339     if (!(bay = c3745_nm_get_info(router,i)))
340     continue;
341    
342     if (bay->dev_type) {
343     fprintf(fd,"c3745 add_nm_binding %s %u %s\n",
344     vm->name,i,bay->dev_type);
345     }
346    
347     for(nb=bay->nio_list;nb;nb=nb->next) {
348     fprintf(fd,"c3745 add_nio_binding %s %u %u %s\n",
349     vm->name,i,nb->port_id,nb->nio->name);
350     }
351     }
352    
353     fprintf(fd,"\n");
354     }
355    
356     /* Save configurations of all C3745 instances */
357     static void c3745_reg_save_config(registry_entry_t *entry,void *opt,int *err)
358     {
359     vm_instance_t *vm = entry->data;
360     c3745_t *router = VM_C3745(vm);
361    
362     if (vm->type == VM_TYPE_C3745)
363     c3745_save_config(router,(FILE *)opt);
364     }
365    
366     void c3745_save_config_all(FILE *fd)
367     {
368     registry_foreach_type(OBJ_TYPE_VM,c3745_reg_save_config,fd,NULL);
369     }
370    
371     /* Set NM EEPROM definition */
372     int c3745_nm_set_eeprom(c3745_t *router,u_int nm_bay,
373     const struct cisco_eeprom *eeprom)
374     {
375     if (!nm_bay || (nm_bay >= C3745_MAX_NM_BAYS)) {
376     vm_error(router->vm,"c3745_nm_set_eeprom: invalid NM Bay %u.\n",nm_bay);
377     return(-1);
378     }
379    
380     if (cisco_eeprom_copy(&router->nm_bay[nm_bay].eeprom,eeprom) == -1) {
381     vm_error(router->vm,"c3745_nm_set_eeprom: no memory.\n");
382     return(-1);
383     }
384    
385     return(0);
386     }
387    
388     /* Unset NM EEPROM definition (empty bay) */
389     int c3745_nm_unset_eeprom(c3745_t *router,u_int nm_bay)
390     {
391     if (!nm_bay || (nm_bay >= C3745_MAX_NM_BAYS)) {
392     vm_error(router->vm,"c3745_nm_set_eeprom: invalid NM Bay %u.\n",nm_bay);
393     return(-1);
394     }
395    
396     cisco_eeprom_free(&router->nm_bay[nm_bay].eeprom);
397     return(0);
398     }
399    
400     /* Check if a bay has a port adapter */
401     int c3745_nm_check_eeprom(c3745_t *router,u_int nm_bay)
402     {
403     if (!nm_bay || (nm_bay >= C3745_MAX_NM_BAYS))
404     return(FALSE);
405    
406     return(cisco_eeprom_valid(&router->nm_bay[nm_bay].eeprom));
407     }
408    
409     /* Get bay info */
410     struct c3745_nm_bay *c3745_nm_get_info(c3745_t *router,u_int nm_bay)
411     {
412     if (nm_bay >= C3745_MAX_NM_BAYS)
413     return NULL;
414    
415     return(&router->nm_bay[nm_bay]);
416     }
417    
418     /* Get NM type */
419     char *c3745_nm_get_type(c3745_t *router,u_int nm_bay)
420     {
421     struct c3745_nm_bay *bay;
422    
423     bay = c3745_nm_get_info(router,nm_bay);
424     return((bay != NULL) ? bay->dev_type : NULL);
425     }
426    
427     /* Get driver info about the specified slot */
428     void *c3745_nm_get_drvinfo(c3745_t *router,u_int nm_bay)
429     {
430     struct c3745_nm_bay *bay;
431    
432     bay = c3745_nm_get_info(router,nm_bay);
433     return((bay != NULL) ? bay->drv_info : NULL);
434     }
435    
436     /* Set driver info for the specified slot */
437     int c3745_nm_set_drvinfo(c3745_t *router,u_int nm_bay,void *drv_info)
438     {
439     struct c3745_nm_bay *bay;
440    
441     if (!(bay = c3745_nm_get_info(router,nm_bay)))
442     return(-1);
443    
444     bay->drv_info = drv_info;
445     return(0);
446     }
447    
448     /* Get a NM driver */
449     static struct c3745_nm_driver *c3745_nm_get_driver(char *dev_type)
450     {
451     int i;
452    
453     for(i=0;nm_drivers[i];i++)
454     if (!strcmp(nm_drivers[i]->dev_type,dev_type))
455     return nm_drivers[i];
456    
457     return NULL;
458     }
459    
460     /* Add a NM binding */
461     int c3745_nm_add_binding(c3745_t *router,char *dev_type,u_int nm_bay)
462     {
463     struct c3745_nm_driver *nm_driver;
464     struct c3745_nm_bay *bay;
465    
466     if (!(bay = c3745_nm_get_info(router,nm_bay)))
467     return(-1);
468    
469     /* check that this bay is empty */
470     if (bay->dev_type != NULL) {
471     vm_error(router->vm,"a NM already exists in slot %u.\n",nm_bay);
472     return(-1);
473     }
474    
475     /* find the NM driver */
476     if (!(nm_driver = c3745_nm_get_driver(dev_type))) {
477     vm_error(router->vm,"unknown NM type '%s'.\n",dev_type);
478     return(-1);
479     }
480    
481     bay->dev_type = nm_driver->dev_type;
482     bay->nm_driver = nm_driver;
483     return(0);
484     }
485    
486     /* Remove a NM binding */
487     int c3745_nm_remove_binding(c3745_t *router,u_int nm_bay)
488     {
489     struct c3745_nm_bay *bay;
490    
491     if (!(bay = c3745_nm_get_info(router,nm_bay)))
492     return(-1);
493    
494     /* stop if this bay is still active */
495     if (bay->drv_info != NULL) {
496     vm_error(router->vm,"slot %u still active.\n",nm_bay);
497     return(-1);
498     }
499    
500     /* check that this bay is not empty */
501     if (bay->dev_type == NULL) {
502     vm_error(router->vm,"slot %u is empty.\n",nm_bay);
503     return(-1);
504     }
505    
506     /* remove all NIOs bindings */
507     c3745_nm_remove_all_nio_bindings(router,nm_bay);
508    
509     bay->dev_type = NULL;
510     bay->nm_driver = NULL;
511     return(0);
512     }
513    
514     /* Find a NIO binding */
515     struct c3745_nio_binding *
516     c3745_nm_find_nio_binding(c3745_t *router,u_int nm_bay,u_int port_id)
517     {
518     struct c3745_nio_binding *nb;
519     struct c3745_nm_bay *bay;
520    
521     if (!(bay = c3745_nm_get_info(router,nm_bay)))
522     return NULL;
523    
524     for(nb=bay->nio_list;nb;nb=nb->next)
525     if (nb->port_id == port_id)
526     return nb;
527    
528     return NULL;
529     }
530    
531     /* Add a network IO binding */
532     int c3745_nm_add_nio_binding(c3745_t *router,u_int nm_bay,u_int port_id,
533     char *nio_name)
534     {
535     struct c3745_nio_binding *nb;
536     struct c3745_nm_bay *bay;
537     netio_desc_t *nio;
538    
539     if (!(bay = c3745_nm_get_info(router,nm_bay)))
540     return(-1);
541    
542     /* check that a NIO is not already bound to this port */
543     if (c3745_nm_find_nio_binding(router,nm_bay,port_id) != NULL) {
544     vm_error(router->vm,"a NIO already exists for interface %u/%u.\n",
545     nm_bay,port_id);
546     return(-1);
547     }
548    
549     /* acquire a reference on the NIO object */
550     if (!(nio = netio_acquire(nio_name))) {
551     vm_error(router->vm,"unable to find NIO '%s'.\n",nio_name);
552     return(-1);
553     }
554    
555     /* create a new binding */
556     if (!(nb = malloc(sizeof(*nb)))) {
557     vm_error(router->vm,"unable to create NIO binding "
558     "for interface %u/%u.\n",nm_bay,port_id);
559     netio_release(nio_name);
560     return(-1);
561     }
562    
563     memset(nb,0,sizeof(*nb));
564     nb->nio = nio;
565     nb->port_id = port_id;
566     nb->next = bay->nio_list;
567     if (nb->next) nb->next->prev = nb;
568     bay->nio_list = nb;
569     return(0);
570     }
571    
572     /* Remove a NIO binding */
573     int c3745_nm_remove_nio_binding(c3745_t *router,u_int nm_bay,u_int port_id)
574     {
575     struct c3745_nio_binding *nb;
576     struct c3745_nm_bay *bay;
577    
578     if (!(bay = c3745_nm_get_info(router,nm_bay)))
579     return(-1);
580    
581     if (!(nb = c3745_nm_find_nio_binding(router,nm_bay,port_id)))
582     return(-1); /* no nio binding for this slot/port */
583    
584     /* tell the NM driver to stop using this NIO */
585     if (bay->nm_driver)
586     bay->nm_driver->nm_unset_nio(router,nm_bay,port_id);
587    
588     /* remove this entry from the double linked list */
589     if (nb->next)
590     nb->next->prev = nb->prev;
591    
592     if (nb->prev) {
593     nb->prev->next = nb->next;
594     } else {
595     bay->nio_list = nb->next;
596     }
597    
598     /* unreference NIO object */
599     netio_release(nb->nio->name);
600     free(nb);
601     return(0);
602     }
603    
604     /* Remove all NIO bindings for the specified NM */
605     int c3745_nm_remove_all_nio_bindings(c3745_t *router,u_int nm_bay)
606     {
607     struct c3745_nio_binding *nb,*next;
608     struct c3745_nm_bay *bay;
609    
610     if (!(bay = c3745_nm_get_info(router,nm_bay)))
611     return(-1);
612    
613     for(nb=bay->nio_list;nb;nb=next) {
614     next = nb->next;
615    
616     /* tell the NM driver to stop using this NIO */
617     if (bay->nm_driver)
618     bay->nm_driver->nm_unset_nio(router,nm_bay,nb->port_id);
619    
620     /* unreference NIO object */
621     netio_release(nb->nio->name);
622     free(nb);
623     }
624    
625     bay->nio_list = NULL;
626     return(0);
627     }
628    
629     /* Enable a Network IO descriptor for a Network Module */
630     int c3745_nm_enable_nio(c3745_t *router,u_int nm_bay,u_int port_id)
631     {
632     struct c3745_nio_binding *nb;
633     struct c3745_nm_bay *bay;
634    
635     if (!(bay = c3745_nm_get_info(router,nm_bay)))
636     return(-1);
637    
638     /* check that we have an NIO binding for this interface */
639     if (!(nb = c3745_nm_find_nio_binding(router,nm_bay,port_id)))
640     return(-1);
641    
642     /* check that the driver is defined and successfully initialized */
643     if (!bay->nm_driver || !bay->drv_info)
644     return(-1);
645    
646     return(bay->nm_driver->nm_set_nio(router,nm_bay,port_id,nb->nio));
647     }
648    
649     /* Disable Network IO descriptor of a Network Module */
650     int c3745_nm_disable_nio(c3745_t *router,u_int nm_bay,u_int port_id)
651     {
652     struct c3745_nm_bay *bay;
653    
654     if (!(bay = c3745_nm_get_info(router,nm_bay)))
655     return(-1);
656    
657     /* check that the driver is defined and successfully initialized */
658     if (!bay->nm_driver || !bay->drv_info)
659     return(-1);
660    
661     return(bay->nm_driver->nm_unset_nio(router,nm_bay,port_id));
662     }
663    
664     /* Enable all NIO of the specified NM */
665     int c3745_nm_enable_all_nio(c3745_t *router,u_int nm_bay)
666     {
667     struct c3745_nio_binding *nb;
668     struct c3745_nm_bay *bay;
669    
670     if (!(bay = c3745_nm_get_info(router,nm_bay)))
671     return(-1);
672    
673     /* check that the driver is defined and successfully initialized */
674     if (!bay->nm_driver || !bay->drv_info)
675     return(-1);
676    
677     for(nb=bay->nio_list;nb;nb=nb->next)
678     bay->nm_driver->nm_set_nio(router,nm_bay,nb->port_id,nb->nio);
679    
680     return(0);
681     }
682    
683     /* Disable all NIO of the specified NM */
684     int c3745_nm_disable_all_nio(c3745_t *router,u_int nm_bay)
685     {
686     struct c3745_nio_binding *nb;
687     struct c3745_nm_bay *bay;
688    
689     if (!(bay = c3745_nm_get_info(router,nm_bay)))
690     return(-1);
691    
692     /* check that the driver is defined and successfully initialized */
693     if (!bay->nm_driver || !bay->drv_info)
694     return(-1);
695    
696     for(nb=bay->nio_list;nb;nb=nb->next)
697     bay->nm_driver->nm_unset_nio(router,nm_bay,nb->port_id);
698    
699     return(0);
700     }
701    
702     /* Initialize a Network Module */
703     int c3745_nm_init(c3745_t *router,u_int nm_bay)
704     {
705     struct c3745_nm_bay *bay;
706     size_t len;
707    
708     if (!(bay = c3745_nm_get_info(router,nm_bay)))
709     return(-1);
710    
711     /* Check that a device type is defined for this bay */
712     if (!bay->dev_type || !bay->nm_driver) {
713     vm_error(router->vm,"trying to init empty slot %u.\n",nm_bay);
714     return(-1);
715     }
716    
717     /* Allocate device name */
718     len = strlen(bay->dev_type) + 10;
719     if (!(bay->dev_name = malloc(len))) {
720     vm_error(router->vm,"unable to allocate device name.\n");
721     return(-1);
722     }
723    
724     snprintf(bay->dev_name,len,"%s(%u)",bay->dev_type,nm_bay);
725    
726     /* Initialize NM driver */
727     if (bay->nm_driver->nm_init(router,bay->dev_name,nm_bay) == 1) {
728     vm_error(router->vm,"unable to initialize NM %u.\n",nm_bay);
729     return(-1);
730     }
731    
732     /* Enable all NIO */
733     c3745_nm_enable_all_nio(router,nm_bay);
734     return(0);
735     }
736    
737     /* Shutdown a Network Module */
738     int c3745_nm_shutdown(c3745_t *router,u_int nm_bay)
739     {
740     struct c3745_nm_bay *bay;
741    
742     if (!(bay = c3745_nm_get_info(router,nm_bay)))
743     return(-1);
744    
745     /* Check that a device type is defined for this bay */
746     if (!bay->dev_type || !bay->nm_driver) {
747     vm_error(router->vm,"trying to shut down empty slot %u.\n",nm_bay);
748     return(-1);
749     }
750    
751     /* Disable all NIO */
752     c3745_nm_disable_all_nio(router,nm_bay);
753    
754     /* Shutdown the NM driver */
755     if (bay->drv_info && (bay->nm_driver->nm_shutdown(router,nm_bay) == -1)) {
756     vm_error(router->vm,"unable to shutdown NM %u.\n",nm_bay);
757     return(-1);
758     }
759    
760     free(bay->dev_name);
761     bay->dev_name = NULL;
762     bay->drv_info = NULL;
763     return(0);
764     }
765    
766     /* Shutdown all NM of a router */
767     int c3745_nm_shutdown_all(c3745_t *router)
768     {
769     int i;
770    
771     for(i=0;i<C3745_MAX_NM_BAYS;i++) {
772     if (!router->nm_bay[i].dev_type)
773     continue;
774    
775     c3745_nm_shutdown(router,i);
776     }
777    
778     return(0);
779     }
780    
781     /* Show info about all NMs */
782     int c3745_nm_show_all_info(c3745_t *router)
783     {
784     struct c3745_nm_bay *bay;
785     int i;
786    
787     for(i=0;i<C3745_MAX_NM_BAYS;i++) {
788     if (!(bay = c3745_nm_get_info(router,i)) || !bay->nm_driver)
789     continue;
790    
791     if (bay->nm_driver->nm_show_info != NULL)
792     bay->nm_driver->nm_show_info(router,i);
793     }
794    
795     return(0);
796     }
797    
798     /* Maximum number of tokens in a NM description */
799     #define NM_DESC_MAX_TOKENS 8
800    
801     /* Create a Network Module (command line) */
802     int c3745_cmd_nm_create(c3745_t *router,char *str)
803     {
804     char *tokens[NM_DESC_MAX_TOKENS];
805     int i,count,res;
806     u_int nm_bay;
807    
808     /* A port adapter description is like "1:NM-1FE" */
809     if ((count = m_strsplit(str,':',tokens,NM_DESC_MAX_TOKENS)) != 2) {
810     vm_error(router->vm,"unable to parse NM description '%s'.\n",str);
811     return(-1);
812     }
813    
814     /* Parse the NM bay id */
815     nm_bay = atoi(tokens[0]);
816    
817     /* Add this new NM to the current NM list */
818     res = c3745_nm_add_binding(router,tokens[1],nm_bay);
819    
820     /* The complete array was cleaned by strsplit */
821     for(i=0;i<NM_DESC_MAX_TOKENS;i++)
822     free(tokens[i]);
823    
824     return(res);
825     }
826    
827     /* Add a Network IO descriptor binding (command line) */
828     int c3745_cmd_add_nio(c3745_t *router,char *str)
829     {
830     char *tokens[NM_DESC_MAX_TOKENS];
831     int i,count,nio_type,res=-1;
832     u_int nm_bay,port_id;
833     netio_desc_t *nio;
834     char nio_name[128];
835    
836     /* A port adapter description is like "1:3:tap:tap0" */
837     if ((count = m_strsplit(str,':',tokens,NM_DESC_MAX_TOKENS)) < 3) {
838     vm_error(router->vm,"unable to parse NIO description '%s'.\n",str);
839     return(-1);
840     }
841    
842     /* Parse the NM bay */
843     nm_bay = atoi(tokens[0]);
844    
845     /* Parse the NM port id */
846     port_id = atoi(tokens[1]);
847    
848     /* Autogenerate a NIO name */
849     snprintf(nio_name,sizeof(nio_name),"c3745-i%u/%u/%u",
850     router->vm->instance_id,nm_bay,port_id);
851    
852     /* Create the Network IO descriptor */
853     nio = NULL;
854     nio_type = netio_get_type(tokens[2]);
855    
856     switch(nio_type) {
857     case NETIO_TYPE_UNIX:
858     if (count != 5) {
859     vm_error(router->vm,
860     "invalid number of arguments for UNIX NIO '%s'\n",str);
861     goto done;
862     }
863    
864     nio = netio_desc_create_unix(nio_name,tokens[3],tokens[4]);
865     break;
866    
867     case NETIO_TYPE_VDE:
868     if (count != 5) {
869     vm_error(router->vm,
870     "invalid number of arguments for VDE NIO '%s'\n",str);
871     goto done;
872     }
873    
874     nio = netio_desc_create_vde(nio_name,tokens[3],tokens[4]);
875     break;
876    
877     case NETIO_TYPE_TAP:
878     if (count != 4) {
879     vm_error(router->vm,
880     "invalid number of arguments for TAP NIO '%s'\n",str);
881     goto done;
882     }
883    
884     nio = netio_desc_create_tap(nio_name,tokens[3]);
885     break;
886    
887     case NETIO_TYPE_UDP:
888     if (count != 6) {
889     vm_error(router->vm,
890     "invalid number of arguments for UDP NIO '%s'\n",str);
891     goto done;
892     }
893    
894     nio = netio_desc_create_udp(nio_name,atoi(tokens[3]),
895     tokens[4],atoi(tokens[5]));
896     break;
897    
898     case NETIO_TYPE_TCP_CLI:
899     if (count != 5) {
900     vm_error(router->vm,
901     "invalid number of arguments for TCP CLI NIO '%s'\n",str);
902     goto done;
903     }
904    
905     nio = netio_desc_create_tcp_cli(nio_name,tokens[3],tokens[4]);
906     break;
907    
908     case NETIO_TYPE_TCP_SER:
909     if (count != 4) {
910     vm_error(router->vm,
911     "invalid number of arguments for TCP SER NIO '%s'\n",str);
912     goto done;
913     }
914    
915     nio = netio_desc_create_tcp_ser(nio_name,tokens[3]);
916     break;
917    
918     case NETIO_TYPE_NULL:
919     nio = netio_desc_create_null(nio_name);
920     break;
921    
922     #ifdef LINUX_ETH
923     case NETIO_TYPE_LINUX_ETH:
924     if (count != 4) {
925     vm_error(router->vm,
926     "invalid number of arguments for Linux Eth NIO '%s'\n",
927     str);
928     goto done;
929     }
930    
931     nio = netio_desc_create_lnxeth(nio_name,tokens[3]);
932     break;
933     #endif
934    
935     #ifdef GEN_ETH
936     case NETIO_TYPE_GEN_ETH:
937     if (count != 4) {
938     vm_error(router->vm,
939     "invalid number of arguments for Generic Eth NIO '%s'\n",
940     str);
941     goto done;
942     }
943    
944     nio = netio_desc_create_geneth(nio_name,tokens[3]);
945     break;
946     #endif
947    
948     default:
949     vm_error(router->vm,"unknown NETIO type '%s'\n",tokens[2]);
950     goto done;
951     }
952    
953     if (!nio) {
954     vm_error(router->vm,"unable to create NETIO "
955     "descriptor for NM slot %u\n",nm_bay);
956     goto done;
957     }
958    
959     if (c3745_nm_add_nio_binding(router,nm_bay,port_id,nio_name) == -1) {
960     vm_error(router->vm,"unable to add NETIO binding for slot %u\n",nm_bay);
961     netio_release(nio_name);
962     netio_delete(nio_name);
963     goto done;
964     }
965    
966     netio_release(nio_name);
967     res = 0;
968    
969     done:
970     /* The complete array was cleaned by strsplit */
971     for(i=0;i<NM_DESC_MAX_TOKENS;i++)
972     free(tokens[i]);
973    
974     return(res);
975     }
976    
977     /* Show the list of available NM drivers */
978     void c3745_nm_show_drivers(void)
979     {
980     int i;
981    
982     printf("Available C3745 Network Module drivers:\n");
983    
984     for(i=0;nm_drivers[i];i++) {
985     printf(" * %s %s\n",
986     nm_drivers[i]->dev_type,
987     !nm_drivers[i]->supported ? "(NOT WORKING)" : "");
988     }
989    
990     printf("\n");
991     }
992    
993     /* Set the base MAC address of the chassis */
994     static int c3745_burn_mac_addr(c3745_t *router,n_eth_addr_t *addr)
995     {
996     m_uint8_t eeprom_ver;
997     size_t offset;
998    
999     /* Read EEPROM format version */
1000     cisco_eeprom_get_byte(&router->sys_eeprom[2],0,&eeprom_ver);
1001    
1002     switch(eeprom_ver) {
1003     case 0:
1004     cisco_eeprom_set_region(&router->sys_eeprom[2],2,
1005     addr->eth_addr_byte,6);
1006     break;
1007    
1008     case 4:
1009     if (!cisco_eeprom_v4_find_field(&router->sys_eeprom[2],
1010     0xC3,&offset)) {
1011     cisco_eeprom_set_region(&router->sys_eeprom[2],offset,
1012     addr->eth_addr_byte,6);
1013     }
1014     break;
1015    
1016     default:
1017     vm_error(router->vm,"c3745_burn_mac_addr: unable to handle "
1018     "EEPROM version %u\n",eeprom_ver);
1019     return(-1);
1020     }
1021    
1022     return(0);
1023     }
1024    
1025     /* Set chassis MAC address */
1026     int c3745_chassis_set_mac_addr(c3745_t *router,char *mac_addr)
1027     {
1028     if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) {
1029     vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr);
1030     return(-1);
1031     }
1032    
1033     /* Set the chassis base MAC address */
1034     c3745_burn_mac_addr(router,&router->mac_addr);
1035     return(0);
1036     }
1037    
1038     /* Create the two main PCI busses for a GT64120 based system */
1039     static int c3745_init_gt96100(c3745_t *router)
1040     {
1041     vm_instance_t *vm = router->vm;
1042    
1043     vm->pci_bus[0] = pci_bus_create("PCI bus #0",0);
1044     vm->pci_bus[1] = pci_bus_create("PCI bus #1",0);
1045    
1046     if (!vm->pci_bus[0] || !vm->pci_bus[1]) {
1047     vm_error(router->vm,"unable to create PCI data.\n");
1048     return(-1);
1049     }
1050    
1051     return(dev_gt96100_init(vm,"gt96100",C3745_GT96K_ADDR,0x200000,
1052     C3745_GT96K_IRQ,C3745_NETIO_IRQ));
1053     }
1054    
1055     /* Initialize a Cisco 3745 */
1056     static int c3745_init(c3745_t *router)
1057     {
1058     vm_instance_t *vm = router->vm;
1059     char bus_name[128];
1060     int i;
1061    
1062     /* Set the processor type: R7000 */
1063 dpavlin 7 mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R7000);
1064 dpavlin 4
1065     /* Initialize the Galileo GT-96100 PCI controller */
1066     if (c3745_init_gt96100(router) == -1)
1067     return(-1);
1068    
1069     /* Create the NM PCI busses for slots 1-4 */
1070     for(i=1;i<=4;i++) {
1071     snprintf(bus_name,sizeof(bus_name),"NM Slot %d",i);
1072     vm->pci_bus_pool[i] = pci_bus_create(bus_name,-1);
1073    
1074     /* Map the NM PCI bus */
1075     router->nm_bay[i].pci_map = vm->pci_bus_pool[i];
1076    
1077     /* Create the PCI bridge */
1078     dev_ti2050b_init(vm->pci_bus[1],i,router->nm_bay[i].pci_map);
1079     }
1080    
1081     vm->elf_machine_id = C3745_ELF_MACHINE_ID;
1082     return(0);
1083     }
1084    
1085     /* Show C3745 hardware info */
1086     void c3745_show_hardware(c3745_t *router)
1087     {
1088     vm_instance_t *vm = router->vm;
1089    
1090     printf("C3745 instance '%s' (id %d):\n",vm->name,vm->instance_id);
1091    
1092     printf(" VM Status : %d\n",vm->status);
1093     printf(" RAM size : %u Mb\n",vm->ram_size);
1094     printf(" NVRAM size : %u Kb\n",vm->nvram_size);
1095     printf(" IOS image : %s\n\n",vm->ios_image);
1096    
1097     if (vm->debug_level > 0) {
1098     dev_show_list(vm);
1099     pci_dev_show_list(vm->pci_bus[0]);
1100     pci_dev_show_list(vm->pci_bus[1]);
1101     printf("\n");
1102     }
1103     }
1104    
1105     /* Initialize default parameters for a C3745 */
1106     void c3745_init_defaults(c3745_t *router)
1107     {
1108     vm_instance_t *vm = router->vm;
1109     n_eth_addr_t *m;
1110     m_uint16_t pid;
1111    
1112     pid = (m_uint16_t)getpid();
1113    
1114     /* Generate a chassis MAC address based on the instance ID */
1115     m = &router->mac_addr;
1116     m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
1117     m->eth_addr_byte[1] = vm->instance_id & 0xFF;
1118     m->eth_addr_byte[2] = pid >> 8;
1119     m->eth_addr_byte[3] = pid & 0xFF;
1120     m->eth_addr_byte[4] = 0x00;
1121     m->eth_addr_byte[5] = 0x00;
1122    
1123     c3745_init_eeprom_groups(router);
1124     cisco_eeprom_copy(&router->sys_eeprom[0],&eeprom_c3745_motherboard);
1125     cisco_eeprom_copy(&router->sys_eeprom[1],&eeprom_c3745_ioboard);
1126     cisco_eeprom_copy(&router->sys_eeprom[2],&eeprom_c3745_midplane);
1127    
1128     c3745_burn_mac_addr(router,&router->mac_addr);
1129    
1130     vm->ram_mmap = C3745_DEFAULT_RAM_MMAP;
1131     vm->ram_size = C3745_DEFAULT_RAM_SIZE;
1132     vm->rom_size = C3745_DEFAULT_ROM_SIZE;
1133     vm->nvram_size = C3745_DEFAULT_NVRAM_SIZE;
1134     vm->conf_reg_setup = C3745_DEFAULT_CONF_REG;
1135     vm->clock_divisor = C3745_DEFAULT_CLOCK_DIV;
1136     vm->nvram_rom_space = C3745_NVRAM_ROM_RES_SIZE;
1137     router->nm_iomem_size = C3745_DEFAULT_IOMEM_SIZE;
1138    
1139     vm->pcmcia_disk_size[0] = C3745_DEFAULT_DISK0_SIZE;
1140     vm->pcmcia_disk_size[1] = C3745_DEFAULT_DISK1_SIZE;
1141    
1142     /* Enable NVRAM operations to load/store configs */
1143     vm->nvram_extract_config = c3745_nvram_extract_config;
1144     vm->nvram_push_config = c3745_nvram_push_config;
1145     }
1146    
1147     /* Initialize the C3745 Platform */
1148     int c3745_init_platform(c3745_t *router)
1149     {
1150     vm_instance_t *vm = router->vm;
1151     struct c3745_nm_bay *nm_bay;
1152     cpu_mips_t *cpu;
1153 dpavlin 7 cpu_gen_t *gen;
1154 dpavlin 4 vm_obj_t *obj;
1155     int i;
1156    
1157     /* Copy config register setup into "active" config register */
1158     vm->conf_reg = vm->conf_reg_setup;
1159    
1160     /* Create Console and AUX ports */
1161     vm_init_vtty(vm);
1162    
1163     /* Create a CPU group */
1164     vm->cpu_group = cpu_group_create("System CPU");
1165    
1166     /* Initialize the virtual MIPS processor */
1167 dpavlin 7 if (!(gen = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
1168 dpavlin 4 vm_error(vm,"unable to create CPU!\n");
1169     return(-1);
1170     }
1171    
1172 dpavlin 7 cpu = CPU_MIPS64(gen);
1173    
1174 dpavlin 4 /* Add this CPU to the system CPU group */
1175 dpavlin 7 cpu_group_add(vm->cpu_group,gen);
1176     vm->boot_cpu = gen;
1177 dpavlin 4
1178 dpavlin 7 /* Initialize the IRQ routing vectors */
1179     vm->set_irq = mips64_vm_set_irq;
1180     vm->clear_irq = mips64_vm_clear_irq;
1181    
1182 dpavlin 4 /* Mark the Network IO interrupt as high priority */
1183     cpu->irq_idle_preempt[C3745_NETIO_IRQ] = TRUE;
1184     cpu->irq_idle_preempt[C3745_GT96K_IRQ] = TRUE;
1185     cpu->irq_idle_preempt[C3745_DUART_IRQ] = TRUE;
1186    
1187     /* Copy some parameters from VM to CPU (idle PC, ...) */
1188     cpu->idle_pc = vm->idle_pc;
1189    
1190     if (vm->timer_irq_check_itv)
1191     cpu->timer_irq_check_itv = vm->timer_irq_check_itv;
1192    
1193     /* Remote emulator control */
1194     dev_remote_control_init(vm,0x16000000,0x1000);
1195    
1196     /* Specific Storage Area (SSA) */
1197 dpavlin 7 dev_ram_init(vm,"ssa",TRUE,FALSE,NULL,FALSE,0x16001000ULL,0x7000);
1198 dpavlin 4
1199     /* IO FPGA */
1200     if (dev_c3745_iofpga_init(router,C3745_IOFPGA_ADDR,0x200000) == -1)
1201     return(-1);
1202    
1203     #if 0
1204     /* PCI IO space */
1205     if (!(vm->pci_io_space = pci_io_data_init(vm,C3745_PCI_IO_ADDR)))
1206     return(-1);
1207     #endif
1208    
1209     /* Initialize the chassis */
1210     if (c3745_init(router) == -1)
1211     return(-1);
1212    
1213     /* Initialize RAM */
1214     vm_ram_init(vm,0x00000000ULL);
1215    
1216     /* Initialize ROM (as a Flash) */
1217     if (!(obj = dev_flash_init(vm,"rom",C3745_ROM_ADDR,vm->rom_size*1048576)))
1218     return(-1);
1219    
1220 dpavlin 7 dev_flash_copy_data(obj,0,mips64_microcode,mips64_microcode_len);
1221 dpavlin 4 c3745_nvram_check_empty_config(vm);
1222    
1223     /* Initialize the NS16552 DUART */
1224     dev_ns16552_init(vm,C3745_DUART_ADDR,0x1000,3,C3745_DUART_IRQ,
1225     vm->vtty_con,vm->vtty_aux);
1226    
1227     /* PCMCIA Slot 0 */
1228     dev_pcmcia_disk_init(vm,"slot0",C3745_SLOT0_ADDR,0x200000,
1229     vm->pcmcia_disk_size[0],1);
1230    
1231     /* PCMCIA Slot 1 */
1232     dev_pcmcia_disk_init(vm,"slot1",C3745_SLOT1_ADDR,0x200000,
1233     vm->pcmcia_disk_size[1],1);
1234    
1235     /* The GT96100 system controller has 2 integrated FastEthernet ports */
1236     c3745_nm_add_binding(router,"GT96100-FE",0);
1237    
1238     /* Initialize Network Modules */
1239     for(i=0;i<C3745_MAX_NM_BAYS;i++) {
1240     nm_bay = &router->nm_bay[i];
1241    
1242     if (!nm_bay->dev_type)
1243     continue;
1244    
1245     if (c3745_nm_init(router,i) == -1) {
1246     vm_error(vm,"unable to create Network Module \"%s\"\n",
1247     nm_bay->dev_type);
1248     return(-1);
1249     }
1250     }
1251    
1252     /* Show device list */
1253     c3745_show_hardware(router);
1254     return(0);
1255     }
1256    
1257     /* Boot the IOS image */
1258     int c3745_boot_ios(c3745_t *router)
1259     {
1260     vm_instance_t *vm = router->vm;
1261 dpavlin 7 cpu_mips_t *cpu;
1262 dpavlin 4
1263     if (!vm->boot_cpu)
1264     return(-1);
1265    
1266     /* Suspend CPU activity since we will restart directly from ROM */
1267     vm_suspend(vm);
1268    
1269     /* Check that CPU activity is really suspended */
1270     if (cpu_group_sync_state(vm->cpu_group) == -1) {
1271     vm_error(vm,"unable to sync with system CPUs.\n");
1272     return(-1);
1273     }
1274    
1275     /* Reset the boot CPU */
1276 dpavlin 7 cpu = CPU_MIPS64(vm->boot_cpu);
1277     mips64_reset(cpu);
1278 dpavlin 4
1279     /* Load IOS image */
1280 dpavlin 7 if (mips64_load_elf_image(cpu,vm->ios_image,
1281 dpavlin 4 (vm->ghost_status == VM_GHOST_RAM_USE),
1282     &vm->ios_entry_point) < 0)
1283     {
1284     vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
1285     return(-1);
1286     }
1287    
1288     /* Launch the simulation */
1289     printf("\nC3745 '%s': starting simulation (CPU0 PC=0x%llx), "
1290     "JIT %sabled.\n",
1291 dpavlin 7 vm->name,cpu->pc,vm->jit_use ? "en":"dis");
1292 dpavlin 4
1293     vm_log(vm,"C3745_BOOT",
1294     "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
1295 dpavlin 7 cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
1296 dpavlin 4
1297     /* Start main CPU */
1298     if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
1299     vm->status = VM_STATUS_RUNNING;
1300     cpu_start(vm->boot_cpu);
1301     } else {
1302     vm->status = VM_STATUS_SHUTDOWN;
1303     }
1304     return(0);
1305     }
1306    
1307     /* Initialize a Cisco 3745 instance */
1308     int c3745_init_instance(c3745_t *router)
1309     {
1310     vm_instance_t *vm = router->vm;
1311     m_uint32_t rom_entry_point;
1312     cpu_mips_t *cpu0;
1313    
1314     if (!vm->ios_image) {
1315     vm_error(vm,"no Cisco IOS image defined.");
1316     return(-1);
1317     }
1318    
1319     /* Initialize the C3745 platform */
1320     if (c3745_init_platform(router) == -1) {
1321     vm_error(vm,"unable to initialize the platform hardware.\n");
1322     return(-1);
1323     }
1324    
1325     /* Load IOS configuration file */
1326     if (vm->ios_config != NULL) {
1327     vm_nvram_push_config(vm,vm->ios_config);
1328     vm->conf_reg &= ~0x40;
1329     }
1330    
1331     /* Load ROM (ELF image or embedded) */
1332 dpavlin 7 cpu0 = CPU_MIPS64(vm->boot_cpu);
1333 dpavlin 4 rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
1334    
1335     if ((vm->rom_filename != NULL) &&
1336     (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
1337     {
1338     vm_error(vm,"unable to load alternate ROM '%s', "
1339     "fallback to embedded ROM.\n\n",vm->rom_filename);
1340     vm->rom_filename = NULL;
1341     }
1342    
1343     /* Load symbol file */
1344     if (vm->sym_filename) {
1345     mips64_sym_load_file(cpu0,vm->sym_filename);
1346     cpu0->sym_trace = 1;
1347     }
1348    
1349     return(c3745_boot_ios(router));
1350     }
1351    
1352     /* Stop a Cisco 3745 instance */
1353     int c3745_stop_instance(c3745_t *router)
1354     {
1355     vm_instance_t *vm = router->vm;
1356    
1357     printf("\nC3745 '%s': stopping simulation.\n",vm->name);
1358     vm_log(vm,"C3745_STOP","stopping simulation.\n");
1359    
1360     /* Stop all CPUs */
1361     if (vm->cpu_group != NULL) {
1362     vm_stop(vm);
1363    
1364     if (cpu_group_sync_state(vm->cpu_group) == -1) {
1365     vm_error(vm,"unable to sync with system CPUs.\n");
1366     return(-1);
1367     }
1368     }
1369    
1370     /* Free resources that were used during execution to emulate hardware */
1371     c3745_nm_shutdown_all(router);
1372     vm_hardware_shutdown(vm);
1373     return(0);
1374     }

  ViewVC Help
Powered by ViewVC 1.1.26