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