/[dynamips]/trunk/dev_c6msfc1.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_c6msfc1.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Sat Oct 6 16:45:40 2007 UTC (11 years, 10 months ago) by dpavlin
File MIME type: text/plain
File size: 23897 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_c6msfc1.h"
30 #include "dev_c6msfc1_mpfpga.h"
31 #include "dev_vtty.h"
32 #include "registry.h"
33 #include "net.h"
34
35 /* MSFC1 EEPROM */
36 static m_uint16_t eeprom_msfc1_data[128] = {
37 0xabab, 0x0190, 0x1262, 0x0100, 0x0002, 0x6003, 0x00cf, 0x4369,
38 0x7363, 0x6f20, 0x5379, 0x7374, 0x656d, 0x732c, 0x2049, 0x6e63,
39 0x2e00, 0x5753, 0x2d46, 0x3630, 0x3031, 0x2d52, 0x5346, 0x4300,
40 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
41 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3733, 0x2d37, 0x3135,
42 0x302d, 0x3036, 0x0000, 0x0000, 0x0000, 0x4130, 0x3100, 0x0000,
43 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
44 0x0000, 0x0000, 0x012d, 0x0000, 0x0000, 0x0009, 0x0005, 0x0001,
45 0x0003, 0x0001, 0x0001, 0x0002, 0x00cf, 0xffbf, 0x0000, 0x0000,
46 0x6003, 0x0162, 0x0afd, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
47 0x0000, 0x0000, 0x0000, 0x0005, 0x00e0, 0xaabb, 0xcc00, 0x0100,
48 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
49 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
50 0x1401, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
51 0x1000, 0x4b3c, 0x4132, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080,
52 0x8080, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
53 };
54
55 static struct cisco_eeprom msfc1_eeprom = {
56 "msfc1", eeprom_msfc1_data, sizeof(eeprom_msfc1_data)/2,
57 };
58
59 /* ====================================================================== */
60 /* EOBC - Ethernet Out of Band Channel */
61 /* ====================================================================== */
62 static int dev_c6msfc1_eobc_init(vm_instance_t *vm,struct cisco_card *card)
63 {
64 struct dec21140_data *data;
65
66 /* Create the DEC21140 chip */
67 data = dev_dec21140_init(vm,card->dev_name,vm->pci_bus[0],6,
68 c6msfc1_net_irq_for_slot_port(0,0));
69 if (!data) return(-1);
70
71 /* Store device info into the router structure */
72 card->drv_info = data;
73 return(0);
74 }
75
76 /* Remove EOBC */
77 static int dev_c6msfc1_eobc_shutdown(vm_instance_t *vm,struct cisco_card *card)
78 {
79 struct dec21140_data *data = card->drv_info;
80 dev_dec21140_remove(data);
81 return(0);
82 }
83
84 /* Bind a Network IO descriptor */
85 static int dev_c6msfc1_eobc_set_nio(vm_instance_t *vm,struct cisco_card *card,
86 u_int port_id,netio_desc_t *nio)
87 {
88 struct dec21140_data *d = card->drv_info;
89
90 if (!d || (port_id != 0))
91 return(-1);
92
93 return(dev_dec21140_set_nio(d,nio));
94 }
95
96 /* Unbind a Network IO descriptor */
97 static int dev_c6msfc1_eobc_unset_nio(vm_instance_t *vm,
98 struct cisco_card *card,
99 u_int port_id)
100 {
101 struct dec21140_data *d = card->drv_info;
102
103 if (!d || (port_id != 0))
104 return(-1);
105
106 dev_dec21140_unset_nio(d);
107 return(0);
108 }
109
110 /* EOBC driver */
111 struct cisco_card_driver dev_c6msfc1_eobc = {
112 "C6MSFC1_EOBC", 0, 0,
113 dev_c6msfc1_eobc_init,
114 dev_c6msfc1_eobc_shutdown,
115 NULL,
116 dev_c6msfc1_eobc_set_nio,
117 dev_c6msfc1_eobc_unset_nio,
118 NULL,
119 };
120
121 /* ====================================================================== */
122 /* IBC - InBand Channel */
123 /* ====================================================================== */
124 static int dev_c6msfc1_ibc_init(vm_instance_t *vm,struct cisco_card *card)
125 {
126 struct i8254x_data *data;
127
128 /* Create the Intel Wiseman/Livengood chip */
129 data = dev_i8254x_init(vm,card->dev_name,0,vm->pci_bus_pool[24],1,
130 c6msfc1_net_irq_for_slot_port(1,0));
131 if (!data) return(-1);
132
133 /* Store device info into the router structure */
134 card->drv_info = data;
135 return(0);
136 }
137
138 /* Remove EOBC */
139 static int dev_c6msfc1_ibc_shutdown(vm_instance_t *vm,struct cisco_card *card)
140 {
141 struct i8254x_data *data = card->drv_info;
142 dev_i8254x_remove(data);
143 return(0);
144 }
145
146 /* Bind a Network IO descriptor */
147 static int dev_c6msfc1_ibc_set_nio(vm_instance_t *vm,struct cisco_card *card,
148 u_int port_id,netio_desc_t *nio)
149 {
150 struct i8254x_data *d = card->drv_info;
151
152 if (!d || (port_id != 0))
153 return(-1);
154
155 return(dev_i8254x_set_nio(d,nio));
156 }
157
158 /* Unbind a Network IO descriptor */
159 static int dev_c6msfc1_ibc_unset_nio(vm_instance_t *vm,
160 struct cisco_card *card,
161 u_int port_id)
162 {
163 struct i8254x_data *d = card->drv_info;
164
165 if (!d || (port_id != 0))
166 return(-1);
167
168 dev_i8254x_unset_nio(d);
169 return(0);
170 }
171
172 /* IBC driver */
173 struct cisco_card_driver dev_c6msfc1_ibc = {
174 "C6MSFC1_IBC", 0, 0,
175 dev_c6msfc1_ibc_init,
176 dev_c6msfc1_ibc_shutdown,
177 NULL,
178 dev_c6msfc1_ibc_set_nio,
179 dev_c6msfc1_ibc_unset_nio,
180 NULL,
181 };
182
183 /* ======================================================================== */
184 /* Port Adapter Drivers */
185 /* ======================================================================== */
186 static struct cisco_card_driver *pa_drivers[] = {
187 &dev_c6msfc1_eobc,
188 &dev_c6msfc1_ibc,
189 NULL,
190 };
191
192 /* ======================================================================== */
193 /* C6MSFC1 router instances */
194 /* ======================================================================== */
195
196 /* Initialize default parameters for a MSFC1 */
197 static void c6msfc1_init_defaults(c6msfc1_t *router);
198
199 /* Directly extract the configuration from the NVRAM device */
200 static ssize_t c6msfc1_nvram_extract_config(vm_instance_t *vm,u_char **buffer)
201 {
202 u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;
203 m_uint32_t start,end,nvlen,clen;
204 m_uint16_t magic1,magic2;
205 struct vdevice *nvram_dev;
206 m_uint64_t nvram_addr;
207 off_t nvram_size;
208 int fd;
209
210 if ((nvram_dev = dev_get_by_name(vm,"nvram")))
211 dev_sync(nvram_dev);
212
213 fd = vm_mmap_open_file(vm,"nvram",&base_ptr,&nvram_size);
214
215 if (fd == -1)
216 return(-1);
217
218 nvram_addr = C6MSFC1_NVRAM_ADDR;
219 ios_ptr = base_ptr + vm->nvram_rom_space;
220 end_ptr = base_ptr + nvram_size;
221
222 if ((ios_ptr + 0x30) >= end_ptr) {
223 vm_error(vm,"NVRAM file too small\n");
224 return(-1);
225 }
226
227 magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06));
228 magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08));
229
230 if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) {
231 vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n",
232 magic1,magic2);
233 return(-1);
234 }
235
236 start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1;
237 end = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x14));
238 nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18));
239 clen = end - start;
240
241 if ((clen + 1) != nvlen) {
242 vm_error(vm,"invalid configuration size (0x%x)\n",nvlen);
243 return(-1);
244 }
245
246 if (!(*buffer = malloc(clen+1))) {
247 vm_error(vm,"unable to allocate config buffer (%u bytes)\n",clen);
248 return(-1);
249 }
250
251 cfg_ptr = base_ptr + (start - nvram_addr);
252
253 if ((start < nvram_addr) || ((cfg_ptr + clen) > end_ptr)) {
254 vm_error(vm,"NVRAM file too small\n");
255 return(-1);
256 }
257
258 memcpy(*buffer,cfg_ptr,clen);
259 (*buffer)[clen] = 0;
260 return(clen);
261 }
262
263 /* Directly push the IOS configuration to the NVRAM device */
264 static int c6msfc1_nvram_push_config(vm_instance_t *vm,
265 u_char *buffer,size_t len)
266 {
267 u_char *base_ptr,*ios_ptr,*cfg_ptr;
268 m_uint32_t cfg_addr,cfg_offset;
269 m_uint32_t nvram_addr,cklen;
270 m_uint16_t cksum;
271 int fd;
272
273 fd = vm_mmap_create_file(vm,"nvram",vm->nvram_size*1024,&base_ptr);
274
275 if (fd == -1)
276 return(-1);
277
278 cfg_offset = 0x2c;
279 ios_ptr = base_ptr + vm->nvram_rom_space;
280 cfg_ptr = ios_ptr + cfg_offset;
281
282 nvram_addr = C6MSFC1_NVRAM_ADDR;
283 cfg_addr = nvram_addr + vm->nvram_rom_space + cfg_offset;
284
285 /* Write IOS tag, uncompressed config... */
286 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5);
287 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD);
288 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001);
289 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000);
290 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0000);
291
292 /* Store file contents to NVRAM */
293 memcpy(cfg_ptr,buffer,len);
294
295 /* Write config addresses + size */
296 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(cfg_addr);
297 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(cfg_addr + len);
298 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len);
299
300 /* Compute the checksum */
301 cklen = (vm->nvram_size*1024) - (vm->nvram_rom_space + 0x08);
302 cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen);
303 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum);
304
305 vm_mmap_close_file(fd,base_ptr,vm->nvram_size*1024);
306 return(0);
307 }
308
309 /* Get slot/port corresponding to specified network IRQ */
310 static inline void
311 c6msfc1_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port)
312 {
313 *slot = irq - C6MSFC1_NETIO_IRQ_BASE;
314 *port = 0;
315 }
316
317 /* Get network IRQ for specified slot/port */
318 u_int c6msfc1_net_irq_for_slot_port(u_int slot,u_int port)
319 {
320 u_int irq;
321
322 irq = C6MSFC1_NETIO_IRQ_BASE + slot;
323 return(irq);
324 }
325
326 /* Set MSFC eeprom definition */
327 static int c6msfc1_set_eeprom(c6msfc1_t *router)
328 {
329 if (cisco_eeprom_copy(&router->cpu_eeprom,&msfc1_eeprom) == -1) {
330 vm_error(router->vm,"unable to set NPE EEPROM.\n");
331 return(-1);
332 }
333
334 return(0);
335 }
336
337 /* Set the base MAC address of the chassis */
338 static int c6msfc1_burn_mac_addr(c6msfc1_t *router,n_eth_addr_t *addr)
339 {
340 m_uint8_t eeprom_ver;
341
342 /* Read EEPROM format version */
343 cisco_eeprom_get_byte(&router->mp_eeprom,0,&eeprom_ver);
344
345 if (eeprom_ver != 1) {
346 vm_error(router->vm,"c6msfc1_burn_mac_addr: unable to handle "
347 "EEPROM version %u\n",eeprom_ver);
348 return(-1);
349 }
350
351 cisco_eeprom_set_region(&router->mp_eeprom,12,addr->eth_addr_byte,6);
352 return(0);
353 }
354
355 /* Create a new router instance */
356 static int c6msfc1_create_instance(vm_instance_t *vm)
357 {
358 c6msfc1_t *router;
359
360 if (!(router = malloc(sizeof(*router)))) {
361 fprintf(stderr,"C6MFC1 '%s': Unable to create new instance!\n",vm->name);
362 return(-1);
363 }
364
365 memset(router,0,sizeof(*router));
366 router->vm = vm;
367 vm->hw_data = router;
368 vm->elf_machine_id = C6MSFC1_ELF_MACHINE_ID;
369
370 c6msfc1_init_defaults(router);
371 return(0);
372 }
373
374 /* Free resources used by a router instance */
375 static int c6msfc1_delete_instance(vm_instance_t *vm)
376 {
377 c6msfc1_t *router = VM_C6MSFC1(vm);
378 int i;
379
380 /* Stop all CPUs */
381 if (vm->cpu_group != NULL) {
382 vm_stop(vm);
383
384 if (cpu_group_sync_state(vm->cpu_group) == -1) {
385 vm_error(vm,"unable to sync with system CPUs.\n");
386 return(FALSE);
387 }
388 }
389
390 /* Remove NIO bindings */
391 for(i=0;i<C6MSFC1_MAX_PA_BAYS;i++)
392 vm_slot_remove_all_nio_bindings(vm,i);
393
394 /* Shutdown all Network Modules */
395 vm_slot_shutdown_all(vm);
396
397 /* Free EEPROMs */
398 cisco_eeprom_free(&router->cpu_eeprom);
399 cisco_eeprom_free(&router->mp_eeprom);
400 cisco_eeprom_free(&router->pem_eeprom);
401
402 /* Free all resources used by VM */
403 vm_free(vm);
404
405 /* Free the router structure */
406 free(router);
407 return(TRUE);
408 }
409
410 /* Create the main PCI bus for a GT64010 based system */
411 static int c6msfc1_init_gt64010(c6msfc1_t *router)
412 {
413 vm_instance_t *vm = router->vm;
414
415 if (!(vm->pci_bus[0] = pci_bus_create("PCI Bus 0",0))) {
416 vm_error(vm,"unable to create PCI data.\n");
417 return(-1);
418 }
419
420 return(dev_gt64010_init(vm,"gt64010",C6MSFC1_GT64K_ADDR,0x1000,
421 C6MSFC1_GT64K_IRQ));
422 }
423
424 /* Initialize a MSFC1 board */
425 static int c6msfc1_init_hw(c6msfc1_t *router)
426 {
427 vm_instance_t *vm = router->vm;
428
429 /* Set the processor type: R5000 */
430 mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R5000);
431
432 /* Initialize the Galileo GT-64010 PCI controller */
433 if (c6msfc1_init_gt64010(router) == -1)
434 return(-1);
435
436 /* Create PCI bus 1 */
437 vm->pci_bus_pool[24] = pci_bus_create("PCI Bus 1",-1);
438 dev_dec21154_init(vm->pci_bus[0],1,vm->pci_bus_pool[24]);
439
440 /* Initialize SRAM (4Mb) */
441 dev_c7200_sram_init(vm,"sram",C6MSFC1_SRAM_ADDR,C6MSFC1_SRAM_SIZE,
442 vm->pci_bus_pool[24],0);
443
444 /* PCI IO space */
445 if (!(vm->pci_io_space = pci_io_data_init(vm,C6MSFC1_PCI_IO_ADDR)))
446 return(-1);
447
448 /* Cirrus Logic PD6729 (PCI-to-PCMCIA host adapter) */
449 dev_clpd6729_init(vm,vm->pci_bus[0],5,vm->pci_io_space,0x402,0x403);
450
451 return(0);
452 }
453
454 /* Show MSFC1 hardware info */
455 void c6msfc1_show_hardware(c6msfc1_t *router)
456 {
457 vm_instance_t *vm = router->vm;
458
459 printf("C6MSFC1 instance '%s' (id %d):\n",vm->name,vm->instance_id);
460
461 printf(" VM Status : %d\n",vm->status);
462 printf(" RAM size : %u Mb\n",vm->ram_size);
463 printf(" IOMEM size : %u Mb\n",vm->iomem_size);
464 printf(" NVRAM size : %u Kb\n",vm->nvram_size);
465 printf(" IOS image : %s\n\n",vm->ios_image);
466
467 if (vm->debug_level > 0) {
468 dev_show_list(vm);
469 pci_dev_show_list(vm->pci_bus[0]);
470 pci_dev_show_list(vm->pci_bus[1]);
471 printf("\n");
472 }
473 }
474
475 /* Initialize default parameters for a MSFC1 */
476 static void c6msfc1_init_defaults(c6msfc1_t *router)
477 {
478 vm_instance_t *vm = router->vm;
479 n_eth_addr_t *m;
480 m_uint16_t pid;
481
482 /* Set platform slots characteristics */
483 vm->nr_slots = C6MSFC1_MAX_PA_BAYS;
484 vm->slots_type = CISCO_CARD_TYPE_PA;
485 vm->slots_drivers = pa_drivers;
486
487 pid = (m_uint16_t)getpid();
488
489 /* Generate a chassis MAC address based on the instance ID */
490 m = &router->mac_addr;
491 m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
492 m->eth_addr_byte[1] = vm->instance_id & 0xFF;
493 m->eth_addr_byte[2] = pid >> 8;
494 m->eth_addr_byte[3] = pid & 0xFF;
495 m->eth_addr_byte[4] = 0x00;
496 m->eth_addr_byte[5] = 0x00;
497
498 /* Default slot: 1 */
499 router->msfc_slot = 1;
500
501 c6msfc1_set_eeprom(router);
502 c6msfc1_init_eeprom_groups(router);
503
504 /* Create EOBC and IBC interfaces */
505 vm_slot_add_binding(vm,"C6MSFC1_EOBC",0,0);
506 vm_slot_add_binding(vm,"C6MSFC1_IBC",1,0);
507
508 vm->ram_mmap = C6MSFC1_DEFAULT_RAM_MMAP;
509 vm->ram_size = C6MSFC1_DEFAULT_RAM_SIZE;
510 vm->rom_size = C6MSFC1_DEFAULT_ROM_SIZE;
511 vm->nvram_size = C6MSFC1_DEFAULT_NVRAM_SIZE;
512 vm->iomem_size = 0;
513 vm->conf_reg_setup = C6MSFC1_DEFAULT_CONF_REG;
514 vm->clock_divisor = C6MSFC1_DEFAULT_CLOCK_DIV;
515 vm->nvram_rom_space = C6MSFC1_NVRAM_ROM_RES_SIZE;
516 }
517
518 /* Run the checklist */
519 static int c6msfc1_checklist(c6msfc1_t *router)
520 {
521 struct vm_instance *vm = router->vm;
522 int res = 0;
523
524 res += vm_object_check(vm,"ram");
525 res += vm_object_check(vm,"rom");
526 res += vm_object_check(vm,"nvram");
527 res += vm_object_check(vm,"zero");
528
529 if (res < 0)
530 vm_error(vm,"incomplete initialization (no memory?)\n");
531
532 return(res);
533 }
534
535 /* Initialize Port Adapters */
536 static int c6msfc1_init_platform_pa(c6msfc1_t *router)
537 {
538 return(vm_slot_init_all(router->vm));
539 }
540
541 /* Initialize the MSFC1 Platform */
542 static int c6msfc1_init_platform(c6msfc1_t *router)
543 {
544 struct vm_instance *vm = router->vm;
545 cpu_mips_t *cpu0;
546 cpu_gen_t *gen0;
547 vm_obj_t *obj;
548
549 /* Copy config register setup into "active" config register */
550 vm->conf_reg = vm->conf_reg_setup;
551
552 /* Create Console and AUX ports */
553 vm_init_vtty(vm);
554
555 /* Create a CPU group */
556 vm->cpu_group = cpu_group_create("System CPU");
557
558 /* Initialize the virtual MIPS processor */
559 if (!(gen0 = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
560 vm_error(vm,"unable to create CPU0!\n");
561 return(-1);
562 }
563
564 cpu0 = CPU_MIPS64(gen0);
565
566 /* Add this CPU to the system CPU group */
567 cpu_group_add(vm->cpu_group,gen0);
568 vm->boot_cpu = gen0;
569
570 /* Initialize the IRQ routing vectors */
571 vm->set_irq = mips64_vm_set_irq;
572 vm->clear_irq = mips64_vm_clear_irq;
573
574 /* Mark the Network IO interrupt as high priority */
575 cpu0->irq_idle_preempt[C6MSFC1_NETIO_IRQ] = TRUE;
576 cpu0->irq_idle_preempt[C6MSFC1_GT64K_IRQ] = TRUE;
577
578 /* Copy some parameters from VM to CPU0 (idle PC, ...) */
579 cpu0->idle_pc = vm->idle_pc;
580
581 if (vm->timer_irq_check_itv)
582 cpu0->timer_irq_check_itv = vm->timer_irq_check_itv;
583
584 /*
585 * On the MSFC1, bit 33 of physical addresses is used to bypass L2 cache.
586 * We clear it systematically.
587 */
588 cpu0->addr_bus_mask = C6MSFC1_ADDR_BUS_MASK;
589
590 /* Remote emulator control */
591 dev_remote_control_init(vm,0x16000000,0x1000);
592
593 /* Bootflash (8 Mb) */
594 dev_bootflash_init(vm,"bootflash","c7200-bootflash-8mb",
595 C6MSFC1_BOOTFLASH_ADDR);
596
597 /* NVRAM and calendar */
598 dev_nvram_init(vm,"nvram",C6MSFC1_NVRAM_ADDR,
599 vm->nvram_size*1024,&vm->conf_reg);
600
601 /* Bit-bucket zone */
602 dev_zero_init(vm,"zero",C6MSFC1_BITBUCKET_ADDR,0xc00000);
603
604 /* Initialize the NPE board */
605 if (c6msfc1_init_hw(router) == -1)
606 return(-1);
607
608 /* Initialize RAM */
609 vm_ram_init(vm,0x00000000ULL);
610
611 /* Initialize ROM */
612 if (!vm->rom_filename) {
613 /* use embedded ROM */
614 dev_rom_init(vm,"rom",C6MSFC1_ROM_ADDR,vm->rom_size*1048576,
615 mips64_microcode,mips64_microcode_len);
616 } else {
617 /* use alternate ROM */
618 dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE,
619 C6MSFC1_ROM_ADDR,vm->rom_size*1048576);
620 }
621
622 /* Byte swapping */
623 dev_bswap_init(vm,"mem_bswap",C6MSFC1_BSWAP_ADDR,1024*1048576,0x00000000ULL);
624
625 /* PCI IO space */
626 if (!(vm->pci_io_space = pci_io_data_init(vm,C6MSFC1_PCI_IO_ADDR)))
627 return(-1);
628
629 /* Initialize the Port Adapters */
630 if (c6msfc1_init_platform_pa(router) == -1)
631 return(-1);
632
633 /* Verify the check list */
634 if (c6msfc1_checklist(router) == -1)
635 return(-1);
636
637 /* Midplane FPGA */
638 if (dev_c6msfc1_mpfpga_init(router,C6MSFC1_MPFPGA_ADDR,0x1000) == -1)
639 return(-1);
640
641 if (!(obj = vm_object_find(router->vm,"mp_fpga")))
642 return(-1);
643
644 router->mpfpga_data = obj->data;
645
646 /* IO FPGA */
647 if (dev_c6msfc1_iofpga_init(router,C6MSFC1_IOFPGA_ADDR,0x1000) == -1)
648 return(-1);
649
650 /* Show device list */
651 c6msfc1_show_hardware(router);
652 return(0);
653 }
654
655 /* Boot the IOS image */
656 static int c6msfc1_boot_ios(c6msfc1_t *router)
657 {
658 vm_instance_t *vm = router->vm;
659 cpu_mips_t *cpu;
660
661 if (!vm->boot_cpu)
662 return(-1);
663
664 /* Suspend CPU activity since we will restart directly from ROM */
665 vm_suspend(vm);
666
667 /* Check that CPU activity is really suspended */
668 if (cpu_group_sync_state(vm->cpu_group) == -1) {
669 vm_error(vm,"unable to sync with system CPUs.\n");
670 return(-1);
671 }
672
673 /* Reset the boot CPU */
674 cpu = CPU_MIPS64(vm->boot_cpu);
675 mips64_reset(cpu);
676
677 /* Load IOS image */
678 if (mips64_load_elf_image(cpu,vm->ios_image,
679 (vm->ghost_status == VM_GHOST_RAM_USE),
680 &vm->ios_entry_point) < 0)
681 {
682 vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
683 return(-1);
684 }
685
686 /* Launch the simulation */
687 printf("\nC6MSFC1 '%s': starting simulation (CPU0 PC=0x%llx), "
688 "JIT %sabled.\n",
689 vm->name,cpu->pc,vm->jit_use ? "en":"dis");
690
691 vm_log(vm,"C6MSFC1_BOOT",
692 "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
693 cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
694
695 /* Start main CPU */
696 if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
697 vm->status = VM_STATUS_RUNNING;
698 cpu_start(vm->boot_cpu);
699 } else {
700 vm->status = VM_STATUS_SHUTDOWN;
701 }
702 return(0);
703 }
704
705 /* Set an IRQ */
706 static void c6msfc1_set_irq(vm_instance_t *vm,u_int irq)
707 {
708 c6msfc1_t *router = VM_C6MSFC1(vm);
709 cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
710 u_int slot,port;
711
712 switch(irq) {
713 case 0 ... 7:
714 mips64_set_irq(cpu0,irq);
715
716 if (cpu0->irq_idle_preempt[irq])
717 cpu_idle_break_wait(cpu0->gen);
718 break;
719
720 case C6MSFC1_NETIO_IRQ_BASE ... C6MSFC1_NETIO_IRQ_END:
721 c6msfc1_net_irq_get_slot_port(irq,&slot,&port);
722 dev_c6msfc1_mpfpga_net_set_irq(router->mpfpga_data,slot,port);
723 break;
724 }
725 }
726
727 /* Clear an IRQ */
728 static void c6msfc1_clear_irq(vm_instance_t *vm,u_int irq)
729 {
730 c6msfc1_t *router = VM_C6MSFC1(vm);
731 cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
732 u_int slot,port;
733
734 switch(irq) {
735 case 0 ... 7:
736 mips64_clear_irq(cpu0,irq);
737 break;
738
739 case C6MSFC1_NETIO_IRQ_BASE ... C6MSFC1_NETIO_IRQ_END:
740 c6msfc1_net_irq_get_slot_port(irq,&slot,&port);
741 dev_c6msfc1_mpfpga_net_clear_irq(router->mpfpga_data,slot,port);
742 break;
743 }
744 }
745
746 /* Initialize a MSFC1 instance */
747 static int c6msfc1_init_instance(vm_instance_t *vm)
748 {
749 c6msfc1_t *router = VM_C6MSFC1(vm);
750 m_uint32_t rom_entry_point;
751 cpu_mips_t *cpu0;
752
753 /* Initialize the MSFC1 platform */
754 if (c6msfc1_init_platform(router) == -1) {
755 vm_error(vm,"unable to initialize the platform hardware.\n");
756 return(-1);
757 }
758
759 /* IRQ routing */
760 vm->set_irq = c6msfc1_set_irq;
761 vm->clear_irq = c6msfc1_clear_irq;
762
763 /* Load IOS configuration file */
764 if (vm->ios_config != NULL) {
765 vm_nvram_push_config(vm,vm->ios_config);
766 vm->conf_reg &= ~0x40;
767 }
768
769 /* Load ROM (ELF image or embedded) */
770 cpu0 = CPU_MIPS64(vm->boot_cpu);
771 rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
772
773 if ((vm->rom_filename != NULL) &&
774 (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
775 {
776 vm_error(vm,"unable to load alternate ROM '%s', "
777 "fallback to embedded ROM.\n\n",vm->rom_filename);
778 vm->rom_filename = NULL;
779 }
780
781 /* Load symbol file */
782 if (vm->sym_filename) {
783 mips64_sym_load_file(cpu0,vm->sym_filename);
784 cpu0->sym_trace = 1;
785 }
786
787 return(c6msfc1_boot_ios(router));
788 }
789
790 /* Stop a MSFC1 instance */
791 static int c6msfc1_stop_instance(vm_instance_t *vm)
792 {
793 printf("\nC6MSFC1 '%s': stopping simulation.\n",vm->name);
794 vm_log(vm,"C6MSFC1_STOP","stopping simulation.\n");
795
796 /* Stop all CPUs */
797 if (vm->cpu_group != NULL) {
798 vm_stop(vm);
799
800 if (cpu_group_sync_state(vm->cpu_group) == -1) {
801 vm_error(vm,"unable to sync with system CPUs.\n");
802 return(-1);
803 }
804 }
805
806 /* Free resources that were used during execution to emulate hardware */
807 vm_slot_shutdown_all(vm);
808 vm_hardware_shutdown(vm);
809 return(0);
810 }
811
812 /* Get MAC address MSB */
813 static u_int c6msfc1_get_mac_addr_msb(void)
814 {
815 return(0xC6);
816 }
817
818 /* Show specific CLI options */
819 static void c6msfc1_cli_show_options(vm_instance_t *vm)
820 {
821 printf(" -s <pa_nio> : Bind a Network IO interface to a "
822 "Port Adapter\n");
823 }
824
825 /* Platform definition */
826 static vm_platform_t c6msfc1_platform = {
827 "c6msfc1", "C6MSFC1", "C6MSFC1",
828 c6msfc1_create_instance,
829 c6msfc1_delete_instance,
830 c6msfc1_init_instance,
831 c6msfc1_stop_instance,
832 c6msfc1_nvram_extract_config,
833 c6msfc1_nvram_push_config,
834 c6msfc1_get_mac_addr_msb,
835 NULL,
836 NULL,
837 c6msfc1_cli_show_options,
838 NULL,
839 };
840
841 /* Register the C6-MSFC1 platform */
842 int c6msfc1_platform_register(void)
843 {
844 return(vm_platform_register(&c6msfc1_platform));
845 }

  ViewVC Help
Powered by ViewVC 1.1.26