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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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

  ViewVC Help
Powered by ViewVC 1.1.26