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

Contents of /trunk/dev_c3725.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (show annotations)
Sat Oct 6 16:26:06 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7-RC3/dev_c3725.c
File MIME type: text/plain
File size: 37408 byte(s)
dynamips-0.2.7-RC3

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4 *
5 * Generic Cisco 3725 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_c3725.h"
25 #include "dev_c3725_iofpga.h"
26 #include "dev_vtty.h"
27 #include "registry.h"
28
29 /* ======================================================================== */
30 /* EEPROM definitions */
31 /* ======================================================================== */
32
33 /* Cisco 3725 mainboard EEPROM */
34 static m_uint16_t eeprom_c3725_mainboard_data[] = {
35 0x04FF, 0xC18B, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0x5809,
36 0x6140, 0x0259, 0xC046, 0x0320, 0x003F, 0x1302, 0x4244, 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, 0x1319, 0x5C6F,
40 0x7043, 0x0030, 0xC508, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x4100,
41 0x0101, 0x02FF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
42 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
43 };
44
45 struct cisco_eeprom eeprom_c3725_mainboard = {
46 "C3725 Backplane",
47 eeprom_c3725_mainboard_data,
48 sizeof(eeprom_c3725_mainboard_data)/2,
49 };
50
51 /* ======================================================================== */
52 /* Network Module Drivers */
53 /* ======================================================================== */
54 static struct c3725_nm_driver *nm_drivers[] = {
55 &dev_c3725_nm_1fe_tx_driver,
56 &dev_c3725_nm_16esw_driver,
57 &dev_c3725_gt96100_fe_driver,
58 &dev_c3725_nm_4t_driver,
59 NULL,
60 };
61
62 /* ======================================================================== */
63 /* Cisco 3725 router instances */
64 /* ======================================================================== */
65
66 /* Directly extract the configuration from the NVRAM device */
67 ssize_t c3725_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 + C3725_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 c3725_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 = C3725_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 c3725_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 + C3725_NVRAM_OFFSET;
168
169 /* Normal config */
170 c3725_nvram_push_config_part(vm,buffer,len,ios_ptr);
171
172 /* Backup config */
173 c3725_nvram_push_config_part(vm,buffer,len,ios_ptr + C3725_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 c3725_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 + C3725_NVRAM_OFFSET;
190 len = C3725_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 c3725_t *c3725_create_instance(char *name,int instance_id)
208 {
209 c3725_t *router;
210
211 if (!(router = malloc(sizeof(*router)))) {
212 fprintf(stderr,"C3725 '%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_C3725))) {
219 fprintf(stderr,"C3725 '%s': unable to create VM instance!\n",name);
220 goto err_vm;
221 }
222
223 c3725_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 c3725_free_instance(void *data,void *arg)
234 {
235 vm_instance_t *vm = data;
236 c3725_t *router;
237 int i;
238
239 if (vm->type == VM_TYPE_C3725) {
240 router = VM_C3725(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<C3725_MAX_NM_BAYS;i++)
254 c3725_nm_remove_all_nio_bindings(router,i);
255
256 /* Shutdown all Network Modules */
257 c3725_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 c3725_delete_instance(char *name)
275 {
276 return(registry_delete_if_unused(name,OBJ_TYPE_VM,
277 c3725_free_instance,NULL));
278 }
279
280 /* Delete all router instances */
281 int c3725_delete_all_instances(void)
282 {
283 return(registry_delete_type(OBJ_TYPE_VM,c3725_free_instance,NULL));
284 }
285
286 /* Save configuration of a C3725 instance */
287 void c3725_save_config(c3725_t *router,FILE *fd)
288 {
289 vm_instance_t *vm = router->vm;
290 struct c3725_nio_binding *nb;
291 struct c3725_nm_bay *bay;
292 int i;
293
294 /* General settings */
295 fprintf(fd,"c3725 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<C3725_MAX_NM_BAYS;i++) {
302 if (!(bay = c3725_nm_get_info(router,i)))
303 continue;
304
305 if (bay->dev_type) {
306 fprintf(fd,"c3725 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,"c3725 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 C3725 instances */
320 static void c3725_reg_save_config(registry_entry_t *entry,void *opt,int *err)
321 {
322 vm_instance_t *vm = entry->data;
323 c3725_t *router = VM_C3725(vm);
324
325 if (vm->type == VM_TYPE_C3725)
326 c3725_save_config(router,(FILE *)opt);
327 }
328
329 void c3725_save_config_all(FILE *fd)
330 {
331 registry_foreach_type(OBJ_TYPE_VM,c3725_reg_save_config,fd,NULL);
332 }
333
334 /* Get slot/port corresponding to specified network IRQ */
335 static inline void
336 c3725_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port)
337 {
338 irq -= C3725_NETIO_IRQ_BASE;
339 *port = irq & C3725_NETIO_IRQ_PORT_MASK;
340 *slot = irq >> C3725_NETIO_IRQ_PORT_BITS;
341 }
342
343 /* Get network IRQ for specified slot/port */
344 u_int c3725_net_irq_for_slot_port(u_int slot,u_int port)
345 {
346 u_int irq;
347
348 irq = (slot << C3725_NETIO_IRQ_PORT_BITS) + port;
349 irq += C3725_NETIO_IRQ_BASE;
350
351 return(irq);
352 }
353
354 /* Get PCI device for the specified NM bay */
355 int c3725_nm_get_pci_device(u_int nm_bay)
356 {
357 switch(nm_bay) {
358 case 1:
359 return(0x06);
360 case 2:
361 return(0x0A);
362 default:
363 return(-1);
364 }
365 }
366
367 /* Set NM EEPROM definition */
368 int c3725_nm_set_eeprom(c3725_t *router,u_int nm_bay,
369 const struct cisco_eeprom *eeprom)
370 {
371 if (!nm_bay || (nm_bay >= C3725_MAX_NM_BAYS)) {
372 vm_error(router->vm,"c3725_nm_set_eeprom: invalid NM Bay %u.\n",nm_bay);
373 return(-1);
374 }
375
376 if (cisco_eeprom_copy(&router->nm_bay[nm_bay].eeprom,eeprom) == -1) {
377 vm_error(router->vm,"c3725_nm_set_eeprom: no memory.\n");
378 return(-1);
379 }
380
381 return(0);
382 }
383
384 /* Unset NM EEPROM definition (empty bay) */
385 int c3725_nm_unset_eeprom(c3725_t *router,u_int nm_bay)
386 {
387 if (!nm_bay || (nm_bay >= C3725_MAX_NM_BAYS)) {
388 vm_error(router->vm,"c3725_nm_set_eeprom: invalid NM Bay %u.\n",nm_bay);
389 return(-1);
390 }
391
392 cisco_eeprom_free(&router->nm_bay[nm_bay].eeprom);
393 return(0);
394 }
395
396 /* Check if a bay has a port adapter */
397 int c3725_nm_check_eeprom(c3725_t *router,u_int nm_bay)
398 {
399 if (!nm_bay || (nm_bay >= C3725_MAX_NM_BAYS))
400 return(FALSE);
401
402 return(cisco_eeprom_valid(&router->nm_bay[nm_bay].eeprom));
403 }
404
405 /* Get bay info */
406 struct c3725_nm_bay *c3725_nm_get_info(c3725_t *router,u_int nm_bay)
407 {
408 if (nm_bay >= C3725_MAX_NM_BAYS)
409 return NULL;
410
411 return(&router->nm_bay[nm_bay]);
412 }
413
414 /* Get NM type */
415 char *c3725_nm_get_type(c3725_t *router,u_int nm_bay)
416 {
417 struct c3725_nm_bay *bay;
418
419 bay = c3725_nm_get_info(router,nm_bay);
420 return((bay != NULL) ? bay->dev_type : NULL);
421 }
422
423 /* Get driver info about the specified slot */
424 void *c3725_nm_get_drvinfo(c3725_t *router,u_int nm_bay)
425 {
426 struct c3725_nm_bay *bay;
427
428 bay = c3725_nm_get_info(router,nm_bay);
429 return((bay != NULL) ? bay->drv_info : NULL);
430 }
431
432 /* Set driver info for the specified slot */
433 int c3725_nm_set_drvinfo(c3725_t *router,u_int nm_bay,void *drv_info)
434 {
435 struct c3725_nm_bay *bay;
436
437 if (!(bay = c3725_nm_get_info(router,nm_bay)))
438 return(-1);
439
440 bay->drv_info = drv_info;
441 return(0);
442 }
443
444 /* Get a NM driver */
445 static struct c3725_nm_driver *c3725_nm_get_driver(char *dev_type)
446 {
447 int i;
448
449 for(i=0;nm_drivers[i];i++)
450 if (!strcmp(nm_drivers[i]->dev_type,dev_type))
451 return nm_drivers[i];
452
453 return NULL;
454 }
455
456 /* Add a NM binding */
457 int c3725_nm_add_binding(c3725_t *router,char *dev_type,u_int nm_bay)
458 {
459 struct c3725_nm_driver *nm_driver;
460 struct c3725_nm_bay *bay;
461
462 if (!(bay = c3725_nm_get_info(router,nm_bay)))
463 return(-1);
464
465 /* check that this bay is empty */
466 if (bay->dev_type != NULL) {
467 vm_error(router->vm,"a NM already exists in slot %u.\n",nm_bay);
468 return(-1);
469 }
470
471 /* find the NM driver */
472 if (!(nm_driver = c3725_nm_get_driver(dev_type))) {
473 vm_error(router->vm,"unknown NM type '%s'.\n",dev_type);
474 return(-1);
475 }
476
477 bay->dev_type = nm_driver->dev_type;
478 bay->nm_driver = nm_driver;
479 return(0);
480 }
481
482 /* Remove a NM binding */
483 int c3725_nm_remove_binding(c3725_t *router,u_int nm_bay)
484 {
485 struct c3725_nm_bay *bay;
486
487 if (!(bay = c3725_nm_get_info(router,nm_bay)))
488 return(-1);
489
490 /* stop if this bay is still active */
491 if (bay->drv_info != NULL) {
492 vm_error(router->vm,"slot %u still active.\n",nm_bay);
493 return(-1);
494 }
495
496 /* check that this bay is not empty */
497 if (bay->dev_type == NULL) {
498 vm_error(router->vm,"slot %u is empty.\n",nm_bay);
499 return(-1);
500 }
501
502 /* remove all NIOs bindings */
503 c3725_nm_remove_all_nio_bindings(router,nm_bay);
504
505 bay->dev_type = NULL;
506 bay->nm_driver = NULL;
507 return(0);
508 }
509
510 /* Find a NIO binding */
511 struct c3725_nio_binding *
512 c3725_nm_find_nio_binding(c3725_t *router,u_int nm_bay,u_int port_id)
513 {
514 struct c3725_nio_binding *nb;
515 struct c3725_nm_bay *bay;
516
517 if (!(bay = c3725_nm_get_info(router,nm_bay)))
518 return NULL;
519
520 for(nb=bay->nio_list;nb;nb=nb->next)
521 if (nb->port_id == port_id)
522 return nb;
523
524 return NULL;
525 }
526
527 /* Add a network IO binding */
528 int c3725_nm_add_nio_binding(c3725_t *router,u_int nm_bay,u_int port_id,
529 char *nio_name)
530 {
531 struct c3725_nio_binding *nb;
532 struct c3725_nm_bay *bay;
533 netio_desc_t *nio;
534
535 if (!(bay = c3725_nm_get_info(router,nm_bay)))
536 return(-1);
537
538 /* check that a NIO is not already bound to this port */
539 if (c3725_nm_find_nio_binding(router,nm_bay,port_id) != NULL) {
540 vm_error(router->vm,"a NIO already exists for interface %u/%u.\n",
541 nm_bay,port_id);
542 return(-1);
543 }
544
545 /* acquire a reference on the NIO object */
546 if (!(nio = netio_acquire(nio_name))) {
547 vm_error(router->vm,"unable to find NIO '%s'.\n",nio_name);
548 return(-1);
549 }
550
551 /* create a new binding */
552 if (!(nb = malloc(sizeof(*nb)))) {
553 vm_error(router->vm,"unable to create NIO binding "
554 "for interface %u/%u.\n",nm_bay,port_id);
555 netio_release(nio_name);
556 return(-1);
557 }
558
559 memset(nb,0,sizeof(*nb));
560 nb->nio = nio;
561 nb->port_id = port_id;
562 nb->next = bay->nio_list;
563 if (nb->next) nb->next->prev = nb;
564 bay->nio_list = nb;
565 return(0);
566 }
567
568 /* Remove a NIO binding */
569 int c3725_nm_remove_nio_binding(c3725_t *router,u_int nm_bay,u_int port_id)
570 {
571 struct c3725_nio_binding *nb;
572 struct c3725_nm_bay *bay;
573
574 if (!(bay = c3725_nm_get_info(router,nm_bay)))
575 return(-1);
576
577 if (!(nb = c3725_nm_find_nio_binding(router,nm_bay,port_id)))
578 return(-1); /* no nio binding for this slot/port */
579
580 /* tell the NM driver to stop using this NIO */
581 if (bay->nm_driver)
582 bay->nm_driver->nm_unset_nio(router,nm_bay,port_id);
583
584 /* remove this entry from the double linked list */
585 if (nb->next)
586 nb->next->prev = nb->prev;
587
588 if (nb->prev) {
589 nb->prev->next = nb->next;
590 } else {
591 bay->nio_list = nb->next;
592 }
593
594 /* unreference NIO object */
595 netio_release(nb->nio->name);
596 free(nb);
597 return(0);
598 }
599
600 /* Remove all NIO bindings for the specified NM */
601 int c3725_nm_remove_all_nio_bindings(c3725_t *router,u_int nm_bay)
602 {
603 struct c3725_nio_binding *nb,*next;
604 struct c3725_nm_bay *bay;
605
606 if (!(bay = c3725_nm_get_info(router,nm_bay)))
607 return(-1);
608
609 for(nb=bay->nio_list;nb;nb=next) {
610 next = nb->next;
611
612 /* tell the NM driver to stop using this NIO */
613 if (bay->nm_driver)
614 bay->nm_driver->nm_unset_nio(router,nm_bay,nb->port_id);
615
616 /* unreference NIO object */
617 netio_release(nb->nio->name);
618 free(nb);
619 }
620
621 bay->nio_list = NULL;
622 return(0);
623 }
624
625 /* Enable a Network IO descriptor for a Network Module */
626 int c3725_nm_enable_nio(c3725_t *router,u_int nm_bay,u_int port_id)
627 {
628 struct c3725_nio_binding *nb;
629 struct c3725_nm_bay *bay;
630
631 if (!(bay = c3725_nm_get_info(router,nm_bay)))
632 return(-1);
633
634 /* check that we have an NIO binding for this interface */
635 if (!(nb = c3725_nm_find_nio_binding(router,nm_bay,port_id)))
636 return(-1);
637
638 /* check that the driver is defined and successfully initialized */
639 if (!bay->nm_driver || !bay->drv_info)
640 return(-1);
641
642 return(bay->nm_driver->nm_set_nio(router,nm_bay,port_id,nb->nio));
643 }
644
645 /* Disable Network IO descriptor of a Network Module */
646 int c3725_nm_disable_nio(c3725_t *router,u_int nm_bay,u_int port_id)
647 {
648 struct c3725_nm_bay *bay;
649
650 if (!(bay = c3725_nm_get_info(router,nm_bay)))
651 return(-1);
652
653 /* check that the driver is defined and successfully initialized */
654 if (!bay->nm_driver || !bay->drv_info)
655 return(-1);
656
657 return(bay->nm_driver->nm_unset_nio(router,nm_bay,port_id));
658 }
659
660 /* Enable all NIO of the specified NM */
661 int c3725_nm_enable_all_nio(c3725_t *router,u_int nm_bay)
662 {
663 struct c3725_nio_binding *nb;
664 struct c3725_nm_bay *bay;
665
666 if (!(bay = c3725_nm_get_info(router,nm_bay)))
667 return(-1);
668
669 /* check that the driver is defined and successfully initialized */
670 if (!bay->nm_driver || !bay->drv_info)
671 return(-1);
672
673 for(nb=bay->nio_list;nb;nb=nb->next)
674 bay->nm_driver->nm_set_nio(router,nm_bay,nb->port_id,nb->nio);
675
676 return(0);
677 }
678
679 /* Disable all NIO of the specified NM */
680 int c3725_nm_disable_all_nio(c3725_t *router,u_int nm_bay)
681 {
682 struct c3725_nio_binding *nb;
683 struct c3725_nm_bay *bay;
684
685 if (!(bay = c3725_nm_get_info(router,nm_bay)))
686 return(-1);
687
688 /* check that the driver is defined and successfully initialized */
689 if (!bay->nm_driver || !bay->drv_info)
690 return(-1);
691
692 for(nb=bay->nio_list;nb;nb=nb->next)
693 bay->nm_driver->nm_unset_nio(router,nm_bay,nb->port_id);
694
695 return(0);
696 }
697
698 /* Initialize a Network Module */
699 int c3725_nm_init(c3725_t *router,u_int nm_bay)
700 {
701 struct c3725_nm_bay *bay;
702 size_t len;
703
704 if (!(bay = c3725_nm_get_info(router,nm_bay)))
705 return(-1);
706
707 /* Check that a device type is defined for this bay */
708 if (!bay->dev_type || !bay->nm_driver) {
709 vm_error(router->vm,"trying to init empty slot %u.\n",nm_bay);
710 return(-1);
711 }
712
713 /* Allocate device name */
714 len = strlen(bay->dev_type) + 10;
715 if (!(bay->dev_name = malloc(len))) {
716 vm_error(router->vm,"unable to allocate device name.\n");
717 return(-1);
718 }
719
720 snprintf(bay->dev_name,len,"%s(%u)",bay->dev_type,nm_bay);
721
722 /* Initialize NM driver */
723 if (bay->nm_driver->nm_init(router,bay->dev_name,nm_bay) == -1) {
724 vm_error(router->vm,"unable to initialize NM %u.\n",nm_bay);
725 return(-1);
726 }
727
728 /* Enable all NIO */
729 c3725_nm_enable_all_nio(router,nm_bay);
730 return(0);
731 }
732
733 /* Shutdown a Network Module */
734 int c3725_nm_shutdown(c3725_t *router,u_int nm_bay)
735 {
736 struct c3725_nm_bay *bay;
737
738 if (!(bay = c3725_nm_get_info(router,nm_bay)))
739 return(-1);
740
741 /* Check that a device type is defined for this bay */
742 if (!bay->dev_type || !bay->nm_driver) {
743 vm_error(router->vm,"trying to shut down empty slot %u.\n",nm_bay);
744 return(-1);
745 }
746
747 /* Disable all NIO */
748 c3725_nm_disable_all_nio(router,nm_bay);
749
750 /* Shutdown the NM driver */
751 if (bay->drv_info && (bay->nm_driver->nm_shutdown(router,nm_bay) == -1)) {
752 vm_error(router->vm,"unable to shutdown NM %u.\n",nm_bay);
753 return(-1);
754 }
755
756 free(bay->dev_name);
757 bay->dev_name = NULL;
758 bay->drv_info = NULL;
759 return(0);
760 }
761
762 /* Shutdown all NM of a router */
763 int c3725_nm_shutdown_all(c3725_t *router)
764 {
765 int i;
766
767 for(i=0;i<C3725_MAX_NM_BAYS;i++) {
768 if (!router->nm_bay[i].dev_type)
769 continue;
770
771 c3725_nm_shutdown(router,i);
772 }
773
774 return(0);
775 }
776
777 /* Show info about all NMs */
778 int c3725_nm_show_all_info(c3725_t *router)
779 {
780 struct c3725_nm_bay *bay;
781 int i;
782
783 for(i=0;i<C3725_MAX_NM_BAYS;i++) {
784 if (!(bay = c3725_nm_get_info(router,i)) || !bay->nm_driver)
785 continue;
786
787 if (bay->nm_driver->nm_show_info != NULL)
788 bay->nm_driver->nm_show_info(router,i);
789 }
790
791 return(0);
792 }
793
794 /* Maximum number of tokens in a NM description */
795 #define NM_DESC_MAX_TOKENS 8
796
797 /* Create a Network Module (command line) */
798 int c3725_cmd_nm_create(c3725_t *router,char *str)
799 {
800 char *tokens[NM_DESC_MAX_TOKENS];
801 int i,count,res;
802 u_int nm_bay;
803
804 /* A port adapter description is like "1:NM-1FE" */
805 if ((count = m_strsplit(str,':',tokens,NM_DESC_MAX_TOKENS)) != 2) {
806 vm_error(router->vm,"unable to parse NM description '%s'.\n",str);
807 return(-1);
808 }
809
810 /* Parse the NM bay id */
811 nm_bay = atoi(tokens[0]);
812
813 /* Add this new NM to the current NM list */
814 res = c3725_nm_add_binding(router,tokens[1],nm_bay);
815
816 /* The complete array was cleaned by strsplit */
817 for(i=0;i<NM_DESC_MAX_TOKENS;i++)
818 free(tokens[i]);
819
820 return(res);
821 }
822
823 /* Add a Network IO descriptor binding (command line) */
824 int c3725_cmd_add_nio(c3725_t *router,char *str)
825 {
826 char *tokens[NM_DESC_MAX_TOKENS];
827 int i,count,nio_type,res=-1;
828 u_int nm_bay,port_id;
829 netio_desc_t *nio;
830 char nio_name[128];
831
832 /* A port adapter description is like "1:3:tap:tap0" */
833 if ((count = m_strsplit(str,':',tokens,NM_DESC_MAX_TOKENS)) < 3) {
834 vm_error(router->vm,"unable to parse NIO description '%s'.\n",str);
835 return(-1);
836 }
837
838 /* Parse the NM bay */
839 nm_bay = atoi(tokens[0]);
840
841 /* Parse the NM port id */
842 port_id = atoi(tokens[1]);
843
844 /* Autogenerate a NIO name */
845 snprintf(nio_name,sizeof(nio_name),"c3725-i%u/%u/%u",
846 router->vm->instance_id,nm_bay,port_id);
847
848 /* Create the Network IO descriptor */
849 nio = NULL;
850 nio_type = netio_get_type(tokens[2]);
851
852 switch(nio_type) {
853 case NETIO_TYPE_UNIX:
854 if (count != 5) {
855 vm_error(router->vm,
856 "invalid number of arguments for UNIX NIO '%s'\n",str);
857 goto done;
858 }
859
860 nio = netio_desc_create_unix(nio_name,tokens[3],tokens[4]);
861 break;
862
863 case NETIO_TYPE_VDE:
864 if (count != 5) {
865 vm_error(router->vm,
866 "invalid number of arguments for VDE NIO '%s'\n",str);
867 goto done;
868 }
869
870 nio = netio_desc_create_vde(nio_name,tokens[3],tokens[4]);
871 break;
872
873 case NETIO_TYPE_TAP:
874 if (count != 4) {
875 vm_error(router->vm,
876 "invalid number of arguments for TAP NIO '%s'\n",str);
877 goto done;
878 }
879
880 nio = netio_desc_create_tap(nio_name,tokens[3]);
881 break;
882
883 case NETIO_TYPE_UDP:
884 if (count != 6) {
885 vm_error(router->vm,
886 "invalid number of arguments for UDP NIO '%s'\n",str);
887 goto done;
888 }
889
890 nio = netio_desc_create_udp(nio_name,atoi(tokens[3]),
891 tokens[4],atoi(tokens[5]));
892 break;
893
894 case NETIO_TYPE_TCP_CLI:
895 if (count != 5) {
896 vm_error(router->vm,
897 "invalid number of arguments for TCP CLI NIO '%s'\n",str);
898 goto done;
899 }
900
901 nio = netio_desc_create_tcp_cli(nio_name,tokens[3],tokens[4]);
902 break;
903
904 case NETIO_TYPE_TCP_SER:
905 if (count != 4) {
906 vm_error(router->vm,
907 "invalid number of arguments for TCP SER NIO '%s'\n",str);
908 goto done;
909 }
910
911 nio = netio_desc_create_tcp_ser(nio_name,tokens[3]);
912 break;
913
914 case NETIO_TYPE_NULL:
915 nio = netio_desc_create_null(nio_name);
916 break;
917
918 #ifdef LINUX_ETH
919 case NETIO_TYPE_LINUX_ETH:
920 if (count != 4) {
921 vm_error(router->vm,
922 "invalid number of arguments for Linux Eth NIO '%s'\n",
923 str);
924 goto done;
925 }
926
927 nio = netio_desc_create_lnxeth(nio_name,tokens[3]);
928 break;
929 #endif
930
931 #ifdef GEN_ETH
932 case NETIO_TYPE_GEN_ETH:
933 if (count != 4) {
934 vm_error(router->vm,
935 "invalid number of arguments for Generic Eth NIO '%s'\n",
936 str);
937 goto done;
938 }
939
940 nio = netio_desc_create_geneth(nio_name,tokens[3]);
941 break;
942 #endif
943
944 default:
945 vm_error(router->vm,"unknown NETIO type '%s'\n",tokens[2]);
946 goto done;
947 }
948
949 if (!nio) {
950 vm_error(router->vm,"unable to create NETIO "
951 "descriptor for NM slot %u\n",nm_bay);
952 goto done;
953 }
954
955 if (c3725_nm_add_nio_binding(router,nm_bay,port_id,nio_name) == -1) {
956 vm_error(router->vm,"unable to add NETIO binding for slot %u\n",nm_bay);
957 netio_release(nio_name);
958 netio_delete(nio_name);
959 goto done;
960 }
961
962 netio_release(nio_name);
963 res = 0;
964
965 done:
966 /* The complete array was cleaned by strsplit */
967 for(i=0;i<NM_DESC_MAX_TOKENS;i++)
968 free(tokens[i]);
969
970 return(res);
971 }
972
973 /* Show the list of available NM drivers */
974 void c3725_nm_show_drivers(void)
975 {
976 int i;
977
978 printf("Available C3725 Network Module drivers:\n");
979
980 for(i=0;nm_drivers[i];i++) {
981 printf(" * %s %s\n",
982 nm_drivers[i]->dev_type,
983 !nm_drivers[i]->supported ? "(NOT WORKING)" : "");
984 }
985
986 printf("\n");
987 }
988
989 /* Set the base MAC address of the chassis */
990 static int c3725_burn_mac_addr(c3725_t *router,n_eth_addr_t *addr)
991 {
992 m_uint8_t eeprom_ver;
993 size_t offset;
994
995 /* Read EEPROM format version */
996 cisco_eeprom_get_byte(&router->mb_eeprom,0,&eeprom_ver);
997
998 switch(eeprom_ver) {
999 case 0:
1000 cisco_eeprom_set_region(&router->mb_eeprom,2,addr->eth_addr_byte,6);
1001 break;
1002
1003 case 4:
1004 if (!cisco_eeprom_v4_find_field(&router->mb_eeprom,0xC3,&offset)) {
1005 cisco_eeprom_set_region(&router->mb_eeprom,offset,
1006 addr->eth_addr_byte,6);
1007 }
1008 break;
1009
1010 default:
1011 vm_error(router->vm,"c3725_burn_mac_addr: unable to handle "
1012 "EEPROM version %u\n",eeprom_ver);
1013 return(-1);
1014 }
1015
1016 return(0);
1017 }
1018
1019 /* Set chassis MAC address */
1020 int c3725_chassis_set_mac_addr(c3725_t *router,char *mac_addr)
1021 {
1022 if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) {
1023 vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr);
1024 return(-1);
1025 }
1026
1027 /* Set the chassis base MAC address */
1028 c3725_burn_mac_addr(router,&router->mac_addr);
1029 return(0);
1030 }
1031
1032 /* Create the two main PCI busses for a GT64120 based system */
1033 static int c3725_init_gt96100(c3725_t *router)
1034 {
1035 vm_instance_t *vm = router->vm;
1036
1037 vm->pci_bus[0] = pci_bus_create("PCI bus #0",0);
1038 vm->pci_bus[1] = pci_bus_create("PCI bus #1",0);
1039
1040 if (!vm->pci_bus[0] || !vm->pci_bus[1]) {
1041 vm_error(router->vm,"unable to create PCI data.\n");
1042 return(-1);
1043 }
1044
1045 return(dev_gt96100_init(vm,"gt96100",C3725_GT96K_ADDR,0x200000,
1046 C3725_GT96K_IRQ,c3725_net_irq_for_slot_port(0,0)));
1047 }
1048
1049 /* Initialize a Cisco 3725 */
1050 static int c3725_init(c3725_t *router)
1051 {
1052 vm_instance_t *vm = router->vm;
1053
1054 /* Set the processor type: R7000 */
1055 mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R7000);
1056
1057 /* Initialize the Galileo GT-96100 PCI controller */
1058 if (c3725_init_gt96100(router) == -1)
1059 return(-1);
1060
1061 /* Initialize PCI map (NM slot 1 & 2) */
1062 router->nm_bay[1].pci_map = vm->pci_bus[1];
1063 router->nm_bay[2].pci_map = vm->pci_bus[1];
1064
1065 vm->elf_machine_id = C3725_ELF_MACHINE_ID;
1066 return(0);
1067 }
1068
1069 /* Show C3725 hardware info */
1070 void c3725_show_hardware(c3725_t *router)
1071 {
1072 vm_instance_t *vm = router->vm;
1073
1074 printf("C3725 instance '%s' (id %d):\n",vm->name,vm->instance_id);
1075
1076 printf(" VM Status : %d\n",vm->status);
1077 printf(" RAM size : %u Mb\n",vm->ram_size);
1078 printf(" NVRAM size : %u Kb\n",vm->nvram_size);
1079 printf(" IOS image : %s\n\n",vm->ios_image);
1080
1081 if (vm->debug_level > 0) {
1082 dev_show_list(vm);
1083 pci_dev_show_list(vm->pci_bus[0]);
1084 pci_dev_show_list(vm->pci_bus[1]);
1085 printf("\n");
1086 }
1087 }
1088
1089 /* Initialize default parameters for a C3725 */
1090 void c3725_init_defaults(c3725_t *router)
1091 {
1092 vm_instance_t *vm = router->vm;
1093 n_eth_addr_t *m;
1094 m_uint16_t pid;
1095
1096 pid = (m_uint16_t)getpid();
1097
1098 /* Generate a chassis MAC address based on the instance ID */
1099 m = &router->mac_addr;
1100 m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
1101 m->eth_addr_byte[1] = vm->instance_id & 0xFF;
1102 m->eth_addr_byte[2] = pid >> 8;
1103 m->eth_addr_byte[3] = pid & 0xFF;
1104 m->eth_addr_byte[4] = 0x00;
1105 m->eth_addr_byte[5] = 0x00;
1106
1107 c3725_init_eeprom_groups(router);
1108 cisco_eeprom_copy(&router->mb_eeprom,&eeprom_c3725_mainboard);
1109 c3725_burn_mac_addr(router,&router->mac_addr);
1110
1111 vm->ram_mmap = C3725_DEFAULT_RAM_MMAP;
1112 vm->ram_size = C3725_DEFAULT_RAM_SIZE;
1113 vm->rom_size = C3725_DEFAULT_ROM_SIZE;
1114 vm->nvram_size = C3725_DEFAULT_NVRAM_SIZE;
1115 vm->conf_reg_setup = C3725_DEFAULT_CONF_REG;
1116 vm->clock_divisor = C3725_DEFAULT_CLOCK_DIV;
1117 vm->nvram_rom_space = C3725_NVRAM_ROM_RES_SIZE;
1118 router->nm_iomem_size = C3725_DEFAULT_IOMEM_SIZE;
1119
1120 vm->pcmcia_disk_size[0] = C3725_DEFAULT_DISK0_SIZE;
1121 vm->pcmcia_disk_size[1] = C3725_DEFAULT_DISK1_SIZE;
1122
1123 /* Enable NVRAM operations to load/store configs */
1124 vm->nvram_extract_config = c3725_nvram_extract_config;
1125 vm->nvram_push_config = c3725_nvram_push_config;
1126 }
1127
1128 /* Initialize the C3725 Platform */
1129 int c3725_init_platform(c3725_t *router)
1130 {
1131 vm_instance_t *vm = router->vm;
1132 struct c3725_nm_bay *nm_bay;
1133 cpu_mips_t *cpu;
1134 cpu_gen_t *gen;
1135 vm_obj_t *obj;
1136 int i;
1137
1138 /* Copy config register setup into "active" config register */
1139 vm->conf_reg = vm->conf_reg_setup;
1140
1141 /* Create Console and AUX ports */
1142 vm_init_vtty(vm);
1143
1144 /* Create a CPU group */
1145 vm->cpu_group = cpu_group_create("System CPU");
1146
1147 /* Initialize the virtual MIPS processor */
1148 if (!(gen = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
1149 vm_error(vm,"unable to create CPU!\n");
1150 return(-1);
1151 }
1152
1153 cpu = CPU_MIPS64(gen);
1154
1155 /* Add this CPU to the system CPU group */
1156 cpu_group_add(vm->cpu_group,gen);
1157 vm->boot_cpu = gen;
1158
1159 /* Initialize the IRQ routing vectors */
1160 vm->set_irq = mips64_vm_set_irq;
1161 vm->clear_irq = mips64_vm_clear_irq;
1162
1163 /* Mark the Network IO interrupt as high priority */
1164 cpu->irq_idle_preempt[C3725_NETIO_IRQ] = TRUE;
1165 cpu->irq_idle_preempt[C3725_GT96K_IRQ] = TRUE;
1166 cpu->irq_idle_preempt[C3725_DUART_IRQ] = TRUE;
1167
1168 /* Copy some parameters from VM to CPU (idle PC, ...) */
1169 cpu->idle_pc = vm->idle_pc;
1170
1171 if (vm->timer_irq_check_itv)
1172 cpu->timer_irq_check_itv = vm->timer_irq_check_itv;
1173
1174 /* Remote emulator control */
1175 dev_remote_control_init(vm,0x16000000,0x1000);
1176
1177 /* Specific Storage Area (SSA) */
1178 dev_ram_init(vm,"ssa",TRUE,FALSE,NULL,FALSE,0x16001000ULL,0x7000);
1179
1180 /* IO FPGA */
1181 if (dev_c3725_iofpga_init(router,C3725_IOFPGA_ADDR,0x40000) == -1)
1182 return(-1);
1183
1184 if (!(obj = vm_object_find(router->vm,"io_fpga")))
1185 return(-1);
1186
1187 router->iofpga_data = obj->data;
1188
1189 #if 0
1190 /* PCI IO space */
1191 if (!(vm->pci_io_space = pci_io_data_init(vm,C3725_PCI_IO_ADDR)))
1192 return(-1);
1193 #endif
1194
1195 /* Initialize the chassis */
1196 if (c3725_init(router) == -1)
1197 return(-1);
1198
1199 /* Initialize RAM */
1200 vm_ram_init(vm,0x00000000ULL);
1201
1202 /* Initialize ROM (as a Flash) */
1203 if (!(obj = dev_flash_init(vm,"rom",C3725_ROM_ADDR,vm->rom_size*1048576)))
1204 return(-1);
1205
1206 dev_flash_copy_data(obj,0,mips64_microcode,mips64_microcode_len);
1207 c3725_nvram_check_empty_config(vm);
1208
1209 /* Initialize the NS16552 DUART */
1210 dev_ns16552_init(vm,C3725_DUART_ADDR,0x1000,3,C3725_DUART_IRQ,
1211 vm->vtty_con,vm->vtty_aux);
1212
1213 /* PCMCIA Slot 0 */
1214 dev_pcmcia_disk_init(vm,"slot0",C3725_SLOT0_ADDR,0x200000,
1215 vm->pcmcia_disk_size[0],1);
1216
1217 /* PCMCIA Slot 1 */
1218 dev_pcmcia_disk_init(vm,"slot1",C3725_SLOT1_ADDR,0x200000,
1219 vm->pcmcia_disk_size[1],1);
1220
1221 /* The GT96100 system controller has 2 integrated FastEthernet ports */
1222 c3725_nm_add_binding(router,"GT96100-FE",0);
1223
1224 /* Initialize Network Modules */
1225 for(i=0;i<C3725_MAX_NM_BAYS;i++) {
1226 nm_bay = &router->nm_bay[i];
1227
1228 if (!nm_bay->dev_type)
1229 continue;
1230
1231 if (c3725_nm_init(router,i) == -1) {
1232 vm_error(vm,"unable to create Network Module \"%s\"\n",
1233 nm_bay->dev_type);
1234 return(-1);
1235 }
1236 }
1237
1238 /* Show device list */
1239 c3725_show_hardware(router);
1240 return(0);
1241 }
1242
1243 /* Boot the IOS image */
1244 int c3725_boot_ios(c3725_t *router)
1245 {
1246 vm_instance_t *vm = router->vm;
1247 cpu_mips_t *cpu;
1248
1249 if (!vm->boot_cpu)
1250 return(-1);
1251
1252 /* Suspend CPU activity since we will restart directly from ROM */
1253 vm_suspend(vm);
1254
1255 /* Check that CPU activity is really suspended */
1256 if (cpu_group_sync_state(vm->cpu_group) == -1) {
1257 vm_error(vm,"unable to sync with system CPUs.\n");
1258 return(-1);
1259 }
1260
1261 /* Reset the boot CPU */
1262 cpu = CPU_MIPS64(vm->boot_cpu);
1263 mips64_reset(cpu);
1264
1265 /* Load IOS image */
1266 if (mips64_load_elf_image(cpu,vm->ios_image,
1267 (vm->ghost_status == VM_GHOST_RAM_USE),
1268 &vm->ios_entry_point) < 0)
1269 {
1270 vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
1271 return(-1);
1272 }
1273
1274 /* Launch the simulation */
1275 printf("\nC3725 '%s': starting simulation (CPU0 PC=0x%llx), "
1276 "JIT %sabled.\n",
1277 vm->name,cpu->pc,vm->jit_use ? "en":"dis");
1278
1279 vm_log(vm,"C3725_BOOT",
1280 "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
1281 cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
1282
1283 /* Start main CPU */
1284 if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
1285 vm->status = VM_STATUS_RUNNING;
1286 cpu_start(vm->boot_cpu);
1287 } else {
1288 vm->status = VM_STATUS_SHUTDOWN;
1289 }
1290 return(0);
1291 }
1292
1293 /* Set an IRQ */
1294 static void c3725_set_irq(vm_instance_t *vm,u_int irq)
1295 {
1296 c3725_t *router = VM_C3725(vm);
1297 cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
1298 u_int slot,port;
1299
1300 switch(irq) {
1301 case 0 ... 7:
1302 mips64_set_irq(cpu0,irq);
1303
1304 if (cpu0->irq_idle_preempt[irq])
1305 cpu_idle_break_wait(cpu0->gen);
1306 break;
1307
1308 case C3725_NETIO_IRQ_BASE ... C3725_NETIO_IRQ_END:
1309 c3725_net_irq_get_slot_port(irq,&slot,&port);
1310 dev_c3725_iofpga_net_set_irq(router->iofpga_data,slot,port);
1311 break;
1312 }
1313 }
1314
1315 /* Clear an IRQ */
1316 static void c3725_clear_irq(vm_instance_t *vm,u_int irq)
1317 {
1318 c3725_t *router = VM_C3725(vm);
1319 cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
1320 u_int slot,port;
1321
1322 switch(irq) {
1323 case 0 ... 7:
1324 mips64_clear_irq(cpu0,irq);
1325 break;
1326
1327 case C3725_NETIO_IRQ_BASE ... C3725_NETIO_IRQ_END:
1328 c3725_net_irq_get_slot_port(irq,&slot,&port);
1329 dev_c3725_iofpga_net_clear_irq(router->iofpga_data,slot,port);
1330 break;
1331 }
1332 }
1333
1334 /* Initialize a Cisco 3725 instance */
1335 int c3725_init_instance(c3725_t *router)
1336 {
1337 vm_instance_t *vm = router->vm;
1338 m_uint32_t rom_entry_point;
1339 cpu_mips_t *cpu0;
1340
1341 if (!vm->ios_image) {
1342 vm_error(vm,"no Cisco IOS image defined.");
1343 return(-1);
1344 }
1345
1346 /* Initialize the C3725 platform */
1347 if (c3725_init_platform(router) == -1) {
1348 vm_error(vm,"unable to initialize the platform hardware.\n");
1349 return(-1);
1350 }
1351
1352 /* IRQ routing */
1353 vm->set_irq = c3725_set_irq;
1354 vm->clear_irq = c3725_clear_irq;
1355
1356 /* Load IOS configuration file */
1357 if (vm->ios_config != NULL) {
1358 vm_nvram_push_config(vm,vm->ios_config);
1359 vm->conf_reg &= ~0x40;
1360 }
1361
1362 /* Load ROM (ELF image or embedded) */
1363 cpu0 = CPU_MIPS64(vm->boot_cpu);
1364 rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
1365
1366 if ((vm->rom_filename != NULL) &&
1367 (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
1368 {
1369 vm_error(vm,"unable to load alternate ROM '%s', "
1370 "fallback to embedded ROM.\n\n",vm->rom_filename);
1371 vm->rom_filename = NULL;
1372 }
1373
1374 /* Load symbol file */
1375 if (vm->sym_filename) {
1376 mips64_sym_load_file(cpu0,vm->sym_filename);
1377 cpu0->sym_trace = 1;
1378 }
1379
1380 return(c3725_boot_ios(router));
1381 }
1382
1383 /* Stop a Cisco 3725 instance */
1384 int c3725_stop_instance(c3725_t *router)
1385 {
1386 vm_instance_t *vm = router->vm;
1387
1388 printf("\nC3725 '%s': stopping simulation.\n",vm->name);
1389 vm_log(vm,"C3725_STOP","stopping simulation.\n");
1390
1391 /* Stop all CPUs */
1392 if (vm->cpu_group != NULL) {
1393 vm_stop(vm);
1394
1395 if (cpu_group_sync_state(vm->cpu_group) == -1) {
1396 vm_error(vm,"unable to sync with system CPUs.\n");
1397 return(-1);
1398 }
1399 }
1400
1401 /* Free resources that were used during execution to emulate hardware */
1402 c3725_nm_shutdown_all(router);
1403 vm_hardware_shutdown(vm);
1404 return(0);
1405 }

  ViewVC Help
Powered by ViewVC 1.1.26