/[dynamips]/upstream/dynamips-0.2.7-RC2/dev_c2691.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

Contents of /upstream/dynamips-0.2.7-RC2/dev_c2691.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 8 - (show annotations)
Sat Oct 6 16:24:54 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 37047 byte(s)
dynamips-0.2.7-RC2

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

  ViewVC Help
Powered by ViewVC 1.1.26