/[dynamips]/upstream/dynamips-0.2.6-RC5/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.6-RC5/dev_c3745.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (hide annotations)
Sat Oct 6 16:06:49 2007 UTC (14 years, 9 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.6-RC3/dev_c3745.c
File MIME type: text/plain
File size: 37281 byte(s)
dynamips-0.2.6-RC3

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

  ViewVC Help
Powered by ViewVC 1.1.26