/[dynamips]/trunk/dev_c1700.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_c1700.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 13 - (show annotations)
Fri Oct 12 09:40:41 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 22356 byte(s)
boot linux kernel from DSM G600
1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4 *
5 * Generic Cisco 1700 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 "ppc32_mem.h"
21 #include "pci_io.h"
22 #include "cisco_eeprom.h"
23 #include "dev_mpc860.h"
24 #include "dev_rom.h"
25 #include "dev_c1700.h"
26 #include "dev_c1700_iofpga.h"
27 #include "dev_vtty.h"
28 #include "registry.h"
29
30 /* ======================================================================== */
31 /* EEPROM definitions */
32 /* ======================================================================== */
33
34 /* Cisco 1700 mainboard EEPROM */
35 static m_uint16_t eeprom_c1700_mb_data[] = {
36 0x0101, 0x0404, 0x0000, 0x0000, 0x4320, 0x00FF, 0x00B2, 0x0020,
37 0x0000, 0x0000, 0x0000, 0x0000, 0x3030, 0x3000, 0x0030, 0x3030,
38 0x3002, 0x0200, 0x0000, 0x0000, 0x00FF, 0xFFFF, 0x5006, 0x490B,
39 0x1709, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
40 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
41 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
42 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
43 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
44 };
45
46 struct c1700_mb_id {
47 char *name;
48 char *mb_driver;
49 m_uint16_t id;
50 int supported;
51 };
52
53 struct c1700_mb_id c1700_mainboard_id[] = {
54 { "1710" , "C1710-MB-1FE-1E" , 0x02F6, TRUE },
55 { "1720" , "C1700-MB-1ETH" , 0x00B2, TRUE },
56 { "1721" , "C1700-MB-1ETH" , 0x035A, TRUE },
57 { "1750" , "C1700-MB-1ETH" , 0x00C9, TRUE },
58 { "1751" , "C1700-MB-1ETH" , 0x024D, TRUE },
59 { "1760" , "C1700-MB-1ETH" , 0x0316, TRUE },
60 { NULL , NULL , 0x0000, 0 },
61 };
62
63 /* ======================================================================== */
64 /* Network Module Drivers */
65 /* ======================================================================== */
66 static struct cisco_card_driver *nm_drivers[] = {
67 &dev_c1700_mb_eth_driver,
68 &dev_c1710_mb_eth_driver,
69 NULL,
70 };
71
72 /* ======================================================================== */
73 /* Cisco 1700 router instances */
74 /* ======================================================================== */
75
76 /* Initialize default parameters for a C1700 */
77 static void c1700_init_defaults(c1700_t *router);
78
79 /* Directly extract the configuration from the NVRAM device */
80 static ssize_t c1700_nvram_extract_config(vm_instance_t *vm,u_char **buffer)
81 {
82 u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;
83 m_uint32_t start,nvlen;
84 m_uint16_t magic1,magic2;
85 struct vdevice *nvram_dev;
86 off_t nvram_size;
87 int fd;
88
89 if ((nvram_dev = dev_get_by_name(vm,"nvram")))
90 dev_sync(nvram_dev);
91
92 fd = vm_mmap_open_file(vm,"nvram",&base_ptr,&nvram_size);
93
94 if (fd == -1)
95 return(-1);
96
97 ios_ptr = base_ptr + vm->nvram_rom_space;
98 end_ptr = base_ptr + nvram_size;
99
100 if ((ios_ptr + 0x30) >= end_ptr) {
101 vm_error(vm,"NVRAM file too small\n");
102 return(-1);
103 }
104
105 magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06));
106 magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08));
107
108 if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) {
109 vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n",
110 magic1,magic2);
111 return(-1);
112 }
113
114 start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1;
115 nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18));
116
117 if (!(*buffer = malloc(nvlen+1))) {
118 vm_error(vm,"unable to allocate config buffer (%u bytes)\n",nvlen);
119 return(-1);
120 }
121
122 cfg_ptr = ios_ptr + start + 0x08;
123
124 if ((cfg_ptr + nvlen) > end_ptr) {
125 vm_error(vm,"NVRAM file too small\n");
126 return(-1);
127 }
128
129 memcpy(*buffer,cfg_ptr,nvlen-1);
130 (*buffer)[nvlen-1] = 0;
131 return(nvlen-1);
132 }
133
134 /* Directly push the IOS configuration to the NVRAM device */
135 static int c1700_nvram_push_config(vm_instance_t *vm,u_char *buffer,size_t len)
136 {
137 u_char *base_ptr,*ios_ptr,*cfg_ptr;
138 m_uint32_t cfg_offset,cklen,tmp;
139 m_uint16_t cksum;
140 int fd;
141
142 fd = vm_mmap_create_file(vm,"nvram",vm->nvram_size*1024,&base_ptr);
143
144 if (fd == -1)
145 return(-1);
146
147 cfg_offset = 0x2c;
148 ios_ptr = base_ptr + vm->nvram_rom_space;
149 cfg_ptr = ios_ptr + cfg_offset;
150
151 /* Write IOS tag, uncompressed config... */
152 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5);
153 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD);
154 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001);
155 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000);
156 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0c04);
157
158 /* Store file contents to NVRAM */
159 memcpy(cfg_ptr,buffer,len);
160
161 /* Write config addresses + size */
162 tmp = cfg_offset - 0x08;
163
164 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(tmp);
165 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(tmp + len);
166 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len);
167
168 /* Compute the checksum */
169 cklen = (vm->nvram_size*1024) - (vm->nvram_rom_space + 0x08);
170 cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen);
171 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum);
172
173 vm_mmap_close_file(fd,base_ptr,vm->nvram_size*1024);
174 return(0);
175 }
176
177 /* Create a new router instance */
178 static int c1700_create_instance(vm_instance_t *vm)
179 {
180 c1700_t *router;
181
182 if (!(router = malloc(sizeof(*router)))) {
183 fprintf(stderr,"C1700 '%s': Unable to create new instance!\n",vm->name);
184 return(-1);
185 }
186
187 memset(router,0,sizeof(*router));
188 router->vm = vm;
189 vm->hw_data = router;
190
191 c1700_init_defaults(router);
192 return(0);
193 }
194
195 /* Free resources used by a router instance */
196 static int c1700_delete_instance(vm_instance_t *vm)
197 {
198 c1700_t *router = VM_C1700(vm);
199 int i;
200
201 /* Stop all CPUs */
202 if (vm->cpu_group != NULL) {
203 vm_stop(vm);
204
205 if (cpu_group_sync_state(vm->cpu_group) == -1) {
206 vm_error(vm,"unable to sync with system CPUs.\n");
207 return(FALSE);
208 }
209 }
210
211 /* Remove NIO bindings */
212 for(i=0;i<vm->nr_slots;i++)
213 vm_slot_remove_all_nio_bindings(vm,i);
214
215 /* Shutdown all Network Modules */
216 vm_slot_shutdown_all(vm);
217
218 /* Free mainboard EEPROM */
219 cisco_eeprom_free(&router->mb_eeprom);
220
221 /* Free all resources used by VM */
222 vm_free(vm);
223
224 /* Free the router structure */
225 free(router);
226 return(TRUE);
227 }
228
229 /* Save configuration of a C1700 instance */
230 void c1700_save_config(vm_instance_t *vm,FILE *fd)
231 {
232 c1700_t *router = VM_C1700(vm);
233
234 fprintf(fd,"c1700 set_chassis %s %s\n\n",vm->name,router->mainboard_type);
235 }
236
237 /* Set EEPROM for the specified slot */
238 int c1700_set_slot_eeprom(c1700_t *router,u_int slot,
239 struct cisco_eeprom *eeprom)
240 {
241 switch(slot) {
242 case 1:
243 router->nm_eeprom_group.eeprom[0] = eeprom;
244 return(0);
245 default:
246 return(-1);
247 }
248 }
249
250 /* Get slot/port corresponding to specified network IRQ */
251 static inline void
252 c1700_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port)
253 {
254 irq -= C1700_NETIO_IRQ_BASE;
255 *port = irq & C1700_NETIO_IRQ_PORT_MASK;
256 *slot = irq >> C1700_NETIO_IRQ_PORT_BITS;
257 }
258
259 /* Get network IRQ for specified slot/port */
260 u_int c1700_net_irq_for_slot_port(u_int slot,u_int port)
261 {
262 u_int irq;
263
264 irq = (slot << C1700_NETIO_IRQ_PORT_BITS) + port;
265 irq += C1700_NETIO_IRQ_BASE;
266
267 return(irq);
268 }
269
270 /* Find Cisco 1700 Mainboard info */
271 static struct c1700_mb_id *c1700_get_mb_info(char *mainboard_type)
272 {
273 int i;
274
275 for(i=0;c1700_mainboard_id[i].name;i++)
276 if (!strcmp(c1700_mainboard_id[i].name,mainboard_type))
277 return(&c1700_mainboard_id[i]);
278
279 return NULL;
280 }
281
282 /* Show all available mainboards */
283 static void c1700_mainboard_show_drivers(void)
284 {
285 int i;
286
287 printf("Available C1700 chassis drivers:\n");
288
289 for(i=0;c1700_mainboard_id[i].name;i++)
290 printf(" * %s %s\n",
291 c1700_mainboard_id[i].name,
292 !c1700_mainboard_id[i].supported ? "(NOT WORKING)" : "");
293
294 printf("\n");
295 }
296
297 /* Set the base MAC address of the chassis */
298 static int c1700_burn_mac_addr(c1700_t *router,n_eth_addr_t *addr)
299 {
300 int i;
301
302 for(i=0;i<3;i++) {
303 router->vm->chassis_cookie[i+1] = addr->eth_addr_byte[i*2] << 8;
304 router->vm->chassis_cookie[i+1] |= addr->eth_addr_byte[(i*2)+1];
305 }
306
307 return(0);
308 }
309
310 /* Set mainboard type */
311 int c1700_mainboard_set_type(c1700_t *router,char *mainboard_type)
312 {
313 struct c1700_mb_id *mb_info;
314
315 if (router->vm->status == VM_STATUS_RUNNING) {
316 vm_error(router->vm,"unable to change mainboard type when online.\n");
317 return(-1);
318 }
319
320 if (!(mb_info = c1700_get_mb_info(mainboard_type))) {
321 vm_error(router->vm,"unknown mainboard '%s'\n",mainboard_type);
322 return(-1);
323 }
324
325 router->mainboard_type = mainboard_type;
326
327 /* Set the cookie */
328 memcpy(router->vm->chassis_cookie,
329 eeprom_c1700_mb_data,sizeof(eeprom_c1700_mb_data));
330
331 router->vm->chassis_cookie[6] = mb_info->id;
332
333 /* Set the chassis base MAC address */
334 c1700_burn_mac_addr(router,&router->mac_addr);
335
336 /* Set the mainboard driver */
337 if (vm_slot_active(router->vm,0,0))
338 vm_slot_remove_binding(router->vm,0,0);
339
340 vm_slot_add_binding(router->vm,mb_info->mb_driver,0,0);
341 return(0);
342 }
343
344 /* Set chassis MAC address */
345 int c1700_chassis_set_mac_addr(c1700_t *router,char *mac_addr)
346 {
347 if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) {
348 vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr);
349 return(-1);
350 }
351
352 /* Set the chassis base MAC address */
353 c1700_burn_mac_addr(router,&router->mac_addr);
354 return(0);
355 }
356
357 /* Initialize a Cisco 1700 */
358 static int c1700_init(c1700_t *router)
359 {
360 vm_instance_t *vm = router->vm;
361
362 /* Create the PCI bus */
363 if (!(vm->pci_bus[0] = pci_bus_create("PCI0",0))) {
364 vm_error(vm,"unable to create PCI data.\n");
365 return(-1);
366 }
367
368 /* Bind PCI bus to slots 0 and 1 */
369 vm->slots_pci_bus[0] = vm->pci_bus[0];
370 vm->slots_pci_bus[1] = vm->pci_bus[0];
371
372 vm->elf_machine_id = C1700_ELF_MACHINE_ID;
373 return(0);
374 }
375
376 /* Show C1700 hardware info */
377 void c1700_show_hardware(c1700_t *router)
378 {
379 vm_instance_t *vm = router->vm;
380
381 printf("C1700 instance '%s' (id %d):\n",vm->name,vm->instance_id);
382
383 printf(" VM Status : %d\n",vm->status);
384 printf(" RAM size : %u Mb\n",vm->ram_size);
385 printf(" NVRAM size : %u Kb\n",vm->nvram_size);
386 printf(" IOS image : %s\n\n",vm->ios_image);
387
388 if (vm->debug_level > 0) {
389 dev_show_list(vm);
390 pci_dev_show_list(vm->pci_bus[0]);
391 pci_dev_show_list(vm->pci_bus[1]);
392 printf("\n");
393 }
394 }
395
396 /* Initialize default parameters for a C1700 */
397 static void c1700_init_defaults(c1700_t *router)
398 {
399 vm_instance_t *vm = router->vm;
400 n_eth_addr_t *m;
401 m_uint16_t pid;
402
403 /* Set platform slots characteristics */
404 vm->nr_slots = C1700_MAX_NM_BAYS;
405 vm->slots_type = CISCO_CARD_TYPE_NM;
406 vm->slots_drivers = nm_drivers;
407
408 pid = (m_uint16_t)getpid();
409
410 /* Generate a chassis MAC address based on the instance ID */
411 m = &router->mac_addr;
412 m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
413 m->eth_addr_byte[1] = vm->instance_id & 0xFF;
414 m->eth_addr_byte[2] = pid >> 8;
415 m->eth_addr_byte[3] = pid & 0xFF;
416 m->eth_addr_byte[4] = 0x00;
417 m->eth_addr_byte[5] = 0x00;
418
419 c1700_init_eeprom_groups(router);
420 c1700_mainboard_set_type(router,C1700_DEFAULT_MAINBOARD);
421 c1700_burn_mac_addr(router,&router->mac_addr);
422
423 vm->ram_mmap = C1700_DEFAULT_RAM_MMAP;
424 vm->ram_size = C1700_DEFAULT_RAM_SIZE;
425 vm->rom_size = C1700_DEFAULT_ROM_SIZE;
426 vm->nvram_size = C1700_DEFAULT_NVRAM_SIZE;
427 vm->conf_reg_setup = C1700_DEFAULT_CONF_REG;
428 vm->clock_divisor = C1700_DEFAULT_CLOCK_DIV;
429 vm->nvram_rom_space = C1700_NVRAM_ROM_RES_SIZE;
430 vm->nm_iomem_size = C1700_DEFAULT_IOMEM_SIZE;
431
432 vm->pcmcia_disk_size[0] = C1700_DEFAULT_DISK0_SIZE;
433 vm->pcmcia_disk_size[1] = C1700_DEFAULT_DISK1_SIZE;
434 }
435
436 /* Set an IRQ */
437 static void c1700_set_irq(vm_instance_t *vm,u_int irq)
438 {
439 c1700_t *router = VM_C1700(vm);
440 cpu_ppc_t *cpu = CPU_PPC32(vm->boot_cpu);
441 u_int slot,port;
442
443 switch(irq) {
444 case C1700_VTIMER_IRQ:
445 mpc860_set_pending_irq(router->mpc_data,30);
446 break;
447 case C1700_DUART_IRQ:
448 mpc860_set_pending_irq(router->mpc_data,29);
449 break;
450 case C1700_NETIO_IRQ:
451 mpc860_set_pending_irq(router->mpc_data,25);
452 break;
453 case C1700_PA_MGMT_IRQ:
454 mpc860_set_pending_irq(router->mpc_data,27);
455 break;
456
457 case C1700_NETIO_IRQ_BASE ... C1700_NETIO_IRQ_END:
458 c1700_net_irq_get_slot_port(irq,&slot,&port);
459 dev_c1700_iofpga_net_set_irq(router->iofpga_data,slot,port);
460 break;
461
462 /* IRQ test */
463 case 255:
464 mpc860_set_pending_irq(router->mpc_data,24);
465 break;
466 }
467
468 if (vm->irq_idle_preempt[irq])
469 cpu_idle_break_wait(cpu->gen);
470 }
471
472 /* Clear an IRQ */
473 static void c1700_clear_irq(vm_instance_t *vm,u_int irq)
474 {
475 c1700_t *router = VM_C1700(vm);
476 u_int slot,port;
477
478 switch(irq) {
479 case C1700_VTIMER_IRQ:
480 mpc860_clear_pending_irq(router->mpc_data,30);
481 break;
482 case C1700_DUART_IRQ:
483 mpc860_clear_pending_irq(router->mpc_data,29);
484 break;
485 case C1700_NETIO_IRQ:
486 mpc860_clear_pending_irq(router->mpc_data,25);
487 break;
488 case C1700_PA_MGMT_IRQ:
489 mpc860_clear_pending_irq(router->mpc_data,27);
490 break;
491
492 case C1700_NETIO_IRQ_BASE ... C1700_NETIO_IRQ_END:
493 c1700_net_irq_get_slot_port(irq,&slot,&port);
494 dev_c1700_iofpga_net_clear_irq(router->iofpga_data,slot,port);
495 break;
496
497 /* IRQ test */
498 case 255:
499 mpc860_clear_pending_irq(router->mpc_data,24);
500 break;
501 }
502 }
503
504 /* Initialize the C1700 Platform */
505 static int c1700_init_platform(c1700_t *router)
506 {
507 vm_instance_t *vm = router->vm;
508 vm_obj_t *obj;
509 cpu_ppc_t *cpu;
510 cpu_gen_t *gen;
511
512 /* Copy config register setup into "active" config register */
513 vm->conf_reg = vm->conf_reg_setup;
514
515 /* Create Console and AUX ports */
516 vm_init_vtty(vm);
517
518 /* Create a CPU group */
519 vm->cpu_group = cpu_group_create("System CPU");
520
521 /* Initialize the virtual PowerPC processor */
522 if (!(gen = cpu_create(vm,CPU_TYPE_PPC32,0))) {
523 vm_error(vm,"unable to create CPU!\n");
524 return(-1);
525 }
526
527 cpu = CPU_PPC32(gen);
528
529 /* Add this CPU to the system CPU group */
530 cpu_group_add(vm->cpu_group,gen);
531 vm->boot_cpu = gen;
532
533 /* Set processor ID */
534 ppc32_set_pvr(cpu,0x00500202);
535
536 /* Mark the Network IO interrupt as high priority */
537 vm->irq_idle_preempt[C1700_NETIO_IRQ] = TRUE;
538 vm->irq_idle_preempt[C1700_DUART_IRQ] = TRUE;
539
540 /* Copy some parameters from VM to CPU (idle PC, ...) */
541 cpu->idle_pc = vm->idle_pc;
542
543 if (vm->timer_irq_check_itv)
544 cpu->timer_irq_check_itv = vm->timer_irq_check_itv;
545
546 /* Remote emulator control */
547 dev_remote_control_init(vm,0xf6000000,0x1000);
548
549 /* MPC860 */
550 cpu->mpc860_immr = C1700_MPC860_ADDR;
551
552 if (dev_mpc860_init(vm,"MPC860",C1700_MPC860_ADDR,0x10000) == -1)
553 return(-1);
554
555 if (!(obj = vm_object_find(router->vm,"MPC860")))
556 return(-1);
557
558 router->mpc_data = obj->data;
559
560 /* IO FPGA */
561 if (dev_c1700_iofpga_init(router,C1700_IOFPGA_ADDR,0x10000) == -1)
562 return(-1);
563
564 if (!(obj = vm_object_find(router->vm,"io_fpga")))
565 return(-1);
566
567 router->iofpga_data = obj->data;
568
569 /* Initialize the chassis */
570 if (c1700_init(router) == -1)
571 return(-1);
572
573 /* Initialize RAM */
574 vm_ram_init(vm,0x00000000ULL);
575
576 /* Initialize ROM */
577 if (!vm->rom_filename) {
578 /* use embedded ROM */
579 dev_rom_init(vm,"rom",C1700_ROM_ADDR,512*1024,
580 ppc32_microcode,ppc32_microcode_len);
581 } else {
582 /* use alternate ROM */
583 dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE,C1700_ROM_ADDR,512*1024);
584 }
585
586 /* RAM aliasing */
587 dev_create_ram_alias(vm,"ram_alias","ram",0x80000000,vm->ram_size*1048576);
588
589 /* NVRAM */
590 dev_nvram_init(vm,"nvram",
591 C1700_NVRAM_ADDR,vm->nvram_size*1024,&vm->conf_reg);
592
593
594 /* Bootflash (4 Mb) */
595 dev_bootflash_init(vm,"bootflash","c1700-bootflash-4mb",C1700_FLASH_ADDR);
596
597 /* Initialize the NS16552 DUART */
598 dev_ns16552_init(vm,C1700_DUART_ADDR,0x1000,0,C1700_DUART_IRQ,
599 vm->vtty_con,vm->vtty_aux);
600
601 /* Initialize Network Modules */
602 if (vm_slot_init_all(vm) == -1)
603 return(-1);
604
605 /* Show device list */
606 c1700_show_hardware(router);
607 return(0);
608 }
609
610 static struct ppc32_bat_prog bat_array[] = {
611 { PPC32_IBAT_IDX, 0, 0xfff0001e, 0xfff00001 },
612 { PPC32_IBAT_IDX, 1, 0x00001ffe, 0x00000001 },
613 { PPC32_IBAT_IDX, 2, 0x00000000, 0xee3e0072 },
614 { PPC32_IBAT_IDX, 3, 0x80001ffe, 0x00000001 },
615
616 { PPC32_DBAT_IDX, 0, 0x80001ffe, 0x00000042 },
617 { PPC32_DBAT_IDX, 1, 0x00001ffe, 0x0000002a },
618 { PPC32_DBAT_IDX, 2, 0x40007ffe, 0x4000002a },
619 { PPC32_DBAT_IDX, 3, 0xf0001ffe, 0xf000002a },
620 { -1, -1, 0, 0 },
621 };
622
623 /* Boot the IOS image */
624 static int c1700_boot_ios(c1700_t *router)
625 {
626 vm_instance_t *vm = router->vm;
627 cpu_ppc_t *cpu;
628
629 if (!vm->boot_cpu)
630 return(-1);
631
632 /* Suspend CPU activity since we will restart directly from ROM */
633 vm_suspend(vm);
634
635 /* Check that CPU activity is really suspended */
636 if (cpu_group_sync_state(vm->cpu_group) == -1) {
637 vm_error(vm,"unable to sync with system CPUs.\n");
638 return(-1);
639 }
640
641 /* Reset the boot CPU */
642 cpu = CPU_PPC32(vm->boot_cpu);
643 ppc32_reset(cpu);
644
645 /* Adjust stack pointer */
646 cpu->gpr[1] |= 0x80000000;
647
648 /* Load BAT registers */
649 printf("Loading BAT registers\n");
650 ppc32_load_bat_array(cpu,bat_array);
651 cpu->msr |= PPC32_MSR_IR|PPC32_MSR_DR;
652
653 /* IRQ routing */
654 vm->set_irq = c1700_set_irq;
655 vm->clear_irq = c1700_clear_irq;
656
657 /* Load IOS image */
658 if (ppc32_load_elf_image(cpu,vm->ios_image,
659 (vm->ghost_status == VM_GHOST_RAM_USE),
660 &vm->ios_entry_point) < 0)
661 {
662 vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
663 return(-1);
664 }
665
666 cpu->ia = 0;
667
668 /* Launch the simulation */
669 printf("\nC1700 '%s': starting simulation (CPU0 IA=0x%8.8x), "
670 "JIT %sabled.\n",
671 vm->name,cpu->ia,vm->jit_use ? "en":"dis");
672
673 vm_log(vm,"C1700_BOOT",
674 "starting instance (CPU0 PC=0x%8.8x,idle_pc=0x%8.8x,JIT %s)\n",
675 cpu->ia,cpu->idle_pc,vm->jit_use ? "on":"off");
676
677 /* Start main CPU */
678 if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
679 vm->status = VM_STATUS_RUNNING;
680 cpu_start(vm->boot_cpu);
681 } else {
682 vm->status = VM_STATUS_SHUTDOWN;
683 }
684 return(0);
685 }
686
687 /* Initialize a Cisco 1700 instance */
688 static int c1700_init_instance(vm_instance_t *vm)
689 {
690 c1700_t *router = VM_C1700(vm);
691 m_uint32_t rom_entry_point;
692 cpu_ppc_t *cpu0;
693
694 if (!vm->ios_image) {
695 vm_error(vm,"no Cisco IOS image defined.");
696 return(-1);
697 }
698
699 /* Initialize the C1700 platform */
700 if (c1700_init_platform(router) == -1) {
701 vm_error(vm,"unable to initialize the platform hardware.\n");
702 return(-1);
703 }
704
705 /* Load IOS configuration file */
706 if (vm->ios_config != NULL) {
707 vm_nvram_push_config(vm,vm->ios_config);
708 vm->conf_reg &= ~0x40;
709 }
710
711 /* Load ROM (ELF image or embedded) */
712 cpu0 = CPU_PPC32(vm->boot_cpu);
713 rom_entry_point = (m_uint32_t)PPC32_ROM_START;
714
715 if ((vm->rom_filename != NULL) &&
716 (ppc32_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
717 {
718 vm_error(vm,"unable to load alternate ROM '%s', "
719 "fallback to embedded ROM.\n\n",vm->rom_filename);
720 vm->rom_filename = NULL;
721 }
722
723 return(c1700_boot_ios(router));
724 }
725
726 /* Stop a Cisco 1700 instance */
727 static int c1700_stop_instance(vm_instance_t *vm)
728 {
729 printf("\nC1700 '%s': stopping simulation.\n",vm->name);
730 vm_log(vm,"C1700_STOP","stopping simulation.\n");
731
732 /* Stop all CPUs */
733 if (vm->cpu_group != NULL) {
734 vm_stop(vm);
735
736 if (cpu_group_sync_state(vm->cpu_group) == -1) {
737 vm_error(vm,"unable to sync with system CPUs.\n");
738 return(-1);
739 }
740 }
741
742 /* Free resources that were used during execution to emulate hardware */
743 vm_slot_shutdown_all(vm);
744 vm_hardware_shutdown(vm);
745 return(0);
746 }
747
748 /* Get MAC address MSB */
749 static u_int c1700_get_mac_addr_msb(void)
750 {
751 return(0xD0);
752 }
753
754 /* Parse specific options for the Cisco 1700 platform */
755 static int c1700_cli_parse_options(vm_instance_t *vm,int option)
756 {
757 c1700_t *router = VM_C1700(vm);
758
759 switch(option) {
760 /* IO memory reserved for NMs (in percents!) */
761 case OPT_IOMEM_SIZE:
762 vm->nm_iomem_size = 0x8000 | atoi(optarg);
763 break;
764
765 /* Mainboard type */
766 case 't':
767 c1700_mainboard_set_type(router,optarg);
768 break;
769
770 /* Unknown option */
771 default:
772 return(-1);
773 }
774
775 return(0);
776 }
777
778 /* Show specific CLI options */
779 static void c1700_cli_show_options(vm_instance_t *vm)
780 {
781 printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n"
782 " -t <chassis_type> : Select Chassis type\n"
783 " -p <wic_desc> : Define a WIC Module\n"
784 " -s <wic_nio> : Bind a Network IO interface to a WIC\n",
785 vm->nm_iomem_size);
786 }
787
788 /* Platform definition */
789 static vm_platform_t c1700_platform = {
790 "c1700", "C1700", "1700",
791 c1700_create_instance,
792 c1700_delete_instance,
793 c1700_init_instance,
794 c1700_stop_instance,
795 c1700_nvram_extract_config,
796 c1700_nvram_push_config,
797 c1700_get_mac_addr_msb,
798 c1700_save_config,
799 c1700_cli_parse_options,
800 c1700_cli_show_options,
801 c1700_mainboard_show_drivers,
802 };
803
804 /* Register the c1700 platform */
805 int c1700_platform_register(void)
806 {
807 if (vm_platform_register(&c1700_platform) == -1)
808 return(-1);
809
810 return(hypervisor_c1700_init(&c1700_platform));
811 }

  ViewVC Help
Powered by ViewVC 1.1.26