/[dynamips]/trunk/dev_c3745.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_c3745.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: 23565 byte(s)
make working copy

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

  ViewVC Help
Powered by ViewVC 1.1.26