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

Contents of /trunk/dev_c3725.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 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: 21691 byte(s)
make working copy

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4 *
5 * Generic Cisco 3725 routines and definitions (EEPROM,...).
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <sys/types.h>
13 #include <assert.h>
14
15 #include "cpu.h"
16 #include "vm.h"
17 #include "dynamips.h"
18 #include "memory.h"
19 #include "device.h"
20 #include "pci_io.h"
21 #include "dev_gt.h"
22 #include "cisco_eeprom.h"
23 #include "dev_rom.h"
24 #include "dev_c3725.h"
25 #include "dev_c3725_iofpga.h"
26 #include "dev_vtty.h"
27 #include "registry.h"
28
29 /* ======================================================================== */
30 /* EEPROM definitions */
31 /* ======================================================================== */
32
33 /* Cisco 3725 mainboard EEPROM */
34 static m_uint16_t eeprom_c3725_mainboard_data[] = {
35 0x04FF, 0xC18B, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0x5809,
36 0x6140, 0x0259, 0xC046, 0x0320, 0x003F, 0x1302, 0x4244, 0x3085,
37 0x1C10, 0x8206, 0x80FF, 0xFFFF, 0xFFC4, 0x08FF, 0xFFFF, 0xFFFF,
38 0xFFFF, 0xFF81, 0xFFFF, 0xFFFF, 0x03FF, 0x04FF, 0xC28B, 0x5858,
39 0x5858, 0x5858, 0x5858, 0x5858, 0x58C3, 0x0600, 0x1319, 0x5C6F,
40 0x7043, 0x0030, 0xC508, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x4100,
41 0x0101, 0x02FF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
42 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
43 };
44
45 struct cisco_eeprom eeprom_c3725_mainboard = {
46 "C3725 Backplane",
47 eeprom_c3725_mainboard_data,
48 sizeof(eeprom_c3725_mainboard_data)/2,
49 };
50
51 /* ======================================================================== */
52 /* Network Module Drivers */
53 /* ======================================================================== */
54 static struct cisco_card_driver *nm_drivers[] = {
55 &dev_c3725_nm_1fe_tx_driver,
56 &dev_c3725_nm_16esw_driver,
57 &dev_c3725_gt96100_fe_driver,
58 &dev_c3725_nm_4t_driver,
59 &dev_c3725_nm_nam_driver,
60 &dev_c3725_nm_cids_driver,
61 NULL,
62 };
63
64 /* ======================================================================== */
65 /* Cisco 3725 router instances */
66 /* ======================================================================== */
67
68 /* Initialize default parameters for a C3725 */
69 static void c3725_init_defaults(c3725_t *router);
70
71 /* Directly extract the configuration from the NVRAM device */
72 static ssize_t c3725_nvram_extract_config(vm_instance_t *vm,u_char **buffer)
73 {
74 u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;
75 m_uint32_t start,nvlen;
76 m_uint16_t magic1,magic2;
77 struct vdevice *nvram_dev;
78 off_t nvram_size;
79 int fd;
80
81 if ((nvram_dev = dev_get_by_name(vm,"rom")))
82 dev_sync(nvram_dev);
83
84 fd = vm_mmap_open_file(vm,"rom",&base_ptr,&nvram_size);
85
86 if (fd == -1)
87 return(-1);
88
89 ios_ptr = base_ptr + C3725_NVRAM_OFFSET;
90 end_ptr = base_ptr + nvram_size;
91
92 if ((ios_ptr + 0x30) >= end_ptr) {
93 vm_error(vm,"NVRAM file too small\n");
94 return(-1);
95 }
96
97 magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06));
98 magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08));
99
100 if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) {
101 vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n",
102 magic1,magic2);
103 return(-1);
104 }
105
106 start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1;
107 nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18));
108
109 if (!(*buffer = malloc(nvlen+1))) {
110 vm_error(vm,"unable to allocate config buffer (%u bytes)\n",nvlen);
111 return(-1);
112 }
113
114 cfg_ptr = ios_ptr + start + 0x08;
115
116 if ((cfg_ptr + nvlen) > end_ptr) {
117 vm_error(vm,"NVRAM file too small\n");
118 return(-1);
119 }
120
121 memcpy(*buffer,cfg_ptr,nvlen-1);
122 (*buffer)[nvlen-1] = 0;
123 return(nvlen-1);
124 }
125
126 static int c3725_nvram_push_config_part(vm_instance_t *vm,
127 u_char *buffer,size_t len,
128 u_char *ios_ptr)
129 {
130 m_uint32_t cfg_offset,cklen,tmp;
131 m_uint16_t cksum;
132 u_char *cfg_ptr;
133
134 cfg_offset = 0x2c;
135 cfg_ptr = ios_ptr + cfg_offset;
136
137 /* Write IOS tag, uncompressed config... */
138 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5);
139 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD);
140 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001);
141 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000);
142 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0c04);
143
144 /* Store file contents to NVRAM */
145 memcpy(cfg_ptr,buffer,len);
146
147 /* Write config addresses + size */
148 tmp = cfg_offset - 0x08;
149
150 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(tmp);
151 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(tmp + len);
152 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len);
153
154 /* Compute the checksum */
155 cklen = C3725_NVRAM_SIZE - 0x08;
156 cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen);
157 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum);
158 return(0);
159 }
160
161 /* Directly push the IOS configuration to the NVRAM device */
162 int c3725_nvram_push_config(vm_instance_t *vm,u_char *buffer,size_t len)
163 {
164 u_char *base_ptr,*ios_ptr;
165 int fd;
166
167 fd = vm_mmap_create_file(vm,"rom",vm->rom_size*1048576,&base_ptr);
168
169 if (fd == -1)
170 return(-1);
171
172 ios_ptr = base_ptr + C3725_NVRAM_OFFSET;
173
174 /* Normal config */
175 c3725_nvram_push_config_part(vm,buffer,len,ios_ptr);
176
177 /* Backup config */
178 c3725_nvram_push_config_part(vm,buffer,len,ios_ptr + C3725_NVRAM_SIZE);
179
180 vm_mmap_close_file(fd,base_ptr,vm->rom_size*1048576);
181 return(0);
182 }
183
184 /* Check for empty config */
185 static int c3725_nvram_check_empty_config(vm_instance_t *vm)
186 {
187 struct vdevice *rom_dev;
188 m_uint64_t addr;
189 size_t len;
190
191 if (!(rom_dev = dev_get_by_name(vm,"rom")))
192 return(-1);
193
194 addr = rom_dev->phys_addr + C3725_NVRAM_OFFSET;
195 len = C3725_NVRAM_SIZE;
196
197 while(len > 0) {
198 if (physmem_copy_u32_from_vm(vm,addr) != 0)
199 return(0);
200
201 addr += sizeof(m_uint32_t);
202 len -= sizeof(m_uint32_t);
203 }
204
205 /* Empty NVRAM */
206 vm->conf_reg |= 0x0040;
207 printf("NVRAM is empty, setting config register to 0x%x\n",vm->conf_reg);
208 return(0);
209 }
210
211 /* Create a new router instance */
212 static int c3725_create_instance(vm_instance_t *vm)
213 {
214 c3725_t *router;
215
216 if (!(router = malloc(sizeof(*router)))) {
217 fprintf(stderr,"C3725 '%s': Unable to create new instance!\n",vm->name);
218 return(-1);
219 }
220
221 memset(router,0,sizeof(*router));
222 router->vm = vm;
223 vm->hw_data = router;
224
225 c3725_init_defaults(router);
226 return(0);
227 }
228
229 /* Free resources used by a router instance */
230 static int c3725_delete_instance(vm_instance_t *vm)
231 {
232 c3725_t *router = VM_C3725(vm);
233 int i;
234
235 /* Stop all CPUs */
236 if (vm->cpu_group != NULL) {
237 vm_stop(vm);
238
239 if (cpu_group_sync_state(vm->cpu_group) == -1) {
240 vm_error(vm,"unable to sync with system CPUs.\n");
241 return(FALSE);
242 }
243 }
244
245 /* Remove NIO bindings */
246 for(i=0;i<vm->nr_slots;i++)
247 vm_slot_remove_all_nio_bindings(vm,i);
248
249 /* Shutdown all Network Modules */
250 vm_slot_shutdown_all(vm);
251
252 /* Free mainboard EEPROM */
253 cisco_eeprom_free(&router->mb_eeprom);
254
255 /* Free all resources used by VM */
256 vm_free(vm);
257
258 /* Free the router structure */
259 free(router);
260 return(TRUE);
261 }
262
263 /* Get WIC device address for the specified onboard port */
264 int c3725_get_onboard_wic_addr(u_int slot,m_uint64_t *phys_addr)
265 {
266 if (slot >= C3725_MAX_WIC_BAYS)
267 return(-1);
268
269 *phys_addr = C3725_WIC_ADDR + (slot * C3725_WIC_SIZE);
270 return(0);
271 }
272
273 /* Set EEPROM for the specified slot */
274 int c3725_set_slot_eeprom(c3725_t *router,u_int slot,
275 struct cisco_eeprom *eeprom)
276 {
277 if ((slot < 1) || (slot >= C3725_MAX_NM_BAYS))
278 return(-1);
279
280 router->nm_eeprom_group[slot-1].eeprom[0] = eeprom;
281 return(0);
282 }
283
284 /* Get slot/port corresponding to specified network IRQ */
285 static inline void
286 c3725_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port)
287 {
288 irq -= C3725_NETIO_IRQ_BASE;
289 *port = irq & C3725_NETIO_IRQ_PORT_MASK;
290 *slot = irq >> C3725_NETIO_IRQ_PORT_BITS;
291 }
292
293 /* Get network IRQ for specified slot/port */
294 u_int c3725_net_irq_for_slot_port(u_int slot,u_int port)
295 {
296 u_int irq;
297
298 irq = (slot << C3725_NETIO_IRQ_PORT_BITS) + port;
299 irq += C3725_NETIO_IRQ_BASE;
300
301 return(irq);
302 }
303
304 /* Get PCI device for the specified NM bay */
305 int c3725_nm_get_pci_device(u_int nm_bay)
306 {
307 switch(nm_bay) {
308 case 1:
309 return(0x06);
310 case 2:
311 return(0x0A);
312 default:
313 return(-1);
314 }
315 }
316
317 /* Set the base MAC address of the chassis */
318 static int c3725_burn_mac_addr(c3725_t *router,n_eth_addr_t *addr)
319 {
320 m_uint8_t eeprom_ver;
321 size_t offset;
322
323 /* Read EEPROM format version */
324 cisco_eeprom_get_byte(&router->mb_eeprom,0,&eeprom_ver);
325
326 switch(eeprom_ver) {
327 case 0:
328 cisco_eeprom_set_region(&router->mb_eeprom,2,addr->eth_addr_byte,6);
329 break;
330
331 case 4:
332 if (!cisco_eeprom_v4_find_field(&router->mb_eeprom,0xC3,&offset)) {
333 cisco_eeprom_set_region(&router->mb_eeprom,offset,
334 addr->eth_addr_byte,6);
335 }
336 break;
337
338 default:
339 vm_error(router->vm,"c3725_burn_mac_addr: unable to handle "
340 "EEPROM version %u\n",eeprom_ver);
341 return(-1);
342 }
343
344 return(0);
345 }
346
347 /* Set chassis MAC address */
348 int c3725_chassis_set_mac_addr(c3725_t *router,char *mac_addr)
349 {
350 if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) {
351 vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr);
352 return(-1);
353 }
354
355 /* Set the chassis base MAC address */
356 c3725_burn_mac_addr(router,&router->mac_addr);
357 return(0);
358 }
359
360 /* Create the two main PCI busses for a GT64120 based system */
361 static int c3725_init_gt96100(c3725_t *router)
362 {
363 vm_instance_t *vm = router->vm;
364 vm_obj_t *obj;
365
366 vm->pci_bus[0] = pci_bus_create("PCI bus #0",0);
367 vm->pci_bus[1] = pci_bus_create("PCI bus #1",0);
368
369 if (!vm->pci_bus[0] || !vm->pci_bus[1]) {
370 vm_error(router->vm,"unable to create PCI data.\n");
371 return(-1);
372 }
373
374 if (dev_gt96100_init(vm,"gt96100",C3725_GT96K_ADDR,0x200000,
375 C3725_GT96K_IRQ,
376 C3725_EXT_IRQ,
377 c3725_net_irq_for_slot_port(0,0),
378 255) == -1)
379 return(-1);
380
381 if (!(obj = vm_object_find(router->vm,"gt96100")))
382 return(-1);
383
384 router->gt_data = obj->data;
385 return(0);
386 }
387
388 /* Initialize a Cisco 3725 */
389 static int c3725_init(c3725_t *router)
390 {
391 vm_instance_t *vm = router->vm;
392
393 /* Set the processor type: R7000 */
394 mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R7000);
395
396 /* Initialize the Galileo GT-96100 PCI controller */
397 if (c3725_init_gt96100(router) == -1)
398 return(-1);
399
400 /* Initialize PCI map (NM slots 1 & 2) */
401 vm->slots_pci_bus[1] = vm->pci_bus[1];
402 vm->slots_pci_bus[2] = vm->pci_bus[1];
403
404 vm->elf_machine_id = C3725_ELF_MACHINE_ID;
405 return(0);
406 }
407
408 /* Show C3725 hardware info */
409 void c3725_show_hardware(c3725_t *router)
410 {
411 vm_instance_t *vm = router->vm;
412
413 printf("C3725 instance '%s' (id %d):\n",vm->name,vm->instance_id);
414
415 printf(" VM Status : %d\n",vm->status);
416 printf(" RAM size : %u Mb\n",vm->ram_size);
417 printf(" NVRAM size : %u Kb\n",vm->nvram_size);
418 printf(" IOS image : %s\n\n",vm->ios_image);
419
420 if (vm->debug_level > 0) {
421 dev_show_list(vm);
422 pci_dev_show_list(vm->pci_bus[0]);
423 pci_dev_show_list(vm->pci_bus[1]);
424 printf("\n");
425 }
426 }
427
428 /* Initialize default parameters for a C3725 */
429 static void c3725_init_defaults(c3725_t *router)
430 {
431 vm_instance_t *vm = router->vm;
432 n_eth_addr_t *m;
433 m_uint16_t pid;
434
435 /* Set platform slots characteristics */
436 vm->nr_slots = C3725_MAX_NM_BAYS;
437 vm->slots_type = CISCO_CARD_TYPE_NM;
438 vm->slots_drivers = nm_drivers;
439
440 pid = (m_uint16_t)getpid();
441
442 /* Generate a chassis MAC address based on the instance ID */
443 m = &router->mac_addr;
444 m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
445 m->eth_addr_byte[1] = vm->instance_id & 0xFF;
446 m->eth_addr_byte[2] = pid >> 8;
447 m->eth_addr_byte[3] = pid & 0xFF;
448 m->eth_addr_byte[4] = 0x00;
449 m->eth_addr_byte[5] = 0x00;
450
451 c3725_init_eeprom_groups(router);
452 cisco_eeprom_copy(&router->mb_eeprom,&eeprom_c3725_mainboard);
453 c3725_burn_mac_addr(router,&router->mac_addr);
454
455 /* The GT96100 system controller has 2 integrated FastEthernet ports */
456 vm_slot_add_binding(vm,"GT96100-FE",0,0);
457
458 vm->ram_mmap = C3725_DEFAULT_RAM_MMAP;
459 vm->ram_size = C3725_DEFAULT_RAM_SIZE;
460 vm->rom_size = C3725_DEFAULT_ROM_SIZE;
461 vm->nvram_size = C3725_DEFAULT_NVRAM_SIZE;
462 vm->conf_reg_setup = C3725_DEFAULT_CONF_REG;
463 vm->clock_divisor = C3725_DEFAULT_CLOCK_DIV;
464 vm->nvram_rom_space = C3725_NVRAM_ROM_RES_SIZE;
465 vm->nm_iomem_size = C3725_DEFAULT_IOMEM_SIZE;
466
467 vm->pcmcia_disk_size[0] = C3725_DEFAULT_DISK0_SIZE;
468 vm->pcmcia_disk_size[1] = C3725_DEFAULT_DISK1_SIZE;
469 }
470
471 /* Initialize the C3725 Platform */
472 static int c3725_init_platform(c3725_t *router)
473 {
474 vm_instance_t *vm = router->vm;
475 cpu_mips_t *cpu;
476 cpu_gen_t *gen;
477 vm_obj_t *obj;
478
479 /* Copy config register setup into "active" config register */
480 vm->conf_reg = vm->conf_reg_setup;
481
482 /* Create Console and AUX ports */
483 vm_init_vtty(vm);
484
485 /* Create a CPU group */
486 vm->cpu_group = cpu_group_create("System CPU");
487
488 /* Initialize the virtual MIPS processor */
489 if (!(gen = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
490 vm_error(vm,"unable to create CPU!\n");
491 return(-1);
492 }
493
494 cpu = CPU_MIPS64(gen);
495
496 /* Add this CPU to the system CPU group */
497 cpu_group_add(vm->cpu_group,gen);
498 vm->boot_cpu = gen;
499
500 /* Initialize the IRQ routing vectors */
501 vm->set_irq = mips64_vm_set_irq;
502 vm->clear_irq = mips64_vm_clear_irq;
503
504 /* Mark the Network IO interrupt as high priority */
505 cpu->irq_idle_preempt[C3725_NETIO_IRQ] = TRUE;
506 cpu->irq_idle_preempt[C3725_GT96K_IRQ] = TRUE;
507 cpu->irq_idle_preempt[C3725_DUART_IRQ] = TRUE;
508
509 /* Copy some parameters from VM to CPU (idle PC, ...) */
510 cpu->idle_pc = vm->idle_pc;
511
512 if (vm->timer_irq_check_itv)
513 cpu->timer_irq_check_itv = vm->timer_irq_check_itv;
514
515 /* Remote emulator control */
516 dev_remote_control_init(vm,0x16000000,0x1000);
517
518 /* Specific Storage Area (SSA) */
519 dev_ram_init(vm,"ssa",TRUE,FALSE,NULL,FALSE,0x16001000ULL,0x7000);
520
521 /* IO FPGA */
522 if (dev_c3725_iofpga_init(router,C3725_IOFPGA_ADDR,0x40000) == -1)
523 return(-1);
524
525 if (!(obj = vm_object_find(router->vm,"io_fpga")))
526 return(-1);
527
528 router->iofpga_data = obj->data;
529
530 #if 0
531 /* PCI IO space */
532 if (!(vm->pci_io_space = pci_io_data_init(vm,C3725_PCI_IO_ADDR)))
533 return(-1);
534 #endif
535
536 /* Initialize the chassis */
537 if (c3725_init(router) == -1)
538 return(-1);
539
540 /* Initialize RAM */
541 vm_ram_init(vm,0x00000000ULL);
542
543 /* Initialize ROM (as a Flash) */
544 if (!(obj = dev_flash_init(vm,"rom",C3725_ROM_ADDR,vm->rom_size*1048576)))
545 return(-1);
546
547 dev_flash_copy_data(obj,0,mips64_microcode,mips64_microcode_len);
548 c3725_nvram_check_empty_config(vm);
549
550 /* Byte swapping */
551 dev_bswap_init(vm,"mem_bswap",C3725_BSWAP_ADDR,1024*1048576,0x00000000ULL);
552
553 /* Initialize the NS16552 DUART */
554 dev_ns16552_init(vm,C3725_DUART_ADDR,0x1000,3,C3725_DUART_IRQ,
555 vm->vtty_con,vm->vtty_aux);
556
557 /* PCMCIA Slot 0 */
558 dev_pcmcia_disk_init(vm,"slot0",C3725_SLOT0_ADDR,0x200000,
559 vm->pcmcia_disk_size[0],1);
560
561 /* PCMCIA Slot 1 */
562 dev_pcmcia_disk_init(vm,"slot1",C3725_SLOT1_ADDR,0x200000,
563 vm->pcmcia_disk_size[1],1);
564
565 /* Initialize Network Modules */
566 if (vm_slot_init_all(vm) == -1)
567 return(-1);
568
569 /* Show device list */
570 c3725_show_hardware(router);
571 return(0);
572 }
573
574 /* Boot the IOS image */
575 static int c3725_boot_ios(c3725_t *router)
576 {
577 vm_instance_t *vm = router->vm;
578 cpu_mips_t *cpu;
579
580 if (!vm->boot_cpu)
581 return(-1);
582
583 /* Suspend CPU activity since we will restart directly from ROM */
584 vm_suspend(vm);
585
586 /* Check that CPU activity is really suspended */
587 if (cpu_group_sync_state(vm->cpu_group) == -1) {
588 vm_error(vm,"unable to sync with system CPUs.\n");
589 return(-1);
590 }
591
592 /* Reset the boot CPU */
593 cpu = CPU_MIPS64(vm->boot_cpu);
594 mips64_reset(cpu);
595
596 /* Load IOS image */
597 if (mips64_load_elf_image(cpu,vm->ios_image,
598 (vm->ghost_status == VM_GHOST_RAM_USE),
599 &vm->ios_entry_point) < 0)
600 {
601 vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
602 return(-1);
603 }
604
605 /* Launch the simulation */
606 printf("\nC3725 '%s': starting simulation (CPU0 PC=0x%llx), "
607 "JIT %sabled.\n",
608 vm->name,cpu->pc,vm->jit_use ? "en":"dis");
609
610 vm_log(vm,"C3725_BOOT",
611 "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
612 cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
613
614 /* Start main CPU */
615 if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
616 vm->status = VM_STATUS_RUNNING;
617 cpu_start(vm->boot_cpu);
618 } else {
619 vm->status = VM_STATUS_SHUTDOWN;
620 }
621 return(0);
622 }
623
624 /* Set an IRQ */
625 static void c3725_set_irq(vm_instance_t *vm,u_int irq)
626 {
627 c3725_t *router = VM_C3725(vm);
628 cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
629 u_int slot,port;
630
631 switch(irq) {
632 case 0 ... 7:
633 mips64_set_irq(cpu0,irq);
634
635 if (cpu0->irq_idle_preempt[irq])
636 cpu_idle_break_wait(cpu0->gen);
637 break;
638
639 case C3725_NETIO_IRQ_BASE ... C3725_NETIO_IRQ_END:
640 c3725_net_irq_get_slot_port(irq,&slot,&port);
641 dev_c3725_iofpga_net_set_irq(router->iofpga_data,slot,port);
642 break;
643 }
644 }
645
646 /* Clear an IRQ */
647 static void c3725_clear_irq(vm_instance_t *vm,u_int irq)
648 {
649 c3725_t *router = VM_C3725(vm);
650 cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
651 u_int slot,port;
652
653 switch(irq) {
654 case 0 ... 7:
655 mips64_clear_irq(cpu0,irq);
656 break;
657
658 case C3725_NETIO_IRQ_BASE ... C3725_NETIO_IRQ_END:
659 c3725_net_irq_get_slot_port(irq,&slot,&port);
660 dev_c3725_iofpga_net_clear_irq(router->iofpga_data,slot,port);
661 break;
662 }
663 }
664
665 /* Initialize a Cisco 3725 instance */
666 static int c3725_init_instance(vm_instance_t *vm)
667 {
668 c3725_t *router = VM_C3725(vm);
669 m_uint32_t rom_entry_point;
670 cpu_mips_t *cpu0;
671
672 if (!vm->ios_image) {
673 vm_error(vm,"no Cisco IOS image defined.");
674 return(-1);
675 }
676
677 /* Initialize the C3725 platform */
678 if (c3725_init_platform(router) == -1) {
679 vm_error(vm,"unable to initialize the platform hardware.\n");
680 return(-1);
681 }
682
683 /* IRQ routing */
684 vm->set_irq = c3725_set_irq;
685 vm->clear_irq = c3725_clear_irq;
686
687 /* Load IOS configuration file */
688 if (vm->ios_config != NULL) {
689 vm_nvram_push_config(vm,vm->ios_config);
690 vm->conf_reg &= ~0x40;
691 }
692
693 /* Load ROM (ELF image or embedded) */
694 cpu0 = CPU_MIPS64(vm->boot_cpu);
695 rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
696
697 if ((vm->rom_filename != NULL) &&
698 (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
699 {
700 vm_error(vm,"unable to load alternate ROM '%s', "
701 "fallback to embedded ROM.\n\n",vm->rom_filename);
702 vm->rom_filename = NULL;
703 }
704
705 /* Load symbol file */
706 if (vm->sym_filename) {
707 mips64_sym_load_file(cpu0,vm->sym_filename);
708 cpu0->sym_trace = 1;
709 }
710
711 return(c3725_boot_ios(router));
712 }
713
714 /* Stop a Cisco 3725 instance */
715 static int c3725_stop_instance(vm_instance_t *vm)
716 {
717 printf("\nC3725 '%s': stopping simulation.\n",vm->name);
718 vm_log(vm,"C3725_STOP","stopping simulation.\n");
719
720 /* Stop all CPUs */
721 if (vm->cpu_group != NULL) {
722 vm_stop(vm);
723
724 if (cpu_group_sync_state(vm->cpu_group) == -1) {
725 vm_error(vm,"unable to sync with system CPUs.\n");
726 return(-1);
727 }
728 }
729
730 /* Free resources that were used during execution to emulate hardware */
731 vm_slot_shutdown_all(vm);
732 vm_hardware_shutdown(vm);
733 return(0);
734 }
735
736 /* Get MAC address MSB */
737 static u_int c3725_get_mac_addr_msb(void)
738 {
739 return(0xC2);
740 }
741
742 /* Parse specific options for the Cisco 3725 platform */
743 static int c3725_cli_parse_options(vm_instance_t *vm,int option)
744 {
745 switch(option) {
746 /* IO memory reserved for NMs (in percents!) */
747 case OPT_IOMEM_SIZE:
748 vm->nm_iomem_size = 0x8000 | atoi(optarg);
749 break;
750
751 /* Unknown option */
752 default:
753 return(-1);
754 }
755
756 return(0);
757 }
758
759 /* Show specific CLI options */
760 static void c3725_cli_show_options(vm_instance_t *vm)
761 {
762 printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n"
763 " -p <nm_desc> : Define a Network Module\n"
764 " -s <nm_nio> : Bind a Network IO interface to a "
765 "Network Module\n",
766 vm->nm_iomem_size);
767 }
768
769 /* Platform definition */
770 static vm_platform_t c3725_platform = {
771 "c3725", "C3725", "3725",
772 c3725_create_instance,
773 c3725_delete_instance,
774 c3725_init_instance,
775 c3725_stop_instance,
776 c3725_nvram_extract_config,
777 c3725_nvram_push_config,
778 c3725_get_mac_addr_msb,
779 NULL,
780 c3725_cli_parse_options,
781 c3725_cli_show_options,
782 NULL,
783 };
784
785 /* Register the c3725 platform */
786 int c3725_platform_register(void)
787 {
788 if (vm_platform_register(&c3725_platform) == -1)
789 return(-1);
790
791 return(hypervisor_c3725_init(&c3725_platform));
792 }

  ViewVC Help
Powered by ViewVC 1.1.26