/[dynamips]/trunk/dev_c6sup1.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_c6sup1.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2007 Christophe Fillot (cf@utc.fr)
4 *
5 * Generic C6k-SUP1 routines and definitions (EEPROM,...).
6 *
7 * This is not a working platform! I only added it to play.
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <assert.h>
16
17 #include "cpu.h"
18 #include "vm.h"
19 #include "dynamips.h"
20 #include "memory.h"
21 #include "device.h"
22 #include "pci_io.h"
23 #include "dev_gt.h"
24 #include "cisco_eeprom.h"
25 #include "dev_rom.h"
26 #include "dev_am79c971.h"
27 #include "dev_i8254x.h"
28 #include "dev_c6sup1.h"
29 #include "dev_c6sup1_mpfpga.h"
30 #include "dev_vtty.h"
31 #include "registry.h"
32 #include "net.h"
33
34 /* ====================================================================== */
35 /* EOBC - Ethernet Out of Band Channel */
36 /* ====================================================================== */
37 static int dev_c6sup1_eobc_init(vm_instance_t *vm,struct cisco_card *card)
38 {
39 struct am79c971_data *data;
40
41 /* Create the AMD 79c970 chip */
42 data = dev_am79c971_init(vm,card->dev_name,AM79C971_TYPE_100BASE_TX,
43 vm->pci_bus[0],6,
44 3/*c6sup1_net_irq_for_slot_port(0,0)*/);
45 if (!data) return(-1);
46
47 /* Store device info into the router structure */
48 card->drv_info = data;
49 return(0);
50 }
51
52 /* Remove EOBC */
53 static int dev_c6sup1_eobc_shutdown(vm_instance_t *vm,struct cisco_card *card)
54 {
55 struct am79c971_data *data = card->drv_info;
56 dev_am79c971_remove(data);
57 return(0);
58 }
59
60 /* Bind a Network IO descriptor */
61 static int dev_c6sup1_eobc_set_nio(vm_instance_t *vm,struct cisco_card *card,
62 u_int port_id,netio_desc_t *nio)
63 {
64 struct am79c971_data *d = card->drv_info;
65
66 if (!d || (port_id != 0))
67 return(-1);
68
69 return(dev_am79c971_set_nio(d,nio));
70 }
71
72 /* Unbind a Network IO descriptor */
73 static int dev_c6sup1_eobc_unset_nio(vm_instance_t *vm,
74 struct cisco_card *card,
75 u_int port_id)
76 {
77 struct am79c971_data *d = card->drv_info;
78
79 if (!d || (port_id != 0))
80 return(-1);
81
82 dev_am79c971_unset_nio(d);
83 return(0);
84 }
85
86 /* EOBC driver */
87 struct cisco_card_driver dev_c6sup1_eobc = {
88 "C6SUP1_EOBC", 0, 0,
89 dev_c6sup1_eobc_init,
90 dev_c6sup1_eobc_shutdown,
91 NULL,
92 dev_c6sup1_eobc_set_nio,
93 dev_c6sup1_eobc_unset_nio,
94 NULL,
95 };
96
97 /* ====================================================================== */
98 /* IBC - InBand Channel */
99 /* ====================================================================== */
100 static int dev_c6sup1_ibc_init(vm_instance_t *vm,struct cisco_card *card)
101 {
102 struct i8254x_data *data;
103
104 /* Create the Intel Wiseman/Livengood chip */
105 data = dev_i8254x_init(vm,card->dev_name,0,vm->pci_bus[0],7,
106 2/*c6sup1_net_irq_for_slot_port(1,0)*/);
107 if (!data) return(-1);
108
109 /* Store device info into the router structure */
110 card->drv_info = data;
111 return(0);
112 }
113
114 /* Remove EOBC */
115 static int dev_c6sup1_ibc_shutdown(vm_instance_t *vm,struct cisco_card *card)
116 {
117 struct i8254x_data *data = card->drv_info;
118 dev_i8254x_remove(data);
119 return(0);
120 }
121
122 /* Bind a Network IO descriptor */
123 static int dev_c6sup1_ibc_set_nio(vm_instance_t *vm,struct cisco_card *card,
124 u_int port_id,netio_desc_t *nio)
125 {
126 struct i8254x_data *d = card->drv_info;
127
128 if (!d || (port_id != 0))
129 return(-1);
130
131 return(dev_i8254x_set_nio(d,nio));
132 }
133
134 /* Unbind a Network IO descriptor */
135 static int dev_c6sup1_ibc_unset_nio(vm_instance_t *vm,
136 struct cisco_card *card,
137 u_int port_id)
138 {
139 struct i8254x_data *d = card->drv_info;
140
141 if (!d || (port_id != 0))
142 return(-1);
143
144 dev_i8254x_unset_nio(d);
145 return(0);
146 }
147
148 /* IBC driver */
149 struct cisco_card_driver dev_c6sup1_ibc = {
150 "C6SUP1_IBC", 0, 0,
151 dev_c6sup1_ibc_init,
152 dev_c6sup1_ibc_shutdown,
153 NULL,
154 dev_c6sup1_ibc_set_nio,
155 dev_c6sup1_ibc_unset_nio,
156 NULL,
157 };
158
159 /* ======================================================================== */
160 /* Port Adapter Drivers */
161 /* ======================================================================== */
162 static struct cisco_card_driver *pa_drivers[] = {
163 &dev_c6sup1_eobc,
164 &dev_c6sup1_ibc,
165 NULL,
166 };
167
168 /* ======================================================================== */
169 /* C6SUP1 router instances */
170 /* ======================================================================== */
171
172 /* Initialize default parameters for a SUP1 */
173 static void c6sup1_init_defaults(c6sup1_t *router);
174
175 /* Directly extract the configuration from the NVRAM device */
176 static ssize_t c6sup1_nvram_extract_config(vm_instance_t *vm,u_char **buffer)
177 {
178 u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;
179 m_uint32_t start,end,nvlen,clen;
180 m_uint16_t magic1,magic2;
181 struct vdevice *nvram_dev;
182 m_uint64_t nvram_addr;
183 off_t nvram_size;
184 int fd;
185
186 if ((nvram_dev = dev_get_by_name(vm,"nvram")))
187 dev_sync(nvram_dev);
188
189 fd = vm_mmap_open_file(vm,"nvram",&base_ptr,&nvram_size);
190
191 if (fd == -1)
192 return(-1);
193
194 nvram_addr = C6SUP1_NVRAM_ADDR;
195 ios_ptr = base_ptr + vm->nvram_rom_space;
196 end_ptr = base_ptr + nvram_size;
197
198 if ((ios_ptr + 0x30) >= end_ptr) {
199 vm_error(vm,"NVRAM file too small\n");
200 return(-1);
201 }
202
203 magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06));
204 magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08));
205
206 if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) {
207 vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n",
208 magic1,magic2);
209 return(-1);
210 }
211
212 start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1;
213 end = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x14));
214 nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18));
215 clen = end - start;
216
217 if ((clen + 1) != nvlen) {
218 vm_error(vm,"invalid configuration size (0x%x)\n",nvlen);
219 return(-1);
220 }
221
222 if (!(*buffer = malloc(clen+1))) {
223 vm_error(vm,"unable to allocate config buffer (%u bytes)\n",clen);
224 return(-1);
225 }
226
227 cfg_ptr = base_ptr + (start - nvram_addr);
228
229 if ((start < nvram_addr) || ((cfg_ptr + clen) > end_ptr)) {
230 vm_error(vm,"NVRAM file too small\n");
231 return(-1);
232 }
233
234 memcpy(*buffer,cfg_ptr,clen);
235 (*buffer)[clen] = 0;
236 return(clen);
237 }
238
239 /* Directly push the IOS configuration to the NVRAM device */
240 static int c6sup1_nvram_push_config(vm_instance_t *vm,
241 u_char *buffer,size_t len)
242 {
243 u_char *base_ptr,*ios_ptr,*cfg_ptr;
244 m_uint32_t cfg_addr,cfg_offset;
245 m_uint32_t nvram_addr,cklen;
246 m_uint16_t cksum;
247 int fd;
248
249 fd = vm_mmap_create_file(vm,"nvram",vm->nvram_size*1024,&base_ptr);
250
251 if (fd == -1)
252 return(-1);
253
254 cfg_offset = 0x2c;
255 ios_ptr = base_ptr + vm->nvram_rom_space;
256 cfg_ptr = ios_ptr + cfg_offset;
257
258 nvram_addr = C6SUP1_NVRAM_ADDR;
259 cfg_addr = nvram_addr + vm->nvram_rom_space + cfg_offset;
260
261 /* Write IOS tag, uncompressed config... */
262 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5);
263 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD);
264 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001);
265 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000);
266 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0000);
267
268 /* Store file contents to NVRAM */
269 memcpy(cfg_ptr,buffer,len);
270
271 /* Write config addresses + size */
272 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(cfg_addr);
273 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(cfg_addr + len);
274 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len);
275
276 /* Compute the checksum */
277 cklen = (vm->nvram_size*1024) - (vm->nvram_rom_space + 0x08);
278 cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen);
279 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum);
280
281 vm_mmap_close_file(fd,base_ptr,vm->nvram_size*1024);
282 return(0);
283 }
284
285 /* Get slot/port corresponding to specified network IRQ */
286 static inline void
287 c6sup1_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port)
288 {
289 *slot = irq - C6SUP1_NETIO_IRQ_BASE;
290 *port = 0;
291 }
292
293 /* Get network IRQ for specified slot/port */
294 u_int c6sup1_net_irq_for_slot_port(u_int slot,u_int port)
295 {
296 u_int irq;
297
298 irq = C6SUP1_NETIO_IRQ_BASE + slot;
299 return(irq);
300 }
301
302 /* Free specific hardware resources used by a SUP1 */
303 static void c6sup1_free_hw_ressources(c6sup1_t *router)
304 {
305 /* Shutdown all Port Adapters */
306 vm_slot_shutdown_all(router->vm);
307 }
308
309 /* Create a new router instance */
310 static int c6sup1_create_instance(vm_instance_t *vm)
311 {
312 c6sup1_t *router;
313
314 if (!(router = malloc(sizeof(*router)))) {
315 fprintf(stderr,"C6SUP1 '%s': Unable to create new instance!\n",vm->name);
316 return(-1);
317 }
318
319 memset(router,0,sizeof(*router));
320 router->vm = vm;
321 vm->hw_data = router;
322 vm->elf_machine_id = C6SUP1_ELF_MACHINE_ID;
323
324 c6sup1_init_defaults(router);
325 return(0);
326 }
327
328 /* Free resources used by a router instance */
329 static int c6sup1_delete_instance(vm_instance_t *vm)
330 {
331 c6sup1_t *router = VM_C6SUP1(vm);
332 int i;
333
334 /* Stop all CPUs */
335 if (vm->cpu_group != NULL) {
336 vm_stop(vm);
337
338 if (cpu_group_sync_state(vm->cpu_group) == -1) {
339 vm_error(vm,"unable to sync with system CPUs.\n");
340 return(FALSE);
341 }
342 }
343
344 /* Remove NIO bindings */
345 for(i=0;i<C6SUP1_MAX_PA_BAYS;i++)
346 vm_slot_remove_all_nio_bindings(vm,i);
347
348 /* Free specific HW resources */
349 c6sup1_free_hw_ressources(router);
350
351 /* Free all resources used by VM */
352 vm_free(vm);
353
354 /* Free the router structure */
355 free(router);
356 return(TRUE);
357 }
358
359 /* Create the main PCI bus for a GT64010 based system */
360 static int c6sup1_init_gt64010(c6sup1_t *router)
361 {
362 vm_instance_t *vm = router->vm;
363
364 if (!(vm->pci_bus[0] = pci_bus_create("PCI Bus 0",0))) {
365 vm_error(vm,"unable to create PCI data.\n");
366 return(-1);
367 }
368
369 return(dev_gt64010_init(vm,"gt64010",C6SUP1_GT64K_ADDR,0x1000,
370 C6SUP1_GT64K_IRQ));
371 }
372
373 /* Initialize a SUP1 board */
374 static int c6sup1_init_hw(c6sup1_t *router)
375 {
376 vm_instance_t *vm = router->vm;
377
378 /* Set the processor type: R5000 */
379 mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R5000);
380
381 /* Initialize the Galileo GT-64010 PCI controller */
382 if (c6sup1_init_gt64010(router) == -1)
383 return(-1);
384
385 /* Create PCI bus 1 */
386 vm->pci_bus_pool[24] = pci_bus_create("PCI Bus 1",-1);
387 dev_dec21154_init(vm->pci_bus[0],1,vm->pci_bus_pool[24]);
388
389 /* PCI IO space */
390 if (!(vm->pci_io_space = pci_io_data_init(vm,C6SUP1_PCI_IO_ADDR)))
391 return(-1);
392
393 /* AGRAM ? */
394 dev_ram_init(vm,"agram",FALSE,FALSE,NULL,FALSE,0x1EA00000,0x40000);
395
396 /* Cirrus Logic PD6729 (PCI-to-PCMCIA host adapter) */
397 dev_clpd6729_init(vm,vm->pci_bus[0],5,vm->pci_io_space,0x402,0x403);
398
399 return(0);
400 }
401
402 /* Show SUP1 hardware info */
403 void c6sup1_show_hardware(c6sup1_t *router)
404 {
405 vm_instance_t *vm = router->vm;
406
407 printf("C6SUP1 instance '%s' (id %d):\n",vm->name,vm->instance_id);
408
409 printf(" VM Status : %d\n",vm->status);
410 printf(" RAM size : %u Mb\n",vm->ram_size);
411 printf(" IOMEM size : %u Mb\n",vm->iomem_size);
412 printf(" NVRAM size : %u Kb\n",vm->nvram_size);
413 printf(" IOS image : %s\n\n",vm->ios_image);
414
415 if (vm->debug_level > 0) {
416 dev_show_list(vm);
417 pci_dev_show_list(vm->pci_bus[0]);
418 pci_dev_show_list(vm->pci_bus[1]);
419 printf("\n");
420 }
421 }
422
423 /* Initialize default parameters for a SUP1 */
424 static void c6sup1_init_defaults(c6sup1_t *router)
425 {
426 vm_instance_t *vm = router->vm;
427 n_eth_addr_t *m;
428 m_uint16_t pid;
429
430 /* Set platform slots characteristics */
431 vm->nr_slots = C6SUP1_MAX_PA_BAYS;
432 vm->slots_type = CISCO_CARD_TYPE_PA;
433 vm->slots_drivers = pa_drivers;
434
435 pid = (m_uint16_t)getpid();
436
437 /* Generate a chassis MAC address based on the instance ID */
438 m = &router->mac_addr;
439 m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
440 m->eth_addr_byte[1] = vm->instance_id & 0xFF;
441 m->eth_addr_byte[2] = pid >> 8;
442 m->eth_addr_byte[3] = pid & 0xFF;
443 m->eth_addr_byte[4] = 0x00;
444 m->eth_addr_byte[5] = 0x00;
445
446 /* Default slot: 1 */
447 router->sup_slot = 1;
448
449 c6sup1_init_eeprom_groups(router);
450
451 /* Create EOBC and IBC interfaces */
452 vm_slot_add_binding(vm,"C6SUP1_EOBC",0,0);
453 vm_slot_add_binding(vm,"C6SUP1_IBC",1,0);
454
455 vm->ram_mmap = C6SUP1_DEFAULT_RAM_MMAP;
456 vm->ram_size = C6SUP1_DEFAULT_RAM_SIZE;
457 vm->rom_size = C6SUP1_DEFAULT_ROM_SIZE;
458 vm->nvram_size = C6SUP1_DEFAULT_NVRAM_SIZE;
459 vm->iomem_size = 0;
460 vm->conf_reg_setup = C6SUP1_DEFAULT_CONF_REG;
461 vm->clock_divisor = C6SUP1_DEFAULT_CLOCK_DIV;
462 vm->nvram_rom_space = C6SUP1_NVRAM_ROM_RES_SIZE;
463 }
464
465 /* Run the checklist */
466 static int c6sup1_checklist(c6sup1_t *router)
467 {
468 struct vm_instance *vm = router->vm;
469 int res = 0;
470
471 res += vm_object_check(vm,"ram");
472 res += vm_object_check(vm,"rom");
473 res += vm_object_check(vm,"nvram");
474 res += vm_object_check(vm,"zero");
475
476 if (res < 0)
477 vm_error(vm,"incomplete initialization (no memory?)\n");
478
479 return(res);
480 }
481
482 /* Initialize Port Adapters */
483 static int c6sup1_init_platform_pa(c6sup1_t *router)
484 {
485 return(vm_slot_init_all(router->vm));
486 }
487
488 /* Initialize the SUP1 Platform */
489 static int c6sup1_init_platform(c6sup1_t *router)
490 {
491 struct vm_instance *vm = router->vm;
492 cpu_mips_t *cpu0;
493 cpu_gen_t *gen0;
494 vm_obj_t *obj;
495
496 /* Copy config register setup into "active" config register */
497 vm->conf_reg = vm->conf_reg_setup;
498
499 /* Create Console and AUX ports */
500 vm_init_vtty(vm);
501
502 /* Create a CPU group */
503 vm->cpu_group = cpu_group_create("System CPU");
504
505 /* Initialize the virtual MIPS processor */
506 if (!(gen0 = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
507 vm_error(vm,"unable to create CPU0!\n");
508 return(-1);
509 }
510
511 cpu0 = CPU_MIPS64(gen0);
512
513 /* Add this CPU to the system CPU group */
514 cpu_group_add(vm->cpu_group,gen0);
515 vm->boot_cpu = gen0;
516
517 /* Initialize the IRQ routing vectors */
518 vm->set_irq = mips64_vm_set_irq;
519 vm->clear_irq = mips64_vm_clear_irq;
520
521 /* Mark the Network IO interrupt as high priority */
522 cpu0->irq_idle_preempt[C6SUP1_NETIO_IRQ] = TRUE;
523 cpu0->irq_idle_preempt[C6SUP1_GT64K_IRQ] = TRUE;
524
525 /* Copy some parameters from VM to CPU0 (idle PC, ...) */
526 cpu0->idle_pc = vm->idle_pc;
527
528 if (vm->timer_irq_check_itv)
529 cpu0->timer_irq_check_itv = vm->timer_irq_check_itv;
530
531 /*
532 * On the SUP1, bit 33 of physical addresses is used to bypass L2 cache.
533 * We clear it systematically.
534 */
535 cpu0->addr_bus_mask = C6SUP1_ADDR_BUS_MASK;
536
537 /* Remote emulator control */
538 dev_remote_control_init(vm,0x16000000,0x1000);
539
540 /* Bootflash (8 Mb) */
541 dev_bootflash_init(vm,"bootflash","c7200-bootflash-8mb",
542 C6SUP1_BOOTFLASH_ADDR);
543
544 /* NVRAM and calendar */
545 dev_nvram_init(vm,"nvram",C6SUP1_NVRAM_ADDR,
546 vm->nvram_size*1024,&vm->conf_reg);
547
548 /* Bit-bucket zone */
549 dev_zero_init(vm,"zero",C6SUP1_BITBUCKET_ADDR,0xc00000);
550
551 /* Initialize the NPE board */
552 if (c6sup1_init_hw(router) == -1)
553 return(-1);
554
555 /* Initialize RAM */
556 vm_ram_init(vm,0x00000000ULL);
557
558 /* Initialize ROM */
559 if (!vm->rom_filename) {
560 /* use embedded ROM */
561 dev_rom_init(vm,"rom",C6SUP1_ROM_ADDR,vm->rom_size*1048576,
562 mips64_microcode,mips64_microcode_len);
563 } else {
564 /* use alternate ROM */
565 dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE,
566 C6SUP1_ROM_ADDR,vm->rom_size*1048576);
567 }
568
569 /* Byte swapping */
570 dev_bswap_init(vm,"mem_bswap",C6SUP1_BSWAP_ADDR,1024*1048576,0x00000000ULL);
571
572 /* PCI IO space */
573 if (!(vm->pci_io_space = pci_io_data_init(vm,C6SUP1_PCI_IO_ADDR)))
574 return(-1);
575
576 /* Initialize the Port Adapters */
577 if (c6sup1_init_platform_pa(router) == -1)
578 return(-1);
579
580 /* Verify the check list */
581 if (c6sup1_checklist(router) == -1)
582 return(-1);
583
584 /* Midplane FPGA */
585 if (dev_c6sup1_mpfpga_init(router,C6SUP1_MPFPGA_ADDR,0x40000) == -1)
586 return(-1);
587
588 if (!(obj = vm_object_find(router->vm,"mp_fpga")))
589 return(-1);
590
591 router->mpfpga_data = obj->data;
592
593 /* IO FPGA */
594 if (dev_c6sup1_iofpga_init(router,C6SUP1_IOFPGA_ADDR,0x1000) == -1)
595 return(-1);
596
597 /* Show device list */
598 c6sup1_show_hardware(router);
599 return(0);
600 }
601
602 /* Boot the IOS image */
603 static int c6sup1_boot_ios(c6sup1_t *router)
604 {
605 vm_instance_t *vm = router->vm;
606 cpu_mips_t *cpu;
607
608 if (!vm->boot_cpu)
609 return(-1);
610
611 /* Suspend CPU activity since we will restart directly from ROM */
612 vm_suspend(vm);
613
614 /* Check that CPU activity is really suspended */
615 if (cpu_group_sync_state(vm->cpu_group) == -1) {
616 vm_error(vm,"unable to sync with system CPUs.\n");
617 return(-1);
618 }
619
620 /* Reset the boot CPU */
621 cpu = CPU_MIPS64(vm->boot_cpu);
622 mips64_reset(cpu);
623
624 /* Load IOS image */
625 if (mips64_load_elf_image(cpu,vm->ios_image,
626 (vm->ghost_status == VM_GHOST_RAM_USE),
627 &vm->ios_entry_point) < 0)
628 {
629 vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
630 return(-1);
631 }
632
633 /* Launch the simulation */
634 printf("\nC6SUP1 '%s': starting simulation (CPU0 PC=0x%llx), "
635 "JIT %sabled.\n",
636 vm->name,cpu->pc,vm->jit_use ? "en":"dis");
637
638 vm_log(vm,"C6SUP1_BOOT",
639 "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
640 cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
641
642 /* Start main CPU */
643 if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
644 vm->status = VM_STATUS_RUNNING;
645 cpu_start(vm->boot_cpu);
646 } else {
647 vm->status = VM_STATUS_SHUTDOWN;
648 }
649 return(0);
650 }
651
652 /* Set an IRQ */
653 static void c6sup1_set_irq(vm_instance_t *vm,u_int irq)
654 {
655 c6sup1_t *router = VM_C6SUP1(vm);
656 cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
657 u_int slot,port;
658
659 switch(irq) {
660 case 0 ... 7:
661 mips64_set_irq(cpu0,irq);
662
663 if (cpu0->irq_idle_preempt[irq])
664 cpu_idle_break_wait(cpu0->gen);
665 break;
666
667 case C6SUP1_NETIO_IRQ_BASE ... C6SUP1_NETIO_IRQ_END:
668 c6sup1_net_irq_get_slot_port(irq,&slot,&port);
669 //dev_c6sup1_mpfpga_net_set_irq(router->mpfpga_data,slot,port);
670 break;
671 }
672 }
673
674 /* Clear an IRQ */
675 static void c6sup1_clear_irq(vm_instance_t *vm,u_int irq)
676 {
677 c6sup1_t *router = VM_C6SUP1(vm);
678 cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
679 u_int slot,port;
680
681 switch(irq) {
682 case 0 ... 7:
683 mips64_clear_irq(cpu0,irq);
684 break;
685
686 case C6SUP1_NETIO_IRQ_BASE ... C6SUP1_NETIO_IRQ_END:
687 c6sup1_net_irq_get_slot_port(irq,&slot,&port);
688 //dev_c6sup1_mpfpga_net_clear_irq(router->mpfpga_data,slot,port);
689 break;
690 }
691 }
692
693 /* Initialize a SUP1 instance */
694 static int c6sup1_init_instance(vm_instance_t *vm)
695 {
696 c6sup1_t *router = VM_C6SUP1(vm);
697 m_uint32_t rom_entry_point;
698 cpu_mips_t *cpu0;
699
700 /* Initialize the SUP1 platform */
701 if (c6sup1_init_platform(router) == -1) {
702 vm_error(vm,"unable to initialize the platform hardware.\n");
703 return(-1);
704 }
705
706 /* IRQ routing */
707 vm->set_irq = c6sup1_set_irq;
708 vm->clear_irq = c6sup1_clear_irq;
709
710 /* Load IOS configuration file */
711 if (vm->ios_config != NULL) {
712 vm_nvram_push_config(vm,vm->ios_config);
713 vm->conf_reg &= ~0x40;
714 }
715
716 /* Load ROM (ELF image or embedded) */
717 cpu0 = CPU_MIPS64(vm->boot_cpu);
718 rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
719
720 if ((vm->rom_filename != NULL) &&
721 (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
722 {
723 vm_error(vm,"unable to load alternate ROM '%s', "
724 "fallback to embedded ROM.\n\n",vm->rom_filename);
725 vm->rom_filename = NULL;
726 }
727
728 /* Load symbol file */
729 if (vm->sym_filename) {
730 mips64_sym_load_file(cpu0,vm->sym_filename);
731 cpu0->sym_trace = 1;
732 }
733
734 return(c6sup1_boot_ios(router));
735 }
736
737 /* Stop a SUP1 instance */
738 static int c6sup1_stop_instance(vm_instance_t *vm)
739 {
740 printf("\nC6SUP1 '%s': stopping simulation.\n",vm->name);
741 vm_log(vm,"C6SUP1_STOP","stopping simulation.\n");
742
743 /* Stop all CPUs */
744 if (vm->cpu_group != NULL) {
745 vm_stop(vm);
746
747 if (cpu_group_sync_state(vm->cpu_group) == -1) {
748 vm_error(vm,"unable to sync with system CPUs.\n");
749 return(-1);
750 }
751 }
752
753 /* Free resources that were used during execution to emulate hardware */
754 c6sup1_free_hw_ressources(VM_C6SUP1(vm));
755 vm_hardware_shutdown(vm);
756 return(0);
757 }
758
759 /* Get MAC address MSB */
760 static u_int c6sup1_get_mac_addr_msb(void)
761 {
762 return(0xD0);
763 }
764
765 /* Show specific CLI options */
766 static void c6sup1_cli_show_options(vm_instance_t *vm)
767 {
768 printf(" -s <pa_nio> : Bind a Network IO interface to a "
769 "Port Adapter\n");
770 }
771
772 /* Platform definition */
773 static vm_platform_t c6sup1_platform = {
774 "c6sup1", "C6SUP1", "C6SUP1",
775 c6sup1_create_instance,
776 c6sup1_delete_instance,
777 c6sup1_init_instance,
778 c6sup1_stop_instance,
779 c6sup1_nvram_extract_config,
780 c6sup1_nvram_push_config,
781 c6sup1_get_mac_addr_msb,
782 NULL,
783 NULL,
784 c6sup1_cli_show_options,
785 NULL,
786 };
787
788 /* Register the C6-SUP1 platform */
789 int c6sup1_platform_register(void)
790 {
791 return(vm_platform_register(&c6sup1_platform));
792 }

  ViewVC Help
Powered by ViewVC 1.1.26