/[dynamips]/trunk/dev_msfc1.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_msfc1.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Sat Oct 6 16:45:40 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 38047 byte(s)
make working copy

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2007 Christophe Fillot (cf@utc.fr)
4 *
5 * Generic MSFC1 routines and definitions (EEPROM,...).
6 *
7 * This is not a working platform! I only added it to play, since it is very
8 * similar to an NPE-200. I think that could work with a functional CatOS SP.
9 */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <sys/types.h>
16 #include <assert.h>
17
18 #include "cpu.h"
19 #include "vm.h"
20 #include "dynamips.h"
21 #include "memory.h"
22 #include "device.h"
23 #include "pci_io.h"
24 #include "dev_gt.h"
25 #include "cisco_eeprom.h"
26 #include "dev_rom.h"
27 #include "dev_dec21140.h"
28 #include "dev_i8254x.h"
29 #include "dev_msfc1.h"
30 #include "dev_vtty.h"
31 #include "registry.h"
32 #include "net.h"
33
34 /* MSFC1 EEPROM */
35 static m_uint16_t eeprom_msfc1_data[128] = {
36 0xabab, 0x0190, 0x1262, 0x0100, 0x0002, 0x6003, 0x00cf, 0x4369,
37 0x7363, 0x6f20, 0x5379, 0x7374, 0x656d, 0x732c, 0x2049, 0x6e63,
38 0x2e00, 0x5753, 0x2d46, 0x3630, 0x3031, 0x2d52, 0x5346, 0x4300,
39 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
40 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3733, 0x2d37, 0x3135,
41 0x302d, 0x3036, 0x0000, 0x0000, 0x0000, 0x4130, 0x3100, 0x0000,
42 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
43 0x0000, 0x0000, 0x012d, 0x0000, 0x0000, 0x0009, 0x0005, 0x0001,
44 0x0003, 0x0001, 0x0001, 0x0002, 0x00cf, 0xffbf, 0x0000, 0x0000,
45 0x6003, 0x0162, 0x0afd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
46 0x0000, 0x0000, 0x0000, 0x0005, 0x00e0, 0xaabb, 0xcc00, 0x0100,
47 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
48 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
49 0x1401, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
50 0x1000, 0x4b3c, 0x4132, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080,
51 0x8080, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
52 };
53
54 static struct cisco_eeprom msfc1_eeprom = {
55 "msfc1", eeprom_msfc1_data, sizeof(eeprom_msfc1_data)/2,
56 };
57
58 /* ====================================================================== */
59 /* EOBC - Ethernet Out of Band Channel */
60 /* ====================================================================== */
61 static int dev_msfc1_eobc_init(msfc1_t *router,char *name,u_int pa_bay)
62 {
63 vm_instance_t *vm = router->vm;
64 struct dec21140_data *data;
65
66 /* Create the DEC21140 chip */
67 data = dev_dec21140_init(vm,name,vm->pci_bus[0],6,MSFC1_NETIO_IRQ);
68 if (!data) return(-1);
69
70 /* Store device info into the router structure */
71 return(msfc1_pa_set_drvinfo(router,pa_bay,data));
72 }
73
74 /* Remove EOBC */
75 static int dev_msfc1_eobc_shutdown(msfc1_t *router,u_int pa_bay)
76 {
77 struct msfc1_pa_bay *bay;
78
79 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
80 return(-1);
81
82 dev_dec21140_remove(bay->drv_info);
83 return(0);
84 }
85
86 /* Bind a Network IO descriptor */
87 static int dev_msfc1_eobc_set_nio(msfc1_t *router,u_int pa_bay,u_int port_id,
88 netio_desc_t *nio)
89 {
90 struct dec21140_data *d;
91
92 if ((port_id != 0) || !(d = msfc1_pa_get_drvinfo(router,pa_bay)))
93 return(-1);
94
95 return(dev_dec21140_set_nio(d,nio));
96 }
97
98 /* Unbind a Network IO descriptor */
99 static int dev_msfc1_eobc_unset_nio(msfc1_t *router,u_int pa_bay,
100 u_int port_id)
101 {
102 struct dec21140_data *d;
103
104 if ((port_id != 0) || !(d = msfc1_pa_get_drvinfo(router,pa_bay)))
105 return(-1);
106
107 dev_dec21140_unset_nio(d);
108 return(0);
109 }
110
111 /* EOBC driver */
112 struct msfc1_pa_driver dev_msfc1_eobc = {
113 "MSFC1_EOBC", 0,
114 dev_msfc1_eobc_init,
115 dev_msfc1_eobc_shutdown,
116 dev_msfc1_eobc_set_nio,
117 dev_msfc1_eobc_unset_nio,
118 NULL,
119 };
120
121 /* ====================================================================== */
122 /* IBC - InBand Channel */
123 /* ====================================================================== */
124 static int dev_msfc1_ibc_init(msfc1_t *router,char *name,u_int pa_bay)
125 {
126 vm_instance_t *vm = router->vm;
127 struct i8254x_data *data;
128
129 /* Create the Intel Wiseman/Livengood chip */
130 data = dev_i8254x_init(vm,name,0,vm->pci_bus_pool[24],1,MSFC1_NETIO_IRQ);
131 if (!data) return(-1);
132
133 /* Store device info into the router structure */
134 return(msfc1_pa_set_drvinfo(router,pa_bay,data));
135 }
136
137 /* Remove EOBC */
138 static int dev_msfc1_ibc_shutdown(msfc1_t *router,u_int pa_bay)
139 {
140 struct msfc1_pa_bay *bay;
141
142 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
143 return(-1);
144
145 dev_i8254x_remove(bay->drv_info);
146 return(0);
147 }
148
149 /* Bind a Network IO descriptor */
150 static int dev_msfc1_ibc_set_nio(msfc1_t *router,u_int pa_bay,u_int port_id,
151 netio_desc_t *nio)
152 {
153 struct i8254x_data *d;
154
155 if ((port_id != 1) || !(d = msfc1_pa_get_drvinfo(router,pa_bay)))
156 return(-1);
157
158 return(dev_i8254x_set_nio(d,nio));
159 }
160
161 /* Unbind a Network IO descriptor */
162 static int dev_msfc1_ibc_unset_nio(msfc1_t *router,u_int pa_bay,
163 u_int port_id)
164 {
165 struct i8254x_data *d;
166
167 if ((port_id != 0) || !(d = msfc1_pa_get_drvinfo(router,pa_bay)))
168 return(-1);
169
170 dev_i8254x_unset_nio(d);
171 return(0);
172 }
173
174 /* IBC driver */
175 struct msfc1_pa_driver dev_msfc1_ibc = {
176 "MSFC1_IBC", 0,
177 dev_msfc1_ibc_init,
178 dev_msfc1_ibc_shutdown,
179 dev_msfc1_ibc_set_nio,
180 dev_msfc1_ibc_unset_nio,
181 NULL,
182 };
183
184 /* ======================================================================== */
185 /* Port Adapter Drivers */
186 /* ======================================================================== */
187 static struct msfc1_pa_driver *pa_drivers[] = {
188 &dev_msfc1_eobc,
189 &dev_msfc1_ibc,
190 NULL,
191 };
192
193 /* ======================================================================== */
194 /* MSFC1 router instances */
195 /* ======================================================================== */
196
197 /* Directly extract the configuration from the NVRAM device */
198 ssize_t msfc1_nvram_extract_config(vm_instance_t *vm,char **buffer)
199 {
200 u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;
201 m_uint32_t start,end,nvlen,clen;
202 m_uint16_t magic1,magic2;
203 struct vdevice *nvram_dev;
204 m_uint64_t nvram_addr;
205 off_t nvram_size;
206 int fd;
207
208 if ((nvram_dev = dev_get_by_name(vm,"nvram")))
209 dev_sync(nvram_dev);
210
211 fd = vm_mmap_open_file(vm,"nvram",&base_ptr,&nvram_size);
212
213 if (fd == -1)
214 return(-1);
215
216 nvram_addr = MSFC1_NVRAM_ADDR;
217 ios_ptr = base_ptr + vm->nvram_rom_space;
218 end_ptr = base_ptr + nvram_size;
219
220 if ((ios_ptr + 0x30) >= end_ptr) {
221 vm_error(vm,"NVRAM file too small\n");
222 return(-1);
223 }
224
225 magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06));
226 magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08));
227
228 if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) {
229 vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n",
230 magic1,magic2);
231 return(-1);
232 }
233
234 start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1;
235 end = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x14));
236 nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18));
237 clen = end - start;
238
239 if ((clen + 1) != nvlen) {
240 vm_error(vm,"invalid configuration size (0x%x)\n",nvlen);
241 return(-1);
242 }
243
244 if (!(*buffer = malloc(clen+1))) {
245 vm_error(vm,"unable to allocate config buffer (%u bytes)\n",clen);
246 return(-1);
247 }
248
249 cfg_ptr = base_ptr + (start - nvram_addr);
250
251 if ((start < nvram_addr) || ((cfg_ptr + clen) > end_ptr)) {
252 vm_error(vm,"NVRAM file too small\n");
253 return(-1);
254 }
255
256 memcpy(*buffer,cfg_ptr,clen);
257 (*buffer)[clen] = 0;
258 return(clen);
259 }
260
261 /* Directly push the IOS configuration to the NVRAM device */
262 int msfc1_nvram_push_config(vm_instance_t *vm,char *buffer,size_t len)
263 {
264 u_char *base_ptr,*ios_ptr,*cfg_ptr;
265 m_uint32_t cfg_addr,cfg_offset;
266 m_uint32_t nvram_addr,cklen;
267 m_uint16_t cksum;
268 int fd;
269
270 fd = vm_mmap_create_file(vm,"nvram",vm->nvram_size*1024,&base_ptr);
271
272 if (fd == -1)
273 return(-1);
274
275 cfg_offset = 0x2c;
276 ios_ptr = base_ptr + vm->nvram_rom_space;
277 cfg_ptr = ios_ptr + cfg_offset;
278
279 nvram_addr = MSFC1_NVRAM_ADDR;
280 cfg_addr = nvram_addr + vm->nvram_rom_space + cfg_offset;
281
282 /* Write IOS tag, uncompressed config... */
283 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5);
284 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD);
285 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001);
286 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000);
287 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0000);
288
289 /* Store file contents to NVRAM */
290 memcpy(cfg_ptr,buffer,len);
291
292 /* Write config addresses + size */
293 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(cfg_addr);
294 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(cfg_addr + len);
295 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len);
296
297 /* Compute the checksum */
298 cklen = (vm->nvram_size*1024) - (vm->nvram_rom_space + 0x08);
299 cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen);
300 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum);
301
302 vm_mmap_close_file(fd,base_ptr,vm->nvram_size*1024);
303 return(0);
304 }
305
306 /* Set MSFC eeprom definition */
307 static int msfc1_set_eeprom(msfc1_t *router)
308 {
309 if (cisco_eeprom_copy(&router->cpu_eeprom,&msfc1_eeprom) == -1) {
310 vm_error(router->vm,"unable to set NPE EEPROM.\n");
311 return(-1);
312 }
313
314 return(0);
315 }
316
317 /* Set the base MAC address of the chassis */
318 static int msfc1_burn_mac_addr(msfc1_t *router,n_eth_addr_t *addr)
319 {
320 m_uint8_t eeprom_ver;
321
322 /* Read EEPROM format version */
323 cisco_eeprom_get_byte(&router->mp_eeprom,0,&eeprom_ver);
324
325 if (eeprom_ver != 1) {
326 vm_error(router->vm,"msfc1_burn_mac_addr: unable to handle "
327 "EEPROM version %u\n",eeprom_ver);
328 return(-1);
329 }
330
331 cisco_eeprom_set_region(&router->mp_eeprom,12,addr->eth_addr_byte,6);
332 return(0);
333 }
334
335 /* Free specific hardware resources used by MSFC1 */
336 static void msfc1_free_hw_ressources(msfc1_t *router)
337 {
338 /* Shutdown all Port Adapters */
339 msfc1_pa_shutdown_all(router);
340 }
341
342 /* Create a new router instance */
343 msfc1_t *msfc1_create_instance(char *name,int instance_id)
344 {
345 msfc1_t *router;
346
347 if (!(router = malloc(sizeof(*router)))) {
348 fprintf(stderr,"MSFC1 '%s': Unable to create new instance!\n",name);
349 return NULL;
350 }
351
352 memset(router,0,sizeof(*router));
353
354 if (!(router->vm = vm_create(name,instance_id,VM_TYPE_MSFC1))) {
355 fprintf(stderr,"MSFC1 '%s': unable to create VM instance!\n",name);
356 goto err_vm;
357 }
358
359 msfc1_init_defaults(router);
360 router->vm->hw_data = router;
361 router->vm->elf_machine_id = MSFC1_ELF_MACHINE_ID;
362 return router;
363
364 err_vm:
365 free(router);
366 return NULL;
367 }
368
369 /* Free resources used by a router instance */
370 static int msfc1_free_instance(void *data,void *arg)
371 {
372 vm_instance_t *vm = data;
373 msfc1_t *router;
374 int i;
375
376 if (vm->type == VM_TYPE_MSFC1) {
377 router = VM_MSFC1(vm);
378
379 /* Stop all CPUs */
380 if (vm->cpu_group != NULL) {
381 vm_stop(vm);
382
383 if (cpu_group_sync_state(vm->cpu_group) == -1) {
384 vm_error(vm,"unable to sync with system CPUs.\n");
385 return(FALSE);
386 }
387 }
388
389 /* Remove NIO bindings */
390 for(i=0;i<MSFC1_MAX_PA_BAYS;i++)
391 msfc1_pa_remove_all_nio_bindings(router,i);
392
393 /* Free specific HW resources */
394 msfc1_free_hw_ressources(router);
395
396 /* Free EEPROMs */
397 cisco_eeprom_free(&router->cpu_eeprom);
398 cisco_eeprom_free(&router->mp_eeprom);
399 cisco_eeprom_free(&router->pem_eeprom);
400
401 /* Free all resources used by VM */
402 vm_free(vm);
403
404 /* Free the router structure */
405 free(router);
406 return(TRUE);
407 }
408
409 return(FALSE);
410 }
411
412 /* Delete a router instance */
413 int msfc1_delete_instance(char *name)
414 {
415 return(registry_delete_if_unused(name,OBJ_TYPE_VM,
416 msfc1_free_instance,NULL));
417 }
418
419 /* Delete all router instances */
420 int msfc1_delete_all_instances(void)
421 {
422 return(registry_delete_type(OBJ_TYPE_VM,msfc1_free_instance,NULL));
423 }
424
425 /* Save configuration of a MSFC1 instance */
426 void msfc1_save_config(msfc1_t *router,FILE *fd)
427 {
428 vm_instance_t *vm = router->vm;
429 struct msfc1_nio_binding *nb;
430 struct msfc1_pa_bay *bay;
431 int i;
432
433 /* General settings */
434 fprintf(fd,"msfc1 create %s %u\n",vm->name,vm->instance_id);
435
436 /* VM configuration */
437 vm_save_config(vm,fd);
438
439 /* Port Adapter settings */
440 for(i=0;i<MSFC1_MAX_PA_BAYS;i++) {
441 if (!(bay = msfc1_pa_get_info(router,i)))
442 continue;
443
444 if (bay->dev_type) {
445 fprintf(fd,"msfc1 add_pa_binding %s %u %s\n",
446 vm->name,i,bay->dev_type);
447 }
448
449 for(nb=bay->nio_list;nb;nb=nb->next) {
450 fprintf(fd,"msfc1 add_nio_binding %s %u %u %s\n",
451 vm->name,i,nb->port_id,nb->nio->name);
452 }
453 }
454
455 fprintf(fd,"\n");
456 }
457
458 /* Save configurations of all MSFC1 instances */
459 static void msfc1_reg_save_config(registry_entry_t *entry,void *opt,int *err)
460 {
461 vm_instance_t *vm = entry->data;
462 msfc1_t *router = VM_MSFC1(vm);
463
464 if (vm->type == VM_TYPE_MSFC1)
465 msfc1_save_config(router,(FILE *)opt);
466 }
467
468 /* Unset PA EEPROM definition (empty bay) */
469 int msfc1_pa_unset_eeprom(msfc1_t *router,u_int pa_bay)
470 {
471 if (pa_bay >= MSFC1_MAX_PA_BAYS) {
472 vm_error(router->vm,"msfc1_pa_set_eeprom: invalid PA Bay %u.\n",pa_bay);
473 return(-1);
474 }
475
476 cisco_eeprom_free(&router->pa_bay[pa_bay].eeprom);
477 return(0);
478 }
479
480 /* Check if a bay has a port adapter */
481 int msfc1_pa_check_eeprom(msfc1_t *router,u_int pa_bay)
482 {
483 if (pa_bay >= MSFC1_MAX_PA_BAYS)
484 return(FALSE);
485
486 return(cisco_eeprom_valid(&router->pa_bay[pa_bay].eeprom));
487 }
488
489 /* Get bay info */
490 struct msfc1_pa_bay *msfc1_pa_get_info(msfc1_t *router,u_int pa_bay)
491 {
492 if (pa_bay >= MSFC1_MAX_PA_BAYS)
493 return NULL;
494
495 return(&router->pa_bay[pa_bay]);
496 }
497
498 /* Get PA type */
499 char *msfc1_pa_get_type(msfc1_t *router,u_int pa_bay)
500 {
501 struct msfc1_pa_bay *bay;
502
503 bay = msfc1_pa_get_info(router,pa_bay);
504 return((bay != NULL) ? bay->dev_type : NULL);
505 }
506
507 /* Get driver info about the specified slot */
508 void *msfc1_pa_get_drvinfo(msfc1_t *router,u_int pa_bay)
509 {
510 struct msfc1_pa_bay *bay;
511
512 bay = msfc1_pa_get_info(router,pa_bay);
513 return((bay != NULL) ? bay->drv_info : NULL);
514 }
515
516 /* Set driver info for the specified slot */
517 int msfc1_pa_set_drvinfo(msfc1_t *router,u_int pa_bay,void *drv_info)
518 {
519 struct msfc1_pa_bay *bay;
520
521 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
522 return(-1);
523
524 bay->drv_info = drv_info;
525 return(0);
526 }
527
528 /* Get a PA driver */
529 static struct msfc1_pa_driver *msfc1_pa_get_driver(char *dev_type)
530 {
531 int i;
532
533 for(i=0;pa_drivers[i];i++)
534 if (!strcmp(pa_drivers[i]->dev_type,dev_type))
535 return pa_drivers[i];
536
537 return NULL;
538 }
539
540 /* Add a PA binding */
541 int msfc1_pa_add_binding(msfc1_t *router,char *dev_type,u_int pa_bay)
542 {
543 struct msfc1_pa_driver *pa_driver;
544 struct msfc1_pa_bay *bay;
545
546 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
547 return(-1);
548
549 /* check that this bay is empty */
550 if (bay->dev_type != NULL) {
551 vm_error(router->vm,"a PA already exists in slot %u.\n",pa_bay);
552 return(-1);
553 }
554
555 /* find the PA driver */
556 if (!(pa_driver = msfc1_pa_get_driver(dev_type))) {
557 vm_error(router->vm,"unknown PA type '%s'.\n",dev_type);
558 return(-1);
559 }
560
561 bay->dev_type = pa_driver->dev_type;
562 bay->pa_driver = pa_driver;
563 return(0);
564 }
565
566 /* Remove a PA binding */
567 int msfc1_pa_remove_binding(msfc1_t *router,u_int pa_bay)
568 {
569 struct msfc1_pa_bay *bay;
570
571 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
572 return(-1);
573
574 /* stop if this bay is still active */
575 if (bay->drv_info != NULL) {
576 vm_error(router->vm,"slot %u still active.\n",pa_bay);
577 return(-1);
578 }
579
580 /* check that this bay is not empty */
581 if (bay->dev_type == NULL) {
582 vm_error(router->vm,"slot %u is empty.\n",pa_bay);
583 return(-1);
584 }
585
586 /* remove all NIOs bindings */
587 msfc1_pa_remove_all_nio_bindings(router,pa_bay);
588
589 bay->dev_type = NULL;
590 bay->pa_driver = NULL;
591 return(0);
592 }
593
594 /* Find a NIO binding */
595 struct msfc1_nio_binding *
596 msfc1_pa_find_nio_binding(msfc1_t *router,u_int pa_bay,u_int port_id)
597 {
598 struct msfc1_nio_binding *nb;
599 struct msfc1_pa_bay *bay;
600
601 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
602 return NULL;
603
604 for(nb=bay->nio_list;nb;nb=nb->next)
605 if (nb->port_id == port_id)
606 return nb;
607
608 return NULL;
609 }
610
611 /* Add a network IO binding */
612 int msfc1_pa_add_nio_binding(msfc1_t *router,u_int pa_bay,u_int port_id,
613 char *nio_name)
614 {
615 struct msfc1_nio_binding *nb;
616 struct msfc1_pa_bay *bay;
617 netio_desc_t *nio;
618
619 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
620 return(-1);
621
622 /* check that a NIO is not already bound to this port */
623 if (msfc1_pa_find_nio_binding(router,pa_bay,port_id) != NULL) {
624 vm_error(router->vm,"a NIO already exists for interface %u/%u\n",
625 pa_bay,port_id);
626 return(-1);
627 }
628
629 /* acquire a reference on the NIO object */
630 if (!(nio = netio_acquire(nio_name))) {
631 vm_error(router->vm,"unable to find NIO '%s'.\n",nio_name);
632 return(-1);
633 }
634
635 /* create a new binding */
636 if (!(nb = malloc(sizeof(*nb)))) {
637 vm_error(router->vm,"unable to create NIO binding "
638 "for interface %u/%u.\n",pa_bay,port_id);
639 netio_release(nio_name);
640 return(-1);
641 }
642
643 memset(nb,0,sizeof(*nb));
644 nb->nio = nio;
645 nb->port_id = port_id;
646 nb->next = bay->nio_list;
647 if (nb->next) nb->next->prev = nb;
648 bay->nio_list = nb;
649 return(0);
650 }
651
652 /* Remove a NIO binding */
653 int msfc1_pa_remove_nio_binding(msfc1_t *router,u_int pa_bay,u_int port_id)
654 {
655 struct msfc1_nio_binding *nb;
656 struct msfc1_pa_bay *bay;
657
658 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
659 return(-1);
660
661 if (!(nb = msfc1_pa_find_nio_binding(router,pa_bay,port_id)))
662 return(-1); /* no nio binding for this slot/port */
663
664 /* tell the PA driver to stop using this NIO */
665 if (bay->pa_driver)
666 bay->pa_driver->pa_unset_nio(router,pa_bay,port_id);
667
668 /* remove this entry from the double linked list */
669 if (nb->next)
670 nb->next->prev = nb->prev;
671
672 if (nb->prev) {
673 nb->prev->next = nb->next;
674 } else {
675 bay->nio_list = nb->next;
676 }
677
678 /* unreference NIO object */
679 netio_release(nb->nio->name);
680 free(nb);
681 return(0);
682 }
683
684 /* Remove all NIO bindings for the specified PA */
685 int msfc1_pa_remove_all_nio_bindings(msfc1_t *router,u_int pa_bay)
686 {
687 struct msfc1_nio_binding *nb,*next;
688 struct msfc1_pa_bay *bay;
689
690 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
691 return(-1);
692
693 for(nb=bay->nio_list;nb;nb=next) {
694 next = nb->next;
695
696 /* tell the PA driver to stop using this NIO */
697 if (bay->pa_driver)
698 bay->pa_driver->pa_unset_nio(router,pa_bay,nb->port_id);
699
700 /* unreference NIO object */
701 netio_release(nb->nio->name);
702 free(nb);
703 }
704
705 bay->nio_list = NULL;
706 return(0);
707 }
708
709 /* Enable a Network IO descriptor for a Port Adapter */
710 int msfc1_pa_enable_nio(msfc1_t *router,u_int pa_bay,u_int port_id)
711 {
712 struct msfc1_nio_binding *nb;
713 struct msfc1_pa_bay *bay;
714
715 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
716 return(-1);
717
718 /* check that we have an NIO binding for this interface */
719 if (!(nb = msfc1_pa_find_nio_binding(router,pa_bay,port_id)))
720 return(-1);
721
722 /* check that the driver is defined and successfully initialized */
723 if (!bay->pa_driver || !bay->drv_info)
724 return(-1);
725
726 return(bay->pa_driver->pa_set_nio(router,pa_bay,port_id,nb->nio));
727 }
728
729 /* Disable Network IO descriptor of a Port Adapter */
730 int msfc1_pa_disable_nio(msfc1_t *router,u_int pa_bay,u_int port_id)
731 {
732 struct msfc1_pa_bay *bay;
733
734 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
735 return(-1);
736
737 /* check that the driver is defined and successfully initialized */
738 if (!bay->pa_driver || !bay->drv_info)
739 return(-1);
740
741 return(bay->pa_driver->pa_unset_nio(router,pa_bay,port_id));
742 }
743
744 /* Enable all NIO of the specified PA */
745 int msfc1_pa_enable_all_nio(msfc1_t *router,u_int pa_bay)
746 {
747 struct msfc1_nio_binding *nb;
748 struct msfc1_pa_bay *bay;
749
750 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
751 return(-1);
752
753 /* check that the driver is defined and successfully initialized */
754 if (!bay->pa_driver || !bay->drv_info)
755 return(-1);
756
757 for(nb=bay->nio_list;nb;nb=nb->next)
758 bay->pa_driver->pa_set_nio(router,pa_bay,nb->port_id,nb->nio);
759
760 return(0);
761 }
762
763 /* Disable all NIO of the specified PA */
764 int msfc1_pa_disable_all_nio(msfc1_t *router,u_int pa_bay)
765 {
766 struct msfc1_nio_binding *nb;
767 struct msfc1_pa_bay *bay;
768
769 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
770 return(-1);
771
772 /* check that the driver is defined and successfully initialized */
773 if (!bay->pa_driver || !bay->drv_info)
774 return(-1);
775
776 for(nb=bay->nio_list;nb;nb=nb->next)
777 bay->pa_driver->pa_unset_nio(router,pa_bay,nb->port_id);
778
779 return(0);
780 }
781
782 /* Initialize a Port Adapter */
783 int msfc1_pa_init(msfc1_t *router,u_int pa_bay)
784 {
785 struct msfc1_pa_bay *bay;
786 size_t len;
787
788 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
789 return(-1);
790
791 /* Check that a device type is defined for this bay */
792 if (!bay->dev_type || !bay->pa_driver) {
793 vm_error(router->vm,"trying to init empty slot %u.\n",pa_bay);
794 return(-1);
795 }
796
797 /* Allocate device name */
798 len = strlen(bay->dev_type) + 10;
799 if (!(bay->dev_name = malloc(len))) {
800 vm_error(router->vm,"unable to allocate device name.\n");
801 return(-1);
802 }
803
804 snprintf(bay->dev_name,len,"%s(%u)",bay->dev_type,pa_bay);
805
806 /* Initialize PA driver */
807 if (bay->pa_driver->pa_init(router,bay->dev_name,pa_bay) == -1) {
808 vm_error(router->vm,"unable to initialize PA %u.\n",pa_bay);
809 return(-1);
810 }
811
812 /* Enable all NIO */
813 msfc1_pa_enable_all_nio(router,pa_bay);
814 return(0);
815 }
816
817 /* Shutdown a Port Adapter */
818 int msfc1_pa_shutdown(msfc1_t *router,u_int pa_bay)
819 {
820 struct msfc1_pa_bay *bay;
821
822 if (!(bay = msfc1_pa_get_info(router,pa_bay)))
823 return(-1);
824
825 /* Check that a device type is defined for this bay */
826 if (!bay->dev_type || !bay->pa_driver) {
827 vm_error(router->vm,"trying to shut down an empty bay %u.\n",pa_bay);
828 return(-1);
829 }
830
831 /* Disable all NIO */
832 msfc1_pa_disable_all_nio(router,pa_bay);
833
834 /* Shutdown the PA driver */
835 if (bay->drv_info && (bay->pa_driver->pa_shutdown(router,pa_bay) == -1)) {
836 vm_error(router->vm,"unable to shutdown PA %u.\n",pa_bay);
837 return(-1);
838 }
839
840 free(bay->dev_name);
841 bay->dev_name = NULL;
842 bay->drv_info = NULL;
843 return(0);
844 }
845
846 /* Shutdown all PA of a router */
847 int msfc1_pa_shutdown_all(msfc1_t *router)
848 {
849 int i;
850
851 for(i=0;i<MSFC1_MAX_PA_BAYS;i++) {
852 if (!router->pa_bay[i].dev_type)
853 continue;
854
855 msfc1_pa_shutdown(router,i);
856 }
857
858 return(0);
859 }
860
861 /* Show info about all NMs */
862 int msfc1_pa_show_all_info(msfc1_t *router)
863 {
864 struct msfc1_pa_bay *bay;
865 int i;
866
867 for(i=0;i<MSFC1_MAX_PA_BAYS;i++) {
868 if (!(bay = msfc1_pa_get_info(router,i)) || !bay->pa_driver)
869 continue;
870
871 if (bay->pa_driver->pa_show_info != NULL)
872 bay->pa_driver->pa_show_info(router,i);
873 }
874
875 return(0);
876 }
877
878 /* Maximum number of tokens in a PA description */
879 #define PA_DESC_MAX_TOKENS 8
880
881 /* Create a Port Adapter (command line) */
882 int msfc1_cmd_pa_create(msfc1_t *router,char *str)
883 {
884 char *tokens[PA_DESC_MAX_TOKENS];
885 int i,count,res;
886 u_int pa_bay;
887
888 /* A port adapter description is like "1:PA-FE-TX" */
889 if ((count = m_strsplit(str,':',tokens,PA_DESC_MAX_TOKENS)) != 2) {
890 vm_error(router->vm,"unable to parse PA description '%s'.\n",str);
891 return(-1);
892 }
893
894 /* Parse the PA bay id */
895 pa_bay = atoi(tokens[0]);
896
897 /* Add this new PA to the current PA list */
898 res = msfc1_pa_add_binding(router,tokens[1],pa_bay);
899
900 /* The complete array was cleaned by strsplit */
901 for(i=0;i<PA_DESC_MAX_TOKENS;i++)
902 free(tokens[i]);
903
904 return(res);
905 }
906
907 /* Add a Network IO descriptor binding (command line) */
908 int msfc1_cmd_add_nio(msfc1_t *router,char *str)
909 {
910 char *tokens[PA_DESC_MAX_TOKENS];
911 int i,count,nio_type,res=-1;
912 u_int pa_bay,port_id;
913 netio_desc_t *nio;
914 char nio_name[128];
915
916 /* A port adapter description is like "1:3:tap:tap0" */
917 if ((count = m_strsplit(str,':',tokens,PA_DESC_MAX_TOKENS)) < 3) {
918 vm_error(router->vm,"unable to parse NIO description '%s'.\n",str);
919 return(-1);
920 }
921
922 /* Parse the PA bay */
923 pa_bay = atoi(tokens[0]);
924
925 /* Parse the PA port id */
926 port_id = atoi(tokens[1]);
927
928 /* Autogenerate a NIO name */
929 snprintf(nio_name,sizeof(nio_name),"msfc1-i%u/%u/%u",
930 router->vm->instance_id,pa_bay,port_id);
931
932 /* Create the Network IO descriptor */
933 nio = NULL;
934 nio_type = netio_get_type(tokens[2]);
935
936 switch(nio_type) {
937 case NETIO_TYPE_UNIX:
938 if (count != 5) {
939 vm_error(router->vm,
940 "invalid number of arguments for UNIX NIO '%s'\n",str);
941 goto done;
942 }
943
944 nio = netio_desc_create_unix(nio_name,tokens[3],tokens[4]);
945 break;
946
947 case NETIO_TYPE_VDE:
948 if (count != 5) {
949 vm_error(router->vm,
950 "invalid number of arguments for VDE NIO '%s'\n",str);
951 goto done;
952 }
953
954 nio = netio_desc_create_vde(nio_name,tokens[3],tokens[4]);
955 break;
956
957 case NETIO_TYPE_TAP:
958 if (count != 4) {
959 vm_error(router->vm,
960 "invalid number of arguments for TAP NIO '%s'\n",str);
961 goto done;
962 }
963
964 nio = netio_desc_create_tap(nio_name,tokens[3]);
965 break;
966
967 case NETIO_TYPE_UDP:
968 if (count != 6) {
969 vm_error(router->vm,
970 "invalid number of arguments for UDP NIO '%s'\n",str);
971 goto done;
972 }
973
974 nio = netio_desc_create_udp(nio_name,atoi(tokens[3]),
975 tokens[4],atoi(tokens[5]));
976 break;
977
978 case NETIO_TYPE_TCP_CLI:
979 if (count != 5) {
980 vm_error(router->vm,
981 "invalid number of arguments for TCP CLI NIO '%s'\n",str);
982 goto done;
983 }
984
985 nio = netio_desc_create_tcp_cli(nio_name,tokens[3],tokens[4]);
986 break;
987
988 case NETIO_TYPE_TCP_SER:
989 if (count != 4) {
990 vm_error(router->vm,
991 "invalid number of arguments for TCP SER NIO '%s'\n",str);
992 goto done;
993 }
994
995 nio = netio_desc_create_tcp_ser(nio_name,tokens[3]);
996 break;
997
998 case NETIO_TYPE_NULL:
999 nio = netio_desc_create_null(nio_name);
1000 break;
1001
1002 #ifdef LINUX_ETH
1003 case NETIO_TYPE_LINUX_ETH:
1004 if (count != 4) {
1005 vm_error(router->vm,
1006 "invalid number of arguments for Linux Eth NIO '%s'\n",
1007 str);
1008 goto done;
1009 }
1010
1011 nio = netio_desc_create_lnxeth(nio_name,tokens[3]);
1012 break;
1013 #endif
1014
1015 #ifdef GEN_ETH
1016 case NETIO_TYPE_GEN_ETH:
1017 if (count != 4) {
1018 vm_error(router->vm,"invalid number of "
1019 "arguments for Generic Eth NIO '%s'\n",str);
1020 goto done;
1021 }
1022
1023 nio = netio_desc_create_geneth(nio_name,tokens[3]);
1024 break;
1025 #endif
1026
1027 default:
1028 vm_error(router->vm,"unknown NETIO type '%s'\n",tokens[2]);
1029 goto done;
1030 }
1031
1032 if (!nio) {
1033 fprintf(stderr,"msfc1_cmd_add_nio: unable to create NETIO "
1034 "descriptor for PA bay %u\n",pa_bay);
1035 goto done;
1036 }
1037
1038 if (msfc1_pa_add_nio_binding(router,pa_bay,port_id,nio_name) == -1) {
1039 vm_error(router->vm,"unable to add NETIO binding for slot %u\n",pa_bay);
1040 netio_release(nio_name);
1041 netio_delete(nio_name);
1042 goto done;
1043 }
1044
1045 netio_release(nio_name);
1046 res = 0;
1047
1048 done:
1049 /* The complete array was cleaned by strsplit */
1050 for(i=0;i<PA_DESC_MAX_TOKENS;i++)
1051 free(tokens[i]);
1052
1053 return(res);
1054 }
1055
1056 /* Create the main PCI bus for a GT64010 based system */
1057 static int msfc1_init_gt64010(msfc1_t *router)
1058 {
1059 vm_instance_t *vm = router->vm;
1060
1061 if (!(vm->pci_bus[0] = pci_bus_create("PCI Bus 0",0))) {
1062 vm_error(vm,"unable to create PCI data.\n");
1063 return(-1);
1064 }
1065
1066 return(dev_gt64010_init(vm,"gt64010",MSFC1_GT64K_ADDR,0x1000,
1067 MSFC1_GT64K_IRQ));
1068 }
1069
1070 /* Initialize a MSFC1 board */
1071 int msfc1_init_hw(msfc1_t *router)
1072 {
1073 vm_instance_t *vm = router->vm;
1074
1075 /* Set the processor type: R5000 */
1076 mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R5000);
1077
1078 /* Initialize the Galileo GT-64010 PCI controller */
1079 if (msfc1_init_gt64010(router) == -1)
1080 return(-1);
1081
1082 /* Create PCI bus 1 */
1083 vm->pci_bus_pool[24] = pci_bus_create("PCI Bus 1",-1);
1084 dev_dec21154_init(vm->pci_bus[0],1,vm->pci_bus_pool[24]);
1085
1086 /* Initialize SRAM (4Mb) */
1087 dev_c7200_sram_init(vm,"sram",MSFC1_SRAM_ADDR,MSFC1_SRAM_SIZE,
1088 vm->pci_bus_pool[24],0);
1089
1090 /* PCI IO space */
1091 if (!(vm->pci_io_space = pci_io_data_init(vm,MSFC1_PCI_IO_ADDR)))
1092 return(-1);
1093
1094 /* Cirrus Logic PD6729 (PCI-to-PCMCIA host adapter) */
1095 dev_clpd6729_init(vm,vm->pci_bus[0],5,vm->pci_io_space,0x402,0x403);
1096
1097 return(0);
1098 }
1099
1100 /* Show MSFC1 hardware info */
1101 void msfc1_show_hardware(msfc1_t *router)
1102 {
1103 vm_instance_t *vm = router->vm;
1104
1105 printf("MSFC1 instance '%s' (id %d):\n",vm->name,vm->instance_id);
1106
1107 printf(" VM Status : %d\n",vm->status);
1108 printf(" RAM size : %u Mb\n",vm->ram_size);
1109 printf(" IOMEM size : %u Mb\n",vm->iomem_size);
1110 printf(" NVRAM size : %u Kb\n",vm->nvram_size);
1111 printf(" IOS image : %s\n\n",vm->ios_image);
1112
1113 if (vm->debug_level > 0) {
1114 dev_show_list(vm);
1115 pci_dev_show_list(vm->pci_bus[0]);
1116 pci_dev_show_list(vm->pci_bus[1]);
1117 printf("\n");
1118 }
1119 }
1120
1121 /* Initialize default parameters for a MSFC1 */
1122 void msfc1_init_defaults(msfc1_t *router)
1123 {
1124 vm_instance_t *vm = router->vm;
1125 n_eth_addr_t *m;
1126 m_uint16_t pid;
1127
1128 pid = (m_uint16_t)getpid();
1129
1130 /* Generate a chassis MAC address based on the instance ID */
1131 m = &router->mac_addr;
1132 m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
1133 m->eth_addr_byte[1] = vm->instance_id & 0xFF;
1134 m->eth_addr_byte[2] = pid >> 8;
1135 m->eth_addr_byte[3] = pid & 0xFF;
1136 m->eth_addr_byte[4] = 0x00;
1137 m->eth_addr_byte[5] = 0x00;
1138
1139 msfc1_set_eeprom(router);
1140 msfc1_init_eeprom_groups(router);
1141 vm->ram_mmap = MSFC1_DEFAULT_RAM_MMAP;
1142 vm->ram_size = MSFC1_DEFAULT_RAM_SIZE;
1143 vm->rom_size = MSFC1_DEFAULT_ROM_SIZE;
1144 vm->nvram_size = MSFC1_DEFAULT_NVRAM_SIZE;
1145 vm->iomem_size = 0;
1146 vm->conf_reg_setup = MSFC1_DEFAULT_CONF_REG;
1147 vm->clock_divisor = MSFC1_DEFAULT_CLOCK_DIV;
1148 vm->nvram_rom_space = MSFC1_NVRAM_ROM_RES_SIZE;
1149
1150 /* Enable NVRAM operations to load/store configs */
1151 vm->nvram_extract_config = msfc1_nvram_extract_config;
1152 vm->nvram_push_config = msfc1_nvram_push_config;
1153 }
1154
1155 /* Run the checklist */
1156 static int msfc1_checklist(msfc1_t *router)
1157 {
1158 struct vm_instance *vm = router->vm;
1159 int res = 0;
1160
1161 res += vm_object_check(vm,"ram");
1162 res += vm_object_check(vm,"rom");
1163 res += vm_object_check(vm,"nvram");
1164 res += vm_object_check(vm,"zero");
1165
1166 if (res < 0)
1167 vm_error(vm,"incomplete initialization (no memory?)\n");
1168
1169 return(res);
1170 }
1171
1172 /* Initialize Port Adapters */
1173 static int msfc1_init_platform_pa(msfc1_t *router)
1174 {
1175 /* Create EOBC interface */
1176 msfc1_pa_add_binding(router,"MSFC1_EOBC",0);
1177 msfc1_pa_init(router,0);
1178
1179 /* Create IBC interface */
1180 msfc1_pa_add_binding(router,"MSFC1_IBC",1);
1181 msfc1_pa_init(router,1);
1182 return(0);
1183 }
1184
1185 /* Initialize the MSFC1 Platform */
1186 static int msfc1_init_platform(msfc1_t *router)
1187 {
1188 struct vm_instance *vm = router->vm;
1189 cpu_mips_t *cpu0;
1190 cpu_gen_t *gen0;
1191
1192 /* Copy config register setup into "active" config register */
1193 vm->conf_reg = vm->conf_reg_setup;
1194
1195 /* Create Console and AUX ports */
1196 vm_init_vtty(vm);
1197
1198 /* Create a CPU group */
1199 vm->cpu_group = cpu_group_create("System CPU");
1200
1201 /* Initialize the virtual MIPS processor */
1202 if (!(gen0 = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
1203 vm_error(vm,"unable to create CPU0!\n");
1204 return(-1);
1205 }
1206
1207 cpu0 = CPU_MIPS64(gen0);
1208
1209 /* Add this CPU to the system CPU group */
1210 cpu_group_add(vm->cpu_group,gen0);
1211 vm->boot_cpu = gen0;
1212
1213 /* Initialize the IRQ routing vectors */
1214 vm->set_irq = mips64_vm_set_irq;
1215 vm->clear_irq = mips64_vm_clear_irq;
1216
1217 /* Mark the Network IO interrupt as high priority */
1218 cpu0->irq_idle_preempt[MSFC1_NETIO_IRQ] = TRUE;
1219 cpu0->irq_idle_preempt[MSFC1_GT64K_IRQ] = TRUE;
1220
1221 /* Copy some parameters from VM to CPU0 (idle PC, ...) */
1222 cpu0->idle_pc = vm->idle_pc;
1223
1224 if (vm->timer_irq_check_itv)
1225 cpu0->timer_irq_check_itv = vm->timer_irq_check_itv;
1226
1227 /*
1228 * On the MSFC1, bit 33 of physical addresses is used to bypass L2 cache.
1229 * We clear it systematically.
1230 */
1231 cpu0->addr_bus_mask = MSFC1_ADDR_BUS_MASK;
1232
1233 /* Remote emulator control */
1234 dev_remote_control_init(vm,0x16000000,0x1000);
1235
1236 /* Bootflash */
1237 dev_bootflash_init(vm,"bootflash",MSFC1_BOOTFLASH_ADDR,(8 * 1048576));
1238
1239 /* NVRAM and calendar */
1240 dev_nvram_init(vm,"nvram",MSFC1_NVRAM_ADDR,
1241 vm->nvram_size*1024,&vm->conf_reg);
1242
1243 /* Bit-bucket zone */
1244 dev_zero_init(vm,"zero",MSFC1_BITBUCKET_ADDR,0xc00000);
1245
1246 /* Initialize the NPE board */
1247 if (msfc1_init_hw(router) == -1)
1248 return(-1);
1249
1250 /* Initialize RAM */
1251 vm_ram_init(vm,0x00000000ULL);
1252
1253 /* Initialize ROM */
1254 if (!vm->rom_filename) {
1255 /* use embedded ROM */
1256 dev_rom_init(vm,"rom",MSFC1_ROM_ADDR,vm->rom_size*1048576,
1257 mips64_microcode,mips64_microcode_len);
1258 } else {
1259 /* use alternate ROM */
1260 dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE,
1261 MSFC1_ROM_ADDR,vm->rom_size*1048576);
1262 }
1263
1264 /* Byte swapping */
1265 dev_bswap_init(vm,"mem_bswap",MSFC1_BSWAP_ADDR,1024*1048576,0x00000000ULL);
1266
1267 /* PCI IO space */
1268 if (!(vm->pci_io_space = pci_io_data_init(vm,MSFC1_PCI_IO_ADDR)))
1269 return(-1);
1270
1271 /* Initialize the Port Adapters */
1272 if (msfc1_init_platform_pa(router) == -1)
1273 return(-1);
1274
1275 /* Verify the check list */
1276 if (msfc1_checklist(router) == -1)
1277 return(-1);
1278
1279 /* Midplane FPGA */
1280 if (dev_msfc1_mpfpga_init(router,MSFC1_MPFPGA_ADDR,0x1000) == -1)
1281 return(-1);
1282
1283 /* IO FPGA */
1284 if (dev_msfc1_iofpga_init(router,MSFC1_IOFPGA_ADDR,0x1000) == -1)
1285 return(-1);
1286
1287 /* Show device list */
1288 msfc1_show_hardware(router);
1289 return(0);
1290 }
1291
1292 /* Boot the IOS image */
1293 static int msfc1_boot_ios(msfc1_t *router)
1294 {
1295 vm_instance_t *vm = router->vm;
1296 cpu_mips_t *cpu;
1297
1298 if (!vm->boot_cpu)
1299 return(-1);
1300
1301 /* Suspend CPU activity since we will restart directly from ROM */
1302 vm_suspend(vm);
1303
1304 /* Check that CPU activity is really suspended */
1305 if (cpu_group_sync_state(vm->cpu_group) == -1) {
1306 vm_error(vm,"unable to sync with system CPUs.\n");
1307 return(-1);
1308 }
1309
1310 /* Reset the boot CPU */
1311 cpu = CPU_MIPS64(vm->boot_cpu);
1312 mips64_reset(cpu);
1313
1314 /* Load IOS image */
1315 if (mips64_load_elf_image(cpu,vm->ios_image,
1316 (vm->ghost_status == VM_GHOST_RAM_USE),
1317 &vm->ios_entry_point) < 0)
1318 {
1319 vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
1320 return(-1);
1321 }
1322
1323 /* Launch the simulation */
1324 printf("\nMSFC1 '%s': starting simulation (CPU0 PC=0x%llx), "
1325 "JIT %sabled.\n",
1326 vm->name,cpu->pc,vm->jit_use ? "en":"dis");
1327
1328 vm_log(vm,"MSFC1_BOOT",
1329 "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
1330 cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
1331
1332 /* Start main CPU */
1333 if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
1334 vm->status = VM_STATUS_RUNNING;
1335 cpu_start(vm->boot_cpu);
1336 } else {
1337 vm->status = VM_STATUS_SHUTDOWN;
1338 }
1339 return(0);
1340 }
1341
1342 /* Initialize a MSFC1 instance */
1343 int msfc1_init_instance(msfc1_t *router)
1344 {
1345 vm_instance_t *vm = router->vm;
1346 m_uint32_t rom_entry_point;
1347 cpu_mips_t *cpu0;
1348
1349 /* Initialize the MSFC1 platform */
1350 if (msfc1_init_platform(router) == -1) {
1351 vm_error(vm,"unable to initialize the platform hardware.\n");
1352 return(-1);
1353 }
1354
1355 /* Load IOS configuration file */
1356 if (vm->ios_config != NULL) {
1357 vm_nvram_push_config(vm,vm->ios_config);
1358 vm->conf_reg &= ~0x40;
1359 }
1360
1361 /* Load ROM (ELF image or embedded) */
1362 cpu0 = CPU_MIPS64(vm->boot_cpu);
1363 rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
1364
1365 if ((vm->rom_filename != NULL) &&
1366 (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
1367 {
1368 vm_error(vm,"unable to load alternate ROM '%s', "
1369 "fallback to embedded ROM.\n\n",vm->rom_filename);
1370 vm->rom_filename = NULL;
1371 }
1372
1373 /* Load symbol file */
1374 if (vm->sym_filename) {
1375 mips64_sym_load_file(cpu0,vm->sym_filename);
1376 cpu0->sym_trace = 1;
1377 }
1378
1379 return(msfc1_boot_ios(router));
1380 }
1381
1382 /* Stop a MSFC1 instance */
1383 int msfc1_stop_instance(msfc1_t *router)
1384 {
1385 vm_instance_t *vm = router->vm;
1386
1387 printf("\nMSFC1 '%s': stopping simulation.\n",vm->name);
1388 vm_log(vm,"MSFC1_STOP","stopping simulation.\n");
1389
1390 /* Stop all CPUs */
1391 if (vm->cpu_group != NULL) {
1392 vm_stop(vm);
1393
1394 if (cpu_group_sync_state(vm->cpu_group) == -1) {
1395 vm_error(vm,"unable to sync with system CPUs.\n");
1396 return(-1);
1397 }
1398 }
1399
1400 /* Free resources that were used during execution to emulate hardware */
1401 msfc1_free_hw_ressources(router);
1402 vm_hardware_shutdown(vm);
1403 return(0);
1404 }

  ViewVC Help
Powered by ViewVC 1.1.26