/[dynamips]/trunk/dev_c6msfc1.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

Annotation of /trunk/dev_c6msfc1.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 dpavlin 11 /*
2     * Cisco router simulation platform.
3     * Copyright (c) 2007 Christophe Fillot (cf@utc.fr)
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     cisco_eeprom_free(&router->pem_eeprom);
401    
402     /* Free all resources used by VM */
403     vm_free(vm);
404    
405     /* Free the router structure */
406     free(router);
407     return(TRUE);
408     }
409    
410     /* Create the main PCI bus for a GT64010 based system */
411     static int c6msfc1_init_gt64010(c6msfc1_t *router)
412     {
413     vm_instance_t *vm = router->vm;
414    
415     if (!(vm->pci_bus[0] = pci_bus_create("PCI Bus 0",0))) {
416     vm_error(vm,"unable to create PCI data.\n");
417     return(-1);
418     }
419    
420     return(dev_gt64010_init(vm,"gt64010",C6MSFC1_GT64K_ADDR,0x1000,
421     C6MSFC1_GT64K_IRQ));
422     }
423    
424     /* Initialize a MSFC1 board */
425     static int c6msfc1_init_hw(c6msfc1_t *router)
426     {
427     vm_instance_t *vm = router->vm;
428    
429     /* Set the processor type: R5000 */
430     mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R5000);
431    
432     /* Initialize the Galileo GT-64010 PCI controller */
433     if (c6msfc1_init_gt64010(router) == -1)
434     return(-1);
435    
436     /* Create PCI bus 1 */
437     vm->pci_bus_pool[24] = pci_bus_create("PCI Bus 1",-1);
438     dev_dec21154_init(vm->pci_bus[0],1,vm->pci_bus_pool[24]);
439    
440     /* Initialize SRAM (4Mb) */
441     dev_c7200_sram_init(vm,"sram",C6MSFC1_SRAM_ADDR,C6MSFC1_SRAM_SIZE,
442     vm->pci_bus_pool[24],0);
443    
444     /* PCI IO space */
445     if (!(vm->pci_io_space = pci_io_data_init(vm,C6MSFC1_PCI_IO_ADDR)))
446     return(-1);
447    
448     /* Cirrus Logic PD6729 (PCI-to-PCMCIA host adapter) */
449     dev_clpd6729_init(vm,vm->pci_bus[0],5,vm->pci_io_space,0x402,0x403);
450    
451     return(0);
452     }
453    
454     /* Show MSFC1 hardware info */
455     void c6msfc1_show_hardware(c6msfc1_t *router)
456     {
457     vm_instance_t *vm = router->vm;
458    
459     printf("C6MSFC1 instance '%s' (id %d):\n",vm->name,vm->instance_id);
460    
461     printf(" VM Status : %d\n",vm->status);
462     printf(" RAM size : %u Mb\n",vm->ram_size);
463     printf(" IOMEM size : %u Mb\n",vm->iomem_size);
464     printf(" NVRAM size : %u Kb\n",vm->nvram_size);
465     printf(" IOS image : %s\n\n",vm->ios_image);
466    
467     if (vm->debug_level > 0) {
468     dev_show_list(vm);
469     pci_dev_show_list(vm->pci_bus[0]);
470     pci_dev_show_list(vm->pci_bus[1]);
471     printf("\n");
472     }
473     }
474    
475     /* Initialize default parameters for a MSFC1 */
476     static void c6msfc1_init_defaults(c6msfc1_t *router)
477     {
478     vm_instance_t *vm = router->vm;
479     n_eth_addr_t *m;
480     m_uint16_t pid;
481    
482     /* Set platform slots characteristics */
483     vm->nr_slots = C6MSFC1_MAX_PA_BAYS;
484     vm->slots_type = CISCO_CARD_TYPE_PA;
485     vm->slots_drivers = pa_drivers;
486    
487     pid = (m_uint16_t)getpid();
488    
489     /* Generate a chassis MAC address based on the instance ID */
490     m = &router->mac_addr;
491     m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
492     m->eth_addr_byte[1] = vm->instance_id & 0xFF;
493     m->eth_addr_byte[2] = pid >> 8;
494     m->eth_addr_byte[3] = pid & 0xFF;
495     m->eth_addr_byte[4] = 0x00;
496     m->eth_addr_byte[5] = 0x00;
497    
498     /* Default slot: 1 */
499     router->msfc_slot = 1;
500    
501     c6msfc1_set_eeprom(router);
502     c6msfc1_init_eeprom_groups(router);
503    
504     /* Create EOBC and IBC interfaces */
505     vm_slot_add_binding(vm,"C6MSFC1_EOBC",0,0);
506     vm_slot_add_binding(vm,"C6MSFC1_IBC",1,0);
507    
508     vm->ram_mmap = C6MSFC1_DEFAULT_RAM_MMAP;
509     vm->ram_size = C6MSFC1_DEFAULT_RAM_SIZE;
510     vm->rom_size = C6MSFC1_DEFAULT_ROM_SIZE;
511     vm->nvram_size = C6MSFC1_DEFAULT_NVRAM_SIZE;
512     vm->iomem_size = 0;
513     vm->conf_reg_setup = C6MSFC1_DEFAULT_CONF_REG;
514     vm->clock_divisor = C6MSFC1_DEFAULT_CLOCK_DIV;
515     vm->nvram_rom_space = C6MSFC1_NVRAM_ROM_RES_SIZE;
516     }
517    
518     /* Run the checklist */
519     static int c6msfc1_checklist(c6msfc1_t *router)
520     {
521     struct vm_instance *vm = router->vm;
522     int res = 0;
523    
524     res += vm_object_check(vm,"ram");
525     res += vm_object_check(vm,"rom");
526     res += vm_object_check(vm,"nvram");
527     res += vm_object_check(vm,"zero");
528    
529     if (res < 0)
530     vm_error(vm,"incomplete initialization (no memory?)\n");
531    
532     return(res);
533     }
534    
535     /* Initialize Port Adapters */
536     static int c6msfc1_init_platform_pa(c6msfc1_t *router)
537     {
538     return(vm_slot_init_all(router->vm));
539     }
540    
541     /* Initialize the MSFC1 Platform */
542     static int c6msfc1_init_platform(c6msfc1_t *router)
543     {
544     struct vm_instance *vm = router->vm;
545     cpu_mips_t *cpu0;
546     cpu_gen_t *gen0;
547     vm_obj_t *obj;
548    
549     /* Copy config register setup into "active" config register */
550     vm->conf_reg = vm->conf_reg_setup;
551    
552     /* Create Console and AUX ports */
553     vm_init_vtty(vm);
554    
555     /* Create a CPU group */
556     vm->cpu_group = cpu_group_create("System CPU");
557    
558     /* Initialize the virtual MIPS processor */
559     if (!(gen0 = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
560     vm_error(vm,"unable to create CPU0!\n");
561     return(-1);
562     }
563    
564     cpu0 = CPU_MIPS64(gen0);
565    
566     /* Add this CPU to the system CPU group */
567     cpu_group_add(vm->cpu_group,gen0);
568     vm->boot_cpu = gen0;
569    
570     /* Initialize the IRQ routing vectors */
571     vm->set_irq = mips64_vm_set_irq;
572     vm->clear_irq = mips64_vm_clear_irq;
573    
574     /* Mark the Network IO interrupt as high priority */
575     cpu0->irq_idle_preempt[C6MSFC1_NETIO_IRQ] = TRUE;
576     cpu0->irq_idle_preempt[C6MSFC1_GT64K_IRQ] = TRUE;
577    
578     /* Copy some parameters from VM to CPU0 (idle PC, ...) */
579     cpu0->idle_pc = vm->idle_pc;
580    
581     if (vm->timer_irq_check_itv)
582     cpu0->timer_irq_check_itv = vm->timer_irq_check_itv;
583    
584     /*
585     * On the MSFC1, bit 33 of physical addresses is used to bypass L2 cache.
586     * We clear it systematically.
587     */
588     cpu0->addr_bus_mask = C6MSFC1_ADDR_BUS_MASK;
589    
590     /* Remote emulator control */
591     dev_remote_control_init(vm,0x16000000,0x1000);
592    
593     /* Bootflash (8 Mb) */
594     dev_bootflash_init(vm,"bootflash","c7200-bootflash-8mb",
595     C6MSFC1_BOOTFLASH_ADDR);
596    
597     /* NVRAM and calendar */
598     dev_nvram_init(vm,"nvram",C6MSFC1_NVRAM_ADDR,
599     vm->nvram_size*1024,&vm->conf_reg);
600    
601     /* Bit-bucket zone */
602     dev_zero_init(vm,"zero",C6MSFC1_BITBUCKET_ADDR,0xc00000);
603    
604     /* Initialize the NPE board */
605     if (c6msfc1_init_hw(router) == -1)
606     return(-1);
607    
608     /* Initialize RAM */
609     vm_ram_init(vm,0x00000000ULL);
610    
611     /* Initialize ROM */
612     if (!vm->rom_filename) {
613     /* use embedded ROM */
614     dev_rom_init(vm,"rom",C6MSFC1_ROM_ADDR,vm->rom_size*1048576,
615     mips64_microcode,mips64_microcode_len);
616     } else {
617     /* use alternate ROM */
618     dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE,
619     C6MSFC1_ROM_ADDR,vm->rom_size*1048576);
620     }
621    
622     /* Byte swapping */
623     dev_bswap_init(vm,"mem_bswap",C6MSFC1_BSWAP_ADDR,1024*1048576,0x00000000ULL);
624    
625     /* PCI IO space */
626     if (!(vm->pci_io_space = pci_io_data_init(vm,C6MSFC1_PCI_IO_ADDR)))
627     return(-1);
628    
629     /* Initialize the Port Adapters */
630     if (c6msfc1_init_platform_pa(router) == -1)
631     return(-1);
632    
633     /* Verify the check list */
634     if (c6msfc1_checklist(router) == -1)
635     return(-1);
636    
637     /* Midplane FPGA */
638     if (dev_c6msfc1_mpfpga_init(router,C6MSFC1_MPFPGA_ADDR,0x1000) == -1)
639     return(-1);
640    
641     if (!(obj = vm_object_find(router->vm,"mp_fpga")))
642     return(-1);
643    
644     router->mpfpga_data = obj->data;
645    
646     /* IO FPGA */
647     if (dev_c6msfc1_iofpga_init(router,C6MSFC1_IOFPGA_ADDR,0x1000) == -1)
648     return(-1);
649    
650     /* Show device list */
651     c6msfc1_show_hardware(router);
652     return(0);
653     }
654    
655     /* Boot the IOS image */
656     static int c6msfc1_boot_ios(c6msfc1_t *router)
657     {
658     vm_instance_t *vm = router->vm;
659     cpu_mips_t *cpu;
660    
661     if (!vm->boot_cpu)
662     return(-1);
663    
664     /* Suspend CPU activity since we will restart directly from ROM */
665     vm_suspend(vm);
666    
667     /* Check that CPU activity is really suspended */
668     if (cpu_group_sync_state(vm->cpu_group) == -1) {
669     vm_error(vm,"unable to sync with system CPUs.\n");
670     return(-1);
671     }
672    
673     /* Reset the boot CPU */
674     cpu = CPU_MIPS64(vm->boot_cpu);
675     mips64_reset(cpu);
676    
677     /* Load IOS image */
678     if (mips64_load_elf_image(cpu,vm->ios_image,
679     (vm->ghost_status == VM_GHOST_RAM_USE),
680     &vm->ios_entry_point) < 0)
681     {
682     vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
683     return(-1);
684     }
685    
686     /* Launch the simulation */
687     printf("\nC6MSFC1 '%s': starting simulation (CPU0 PC=0x%llx), "
688     "JIT %sabled.\n",
689     vm->name,cpu->pc,vm->jit_use ? "en":"dis");
690    
691     vm_log(vm,"C6MSFC1_BOOT",
692     "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
693     cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
694    
695     /* Start main CPU */
696     if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
697     vm->status = VM_STATUS_RUNNING;
698     cpu_start(vm->boot_cpu);
699     } else {
700     vm->status = VM_STATUS_SHUTDOWN;
701     }
702     return(0);
703     }
704    
705     /* Set an IRQ */
706     static void c6msfc1_set_irq(vm_instance_t *vm,u_int irq)
707     {
708     c6msfc1_t *router = VM_C6MSFC1(vm);
709     cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
710     u_int slot,port;
711    
712     switch(irq) {
713     case 0 ... 7:
714     mips64_set_irq(cpu0,irq);
715    
716     if (cpu0->irq_idle_preempt[irq])
717     cpu_idle_break_wait(cpu0->gen);
718     break;
719    
720     case C6MSFC1_NETIO_IRQ_BASE ... C6MSFC1_NETIO_IRQ_END:
721     c6msfc1_net_irq_get_slot_port(irq,&slot,&port);
722     dev_c6msfc1_mpfpga_net_set_irq(router->mpfpga_data,slot,port);
723     break;
724     }
725     }
726    
727     /* Clear an IRQ */
728     static void c6msfc1_clear_irq(vm_instance_t *vm,u_int irq)
729     {
730     c6msfc1_t *router = VM_C6MSFC1(vm);
731     cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
732     u_int slot,port;
733    
734     switch(irq) {
735     case 0 ... 7:
736     mips64_clear_irq(cpu0,irq);
737     break;
738    
739     case C6MSFC1_NETIO_IRQ_BASE ... C6MSFC1_NETIO_IRQ_END:
740     c6msfc1_net_irq_get_slot_port(irq,&slot,&port);
741     dev_c6msfc1_mpfpga_net_clear_irq(router->mpfpga_data,slot,port);
742     break;
743     }
744     }
745    
746     /* Initialize a MSFC1 instance */
747     static int c6msfc1_init_instance(vm_instance_t *vm)
748     {
749     c6msfc1_t *router = VM_C6MSFC1(vm);
750     m_uint32_t rom_entry_point;
751     cpu_mips_t *cpu0;
752    
753     /* Initialize the MSFC1 platform */
754     if (c6msfc1_init_platform(router) == -1) {
755     vm_error(vm,"unable to initialize the platform hardware.\n");
756     return(-1);
757     }
758    
759     /* IRQ routing */
760     vm->set_irq = c6msfc1_set_irq;
761     vm->clear_irq = c6msfc1_clear_irq;
762    
763     /* Load IOS configuration file */
764     if (vm->ios_config != NULL) {
765     vm_nvram_push_config(vm,vm->ios_config);
766     vm->conf_reg &= ~0x40;
767     }
768    
769     /* Load ROM (ELF image or embedded) */
770     cpu0 = CPU_MIPS64(vm->boot_cpu);
771     rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
772    
773     if ((vm->rom_filename != NULL) &&
774     (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
775     {
776     vm_error(vm,"unable to load alternate ROM '%s', "
777     "fallback to embedded ROM.\n\n",vm->rom_filename);
778     vm->rom_filename = NULL;
779     }
780    
781     /* Load symbol file */
782     if (vm->sym_filename) {
783     mips64_sym_load_file(cpu0,vm->sym_filename);
784     cpu0->sym_trace = 1;
785     }
786    
787     return(c6msfc1_boot_ios(router));
788     }
789    
790     /* Stop a MSFC1 instance */
791     static int c6msfc1_stop_instance(vm_instance_t *vm)
792     {
793     printf("\nC6MSFC1 '%s': stopping simulation.\n",vm->name);
794     vm_log(vm,"C6MSFC1_STOP","stopping simulation.\n");
795    
796     /* Stop all CPUs */
797     if (vm->cpu_group != NULL) {
798     vm_stop(vm);
799    
800     if (cpu_group_sync_state(vm->cpu_group) == -1) {
801     vm_error(vm,"unable to sync with system CPUs.\n");
802     return(-1);
803     }
804     }
805    
806     /* Free resources that were used during execution to emulate hardware */
807     vm_slot_shutdown_all(vm);
808     vm_hardware_shutdown(vm);
809     return(0);
810     }
811    
812     /* Get MAC address MSB */
813     static u_int c6msfc1_get_mac_addr_msb(void)
814     {
815     return(0xC6);
816     }
817    
818     /* Show specific CLI options */
819     static void c6msfc1_cli_show_options(vm_instance_t *vm)
820     {
821     printf(" -s <pa_nio> : Bind a Network IO interface to a "
822     "Port Adapter\n");
823     }
824    
825     /* Platform definition */
826     static vm_platform_t c6msfc1_platform = {
827     "c6msfc1", "C6MSFC1", "C6MSFC1",
828     c6msfc1_create_instance,
829     c6msfc1_delete_instance,
830     c6msfc1_init_instance,
831     c6msfc1_stop_instance,
832     c6msfc1_nvram_extract_config,
833     c6msfc1_nvram_push_config,
834     c6msfc1_get_mac_addr_msb,
835     NULL,
836     NULL,
837     c6msfc1_cli_show_options,
838     NULL,
839     };
840    
841     /* Register the C6-MSFC1 platform */
842     int c6msfc1_platform_register(void)
843     {
844     return(vm_platform_register(&c6msfc1_platform));
845     }

  ViewVC Help
Powered by ViewVC 1.1.26