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

Annotation of /trunk/dev_c3725.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations)
Sat Oct 6 16:29:14 2007 UTC (16 years, 6 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7/dev_c3725.c
File MIME type: text/plain
File size: 37408 byte(s)
dynamips-0.2.7

1 dpavlin 4 /*
2 dpavlin 8 * Cisco router simulation platform.
3 dpavlin 4 * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4     *
5     * Generic Cisco 3725 routines and definitions (EEPROM,...).
6     */
7    
8     #include <stdio.h>
9     #include <stdlib.h>
10     #include <string.h>
11     #include <unistd.h>
12     #include <sys/types.h>
13     #include <assert.h>
14    
15 dpavlin 7 #include "cpu.h"
16     #include "vm.h"
17 dpavlin 4 #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 dpavlin 7 #include "dev_rom.h"
24 dpavlin 4 #include "dev_c3725.h"
25 dpavlin 8 #include "dev_c3725_iofpga.h"
26 dpavlin 4 #include "dev_vtty.h"
27     #include "registry.h"
28    
29     /* ======================================================================== */
30     /* EEPROM definitions */
31     /* ======================================================================== */
32    
33     /* Cisco 3725 mainboard EEPROM */
34     static m_uint16_t eeprom_c3725_mainboard_data[] = {
35     0x04FF, 0xC18B, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0x5809,
36     0x6140, 0x0259, 0xC046, 0x0320, 0x003F, 0x1302, 0x4244, 0x3085,
37     0x1C10, 0x8206, 0x80FF, 0xFFFF, 0xFFC4, 0x08FF, 0xFFFF, 0xFFFF,
38     0xFFFF, 0xFF81, 0xFFFF, 0xFFFF, 0x03FF, 0x04FF, 0xC28B, 0x5858,
39     0x5858, 0x5858, 0x5858, 0x5858, 0x58C3, 0x0600, 0x1319, 0x5C6F,
40     0x7043, 0x0030, 0xC508, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x4100,
41     0x0101, 0x02FF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
42     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
43     };
44    
45     struct cisco_eeprom eeprom_c3725_mainboard = {
46     "C3725 Backplane",
47     eeprom_c3725_mainboard_data,
48     sizeof(eeprom_c3725_mainboard_data)/2,
49     };
50    
51     /* ======================================================================== */
52     /* Network Module Drivers */
53     /* ======================================================================== */
54     static struct c3725_nm_driver *nm_drivers[] = {
55     &dev_c3725_nm_1fe_tx_driver,
56     &dev_c3725_nm_16esw_driver,
57     &dev_c3725_gt96100_fe_driver,
58     &dev_c3725_nm_4t_driver,
59     NULL,
60     };
61    
62     /* ======================================================================== */
63     /* Cisco 3725 router instances */
64     /* ======================================================================== */
65    
66     /* Directly extract the configuration from the NVRAM device */
67     ssize_t c3725_nvram_extract_config(vm_instance_t *vm,char **buffer)
68     {
69     u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;
70     m_uint32_t start,nvlen;
71     m_uint16_t magic1,magic2;
72     struct vdevice *nvram_dev;
73     off_t nvram_size;
74     int fd;
75    
76     if ((nvram_dev = dev_get_by_name(vm,"rom")))
77     dev_sync(nvram_dev);
78    
79     fd = vm_mmap_open_file(vm,"rom",&base_ptr,&nvram_size);
80    
81     if (fd == -1)
82     return(-1);
83    
84     ios_ptr = base_ptr + C3725_NVRAM_OFFSET;
85     end_ptr = base_ptr + nvram_size;
86    
87     if ((ios_ptr + 0x30) >= end_ptr) {
88     vm_error(vm,"NVRAM file too small\n");
89     return(-1);
90     }
91    
92     magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06));
93     magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08));
94    
95     if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) {
96     vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n",
97     magic1,magic2);
98     return(-1);
99     }
100    
101     start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1;
102     nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18));
103    
104     if (!(*buffer = malloc(nvlen+1))) {
105     vm_error(vm,"unable to allocate config buffer (%u bytes)\n",nvlen);
106     return(-1);
107     }
108    
109     cfg_ptr = ios_ptr + start + 0x08;
110    
111     if ((cfg_ptr + nvlen) > end_ptr) {
112     vm_error(vm,"NVRAM file too small\n");
113     return(-1);
114     }
115    
116     memcpy(*buffer,cfg_ptr,nvlen-1);
117     (*buffer)[nvlen-1] = 0;
118     return(nvlen-1);
119     }
120    
121     static int c3725_nvram_push_config_part(vm_instance_t *vm,
122     char *buffer,size_t len,
123     u_char *ios_ptr)
124     {
125     m_uint32_t cfg_offset,cklen,tmp;
126     m_uint16_t cksum;
127     u_char *cfg_ptr;
128    
129     cfg_offset = 0x2c;
130     cfg_ptr = ios_ptr + cfg_offset;
131    
132     /* Write IOS tag, uncompressed config... */
133     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5);
134     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD);
135     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001);
136     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000);
137     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0c04);
138    
139     /* Store file contents to NVRAM */
140     memcpy(cfg_ptr,buffer,len);
141    
142     /* Write config addresses + size */
143     tmp = cfg_offset - 0x08;
144    
145     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(tmp);
146     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(tmp + len);
147     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len);
148    
149     /* Compute the checksum */
150     cklen = C3725_NVRAM_SIZE - 0x08;
151     cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen);
152     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum);
153     return(0);
154     }
155    
156     /* Directly push the IOS configuration to the NVRAM device */
157     int c3725_nvram_push_config(vm_instance_t *vm,char *buffer,size_t len)
158     {
159     u_char *base_ptr,*ios_ptr;
160     int fd;
161    
162     fd = vm_mmap_create_file(vm,"rom",vm->rom_size*1048576,&base_ptr);
163    
164     if (fd == -1)
165     return(-1);
166    
167     ios_ptr = base_ptr + C3725_NVRAM_OFFSET;
168    
169     /* Normal config */
170     c3725_nvram_push_config_part(vm,buffer,len,ios_ptr);
171    
172     /* Backup config */
173     c3725_nvram_push_config_part(vm,buffer,len,ios_ptr + C3725_NVRAM_SIZE);
174    
175     vm_mmap_close_file(fd,base_ptr,vm->rom_size*1048576);
176     return(0);
177     }
178    
179     /* Check for empty config */
180     int c3725_nvram_check_empty_config(vm_instance_t *vm)
181     {
182     struct vdevice *rom_dev;
183     m_uint64_t addr;
184     size_t len;
185    
186     if (!(rom_dev = dev_get_by_name(vm,"rom")))
187     return(-1);
188    
189     addr = rom_dev->phys_addr + C3725_NVRAM_OFFSET;
190     len = C3725_NVRAM_SIZE;
191    
192     while(len > 0) {
193     if (physmem_copy_u32_from_vm(vm,addr) != 0)
194     return(0);
195    
196     addr += sizeof(m_uint32_t);
197     len -= sizeof(m_uint32_t);
198     }
199    
200     /* Empty NVRAM */
201     vm->conf_reg |= 0x0040;
202     printf("NVRAM is empty, setting config register to 0x%x\n",vm->conf_reg);
203     return(0);
204     }
205    
206     /* Create a new router instance */
207     c3725_t *c3725_create_instance(char *name,int instance_id)
208     {
209     c3725_t *router;
210    
211     if (!(router = malloc(sizeof(*router)))) {
212     fprintf(stderr,"C3725 '%s': Unable to create new instance!\n",name);
213     return NULL;
214     }
215    
216     memset(router,0,sizeof(*router));
217    
218     if (!(router->vm = vm_create(name,instance_id,VM_TYPE_C3725))) {
219     fprintf(stderr,"C3725 '%s': unable to create VM instance!\n",name);
220     goto err_vm;
221     }
222    
223     c3725_init_defaults(router);
224     router->vm->hw_data = router;
225     return router;
226    
227     err_vm:
228     free(router);
229     return NULL;
230     }
231    
232     /* Free resources used by a router instance */
233     static int c3725_free_instance(void *data,void *arg)
234     {
235     vm_instance_t *vm = data;
236     c3725_t *router;
237     int i;
238    
239     if (vm->type == VM_TYPE_C3725) {
240     router = VM_C3725(vm);
241    
242     /* Stop all CPUs */
243     if (vm->cpu_group != NULL) {
244     vm_stop(vm);
245    
246     if (cpu_group_sync_state(vm->cpu_group) == -1) {
247     vm_error(vm,"unable to sync with system CPUs.\n");
248     return(FALSE);
249     }
250     }
251    
252     /* Remove NIO bindings */
253     for(i=0;i<C3725_MAX_NM_BAYS;i++)
254     c3725_nm_remove_all_nio_bindings(router,i);
255    
256     /* Shutdown all Network Modules */
257     c3725_nm_shutdown_all(router);
258    
259     /* Free mainboard EEPROM */
260     cisco_eeprom_free(&router->mb_eeprom);
261    
262     /* Free all resources used by VM */
263     vm_free(vm);
264    
265     /* Free the router structure */
266     free(router);
267     return(TRUE);
268     }
269    
270     return(FALSE);
271     }
272    
273     /* Delete a router instance */
274     int c3725_delete_instance(char *name)
275     {
276     return(registry_delete_if_unused(name,OBJ_TYPE_VM,
277     c3725_free_instance,NULL));
278     }
279    
280     /* Delete all router instances */
281     int c3725_delete_all_instances(void)
282     {
283     return(registry_delete_type(OBJ_TYPE_VM,c3725_free_instance,NULL));
284     }
285    
286     /* Save configuration of a C3725 instance */
287     void c3725_save_config(c3725_t *router,FILE *fd)
288     {
289     vm_instance_t *vm = router->vm;
290     struct c3725_nio_binding *nb;
291     struct c3725_nm_bay *bay;
292     int i;
293    
294     /* General settings */
295     fprintf(fd,"c3725 create %s %u\n",vm->name,vm->instance_id);
296    
297     /* VM configuration */
298     vm_save_config(vm,fd);
299    
300     /* Network Module settings */
301     for(i=0;i<C3725_MAX_NM_BAYS;i++) {
302     if (!(bay = c3725_nm_get_info(router,i)))
303     continue;
304    
305     if (bay->dev_type) {
306     fprintf(fd,"c3725 add_nm_binding %s %u %s\n",
307     vm->name,i,bay->dev_type);
308     }
309    
310     for(nb=bay->nio_list;nb;nb=nb->next) {
311     fprintf(fd,"c3725 add_nio_binding %s %u %u %s\n",
312     vm->name,i,nb->port_id,nb->nio->name);
313     }
314     }
315    
316     fprintf(fd,"\n");
317     }
318    
319     /* Save configurations of all C3725 instances */
320     static void c3725_reg_save_config(registry_entry_t *entry,void *opt,int *err)
321     {
322     vm_instance_t *vm = entry->data;
323     c3725_t *router = VM_C3725(vm);
324    
325     if (vm->type == VM_TYPE_C3725)
326     c3725_save_config(router,(FILE *)opt);
327     }
328    
329     void c3725_save_config_all(FILE *fd)
330     {
331     registry_foreach_type(OBJ_TYPE_VM,c3725_reg_save_config,fd,NULL);
332     }
333    
334 dpavlin 8 /* Get slot/port corresponding to specified network IRQ */
335     static inline void
336     c3725_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port)
337     {
338     irq -= C3725_NETIO_IRQ_BASE;
339     *port = irq & C3725_NETIO_IRQ_PORT_MASK;
340     *slot = irq >> C3725_NETIO_IRQ_PORT_BITS;
341     }
342    
343     /* Get network IRQ for specified slot/port */
344     u_int c3725_net_irq_for_slot_port(u_int slot,u_int port)
345     {
346     u_int irq;
347    
348     irq = (slot << C3725_NETIO_IRQ_PORT_BITS) + port;
349     irq += C3725_NETIO_IRQ_BASE;
350    
351     return(irq);
352     }
353    
354 dpavlin 4 /* Get PCI device for the specified NM bay */
355     int c3725_nm_get_pci_device(u_int nm_bay)
356     {
357     switch(nm_bay) {
358     case 1:
359     return(0x06);
360     case 2:
361     return(0x0A);
362     default:
363     return(-1);
364     }
365     }
366    
367     /* Set NM EEPROM definition */
368     int c3725_nm_set_eeprom(c3725_t *router,u_int nm_bay,
369     const struct cisco_eeprom *eeprom)
370     {
371     if (!nm_bay || (nm_bay >= C3725_MAX_NM_BAYS)) {
372     vm_error(router->vm,"c3725_nm_set_eeprom: invalid NM Bay %u.\n",nm_bay);
373     return(-1);
374     }
375    
376     if (cisco_eeprom_copy(&router->nm_bay[nm_bay].eeprom,eeprom) == -1) {
377     vm_error(router->vm,"c3725_nm_set_eeprom: no memory.\n");
378     return(-1);
379     }
380    
381     return(0);
382     }
383    
384     /* Unset NM EEPROM definition (empty bay) */
385     int c3725_nm_unset_eeprom(c3725_t *router,u_int nm_bay)
386     {
387     if (!nm_bay || (nm_bay >= C3725_MAX_NM_BAYS)) {
388     vm_error(router->vm,"c3725_nm_set_eeprom: invalid NM Bay %u.\n",nm_bay);
389     return(-1);
390     }
391    
392     cisco_eeprom_free(&router->nm_bay[nm_bay].eeprom);
393     return(0);
394     }
395    
396     /* Check if a bay has a port adapter */
397     int c3725_nm_check_eeprom(c3725_t *router,u_int nm_bay)
398     {
399     if (!nm_bay || (nm_bay >= C3725_MAX_NM_BAYS))
400     return(FALSE);
401    
402     return(cisco_eeprom_valid(&router->nm_bay[nm_bay].eeprom));
403     }
404    
405     /* Get bay info */
406     struct c3725_nm_bay *c3725_nm_get_info(c3725_t *router,u_int nm_bay)
407     {
408     if (nm_bay >= C3725_MAX_NM_BAYS)
409     return NULL;
410    
411     return(&router->nm_bay[nm_bay]);
412     }
413    
414     /* Get NM type */
415     char *c3725_nm_get_type(c3725_t *router,u_int nm_bay)
416     {
417     struct c3725_nm_bay *bay;
418    
419     bay = c3725_nm_get_info(router,nm_bay);
420     return((bay != NULL) ? bay->dev_type : NULL);
421     }
422    
423     /* Get driver info about the specified slot */
424     void *c3725_nm_get_drvinfo(c3725_t *router,u_int nm_bay)
425     {
426     struct c3725_nm_bay *bay;
427    
428     bay = c3725_nm_get_info(router,nm_bay);
429     return((bay != NULL) ? bay->drv_info : NULL);
430     }
431    
432     /* Set driver info for the specified slot */
433     int c3725_nm_set_drvinfo(c3725_t *router,u_int nm_bay,void *drv_info)
434     {
435     struct c3725_nm_bay *bay;
436    
437     if (!(bay = c3725_nm_get_info(router,nm_bay)))
438     return(-1);
439    
440     bay->drv_info = drv_info;
441     return(0);
442     }
443    
444     /* Get a NM driver */
445     static struct c3725_nm_driver *c3725_nm_get_driver(char *dev_type)
446     {
447     int i;
448    
449     for(i=0;nm_drivers[i];i++)
450     if (!strcmp(nm_drivers[i]->dev_type,dev_type))
451     return nm_drivers[i];
452    
453     return NULL;
454     }
455    
456     /* Add a NM binding */
457     int c3725_nm_add_binding(c3725_t *router,char *dev_type,u_int nm_bay)
458     {
459     struct c3725_nm_driver *nm_driver;
460     struct c3725_nm_bay *bay;
461    
462     if (!(bay = c3725_nm_get_info(router,nm_bay)))
463     return(-1);
464    
465     /* check that this bay is empty */
466     if (bay->dev_type != NULL) {
467     vm_error(router->vm,"a NM already exists in slot %u.\n",nm_bay);
468     return(-1);
469     }
470    
471     /* find the NM driver */
472     if (!(nm_driver = c3725_nm_get_driver(dev_type))) {
473     vm_error(router->vm,"unknown NM type '%s'.\n",dev_type);
474     return(-1);
475     }
476    
477     bay->dev_type = nm_driver->dev_type;
478     bay->nm_driver = nm_driver;
479     return(0);
480     }
481    
482     /* Remove a NM binding */
483     int c3725_nm_remove_binding(c3725_t *router,u_int nm_bay)
484     {
485     struct c3725_nm_bay *bay;
486    
487     if (!(bay = c3725_nm_get_info(router,nm_bay)))
488     return(-1);
489    
490     /* stop if this bay is still active */
491     if (bay->drv_info != NULL) {
492     vm_error(router->vm,"slot %u still active.\n",nm_bay);
493     return(-1);
494     }
495    
496     /* check that this bay is not empty */
497     if (bay->dev_type == NULL) {
498     vm_error(router->vm,"slot %u is empty.\n",nm_bay);
499     return(-1);
500     }
501    
502     /* remove all NIOs bindings */
503     c3725_nm_remove_all_nio_bindings(router,nm_bay);
504    
505     bay->dev_type = NULL;
506     bay->nm_driver = NULL;
507     return(0);
508     }
509    
510     /* Find a NIO binding */
511     struct c3725_nio_binding *
512     c3725_nm_find_nio_binding(c3725_t *router,u_int nm_bay,u_int port_id)
513     {
514     struct c3725_nio_binding *nb;
515     struct c3725_nm_bay *bay;
516    
517     if (!(bay = c3725_nm_get_info(router,nm_bay)))
518     return NULL;
519    
520     for(nb=bay->nio_list;nb;nb=nb->next)
521     if (nb->port_id == port_id)
522     return nb;
523    
524     return NULL;
525     }
526    
527     /* Add a network IO binding */
528     int c3725_nm_add_nio_binding(c3725_t *router,u_int nm_bay,u_int port_id,
529     char *nio_name)
530     {
531     struct c3725_nio_binding *nb;
532     struct c3725_nm_bay *bay;
533     netio_desc_t *nio;
534    
535     if (!(bay = c3725_nm_get_info(router,nm_bay)))
536     return(-1);
537    
538     /* check that a NIO is not already bound to this port */
539     if (c3725_nm_find_nio_binding(router,nm_bay,port_id) != NULL) {
540     vm_error(router->vm,"a NIO already exists for interface %u/%u.\n",
541     nm_bay,port_id);
542     return(-1);
543     }
544    
545     /* acquire a reference on the NIO object */
546     if (!(nio = netio_acquire(nio_name))) {
547     vm_error(router->vm,"unable to find NIO '%s'.\n",nio_name);
548     return(-1);
549     }
550    
551     /* create a new binding */
552     if (!(nb = malloc(sizeof(*nb)))) {
553     vm_error(router->vm,"unable to create NIO binding "
554     "for interface %u/%u.\n",nm_bay,port_id);
555     netio_release(nio_name);
556     return(-1);
557     }
558    
559     memset(nb,0,sizeof(*nb));
560     nb->nio = nio;
561     nb->port_id = port_id;
562     nb->next = bay->nio_list;
563     if (nb->next) nb->next->prev = nb;
564     bay->nio_list = nb;
565     return(0);
566     }
567    
568     /* Remove a NIO binding */
569     int c3725_nm_remove_nio_binding(c3725_t *router,u_int nm_bay,u_int port_id)
570     {
571     struct c3725_nio_binding *nb;
572     struct c3725_nm_bay *bay;
573    
574     if (!(bay = c3725_nm_get_info(router,nm_bay)))
575     return(-1);
576    
577     if (!(nb = c3725_nm_find_nio_binding(router,nm_bay,port_id)))
578     return(-1); /* no nio binding for this slot/port */
579    
580     /* tell the NM driver to stop using this NIO */
581     if (bay->nm_driver)
582     bay->nm_driver->nm_unset_nio(router,nm_bay,port_id);
583    
584     /* remove this entry from the double linked list */
585     if (nb->next)
586     nb->next->prev = nb->prev;
587    
588     if (nb->prev) {
589     nb->prev->next = nb->next;
590     } else {
591     bay->nio_list = nb->next;
592     }
593    
594     /* unreference NIO object */
595     netio_release(nb->nio->name);
596     free(nb);
597     return(0);
598     }
599    
600     /* Remove all NIO bindings for the specified NM */
601     int c3725_nm_remove_all_nio_bindings(c3725_t *router,u_int nm_bay)
602     {
603     struct c3725_nio_binding *nb,*next;
604     struct c3725_nm_bay *bay;
605    
606     if (!(bay = c3725_nm_get_info(router,nm_bay)))
607     return(-1);
608    
609     for(nb=bay->nio_list;nb;nb=next) {
610     next = nb->next;
611    
612     /* tell the NM driver to stop using this NIO */
613     if (bay->nm_driver)
614     bay->nm_driver->nm_unset_nio(router,nm_bay,nb->port_id);
615    
616     /* unreference NIO object */
617     netio_release(nb->nio->name);
618     free(nb);
619     }
620    
621     bay->nio_list = NULL;
622     return(0);
623     }
624    
625     /* Enable a Network IO descriptor for a Network Module */
626     int c3725_nm_enable_nio(c3725_t *router,u_int nm_bay,u_int port_id)
627     {
628     struct c3725_nio_binding *nb;
629     struct c3725_nm_bay *bay;
630    
631     if (!(bay = c3725_nm_get_info(router,nm_bay)))
632     return(-1);
633    
634     /* check that we have an NIO binding for this interface */
635     if (!(nb = c3725_nm_find_nio_binding(router,nm_bay,port_id)))
636     return(-1);
637    
638     /* check that the driver is defined and successfully initialized */
639     if (!bay->nm_driver || !bay->drv_info)
640     return(-1);
641    
642     return(bay->nm_driver->nm_set_nio(router,nm_bay,port_id,nb->nio));
643     }
644    
645     /* Disable Network IO descriptor of a Network Module */
646     int c3725_nm_disable_nio(c3725_t *router,u_int nm_bay,u_int port_id)
647     {
648     struct c3725_nm_bay *bay;
649    
650     if (!(bay = c3725_nm_get_info(router,nm_bay)))
651     return(-1);
652    
653     /* check that the driver is defined and successfully initialized */
654     if (!bay->nm_driver || !bay->drv_info)
655     return(-1);
656    
657     return(bay->nm_driver->nm_unset_nio(router,nm_bay,port_id));
658     }
659    
660     /* Enable all NIO of the specified NM */
661     int c3725_nm_enable_all_nio(c3725_t *router,u_int nm_bay)
662     {
663     struct c3725_nio_binding *nb;
664     struct c3725_nm_bay *bay;
665    
666     if (!(bay = c3725_nm_get_info(router,nm_bay)))
667     return(-1);
668    
669     /* check that the driver is defined and successfully initialized */
670     if (!bay->nm_driver || !bay->drv_info)
671     return(-1);
672    
673     for(nb=bay->nio_list;nb;nb=nb->next)
674     bay->nm_driver->nm_set_nio(router,nm_bay,nb->port_id,nb->nio);
675    
676     return(0);
677     }
678    
679     /* Disable all NIO of the specified NM */
680     int c3725_nm_disable_all_nio(c3725_t *router,u_int nm_bay)
681     {
682     struct c3725_nio_binding *nb;
683     struct c3725_nm_bay *bay;
684    
685     if (!(bay = c3725_nm_get_info(router,nm_bay)))
686     return(-1);
687    
688     /* check that the driver is defined and successfully initialized */
689     if (!bay->nm_driver || !bay->drv_info)
690     return(-1);
691    
692     for(nb=bay->nio_list;nb;nb=nb->next)
693     bay->nm_driver->nm_unset_nio(router,nm_bay,nb->port_id);
694    
695     return(0);
696     }
697    
698     /* Initialize a Network Module */
699     int c3725_nm_init(c3725_t *router,u_int nm_bay)
700     {
701     struct c3725_nm_bay *bay;
702     size_t len;
703    
704     if (!(bay = c3725_nm_get_info(router,nm_bay)))
705     return(-1);
706    
707     /* Check that a device type is defined for this bay */
708     if (!bay->dev_type || !bay->nm_driver) {
709     vm_error(router->vm,"trying to init empty slot %u.\n",nm_bay);
710     return(-1);
711     }
712    
713     /* Allocate device name */
714     len = strlen(bay->dev_type) + 10;
715     if (!(bay->dev_name = malloc(len))) {
716     vm_error(router->vm,"unable to allocate device name.\n");
717     return(-1);
718     }
719    
720     snprintf(bay->dev_name,len,"%s(%u)",bay->dev_type,nm_bay);
721    
722     /* Initialize NM driver */
723 dpavlin 8 if (bay->nm_driver->nm_init(router,bay->dev_name,nm_bay) == -1) {
724 dpavlin 4 vm_error(router->vm,"unable to initialize NM %u.\n",nm_bay);
725     return(-1);
726     }
727    
728     /* Enable all NIO */
729     c3725_nm_enable_all_nio(router,nm_bay);
730     return(0);
731     }
732    
733     /* Shutdown a Network Module */
734     int c3725_nm_shutdown(c3725_t *router,u_int nm_bay)
735     {
736     struct c3725_nm_bay *bay;
737    
738     if (!(bay = c3725_nm_get_info(router,nm_bay)))
739     return(-1);
740    
741     /* Check that a device type is defined for this bay */
742     if (!bay->dev_type || !bay->nm_driver) {
743     vm_error(router->vm,"trying to shut down empty slot %u.\n",nm_bay);
744     return(-1);
745     }
746    
747     /* Disable all NIO */
748     c3725_nm_disable_all_nio(router,nm_bay);
749    
750     /* Shutdown the NM driver */
751     if (bay->drv_info && (bay->nm_driver->nm_shutdown(router,nm_bay) == -1)) {
752     vm_error(router->vm,"unable to shutdown NM %u.\n",nm_bay);
753     return(-1);
754     }
755    
756     free(bay->dev_name);
757     bay->dev_name = NULL;
758     bay->drv_info = NULL;
759     return(0);
760     }
761    
762     /* Shutdown all NM of a router */
763     int c3725_nm_shutdown_all(c3725_t *router)
764     {
765     int i;
766    
767     for(i=0;i<C3725_MAX_NM_BAYS;i++) {
768     if (!router->nm_bay[i].dev_type)
769     continue;
770    
771     c3725_nm_shutdown(router,i);
772     }
773    
774     return(0);
775     }
776    
777     /* Show info about all NMs */
778     int c3725_nm_show_all_info(c3725_t *router)
779     {
780     struct c3725_nm_bay *bay;
781     int i;
782    
783     for(i=0;i<C3725_MAX_NM_BAYS;i++) {
784     if (!(bay = c3725_nm_get_info(router,i)) || !bay->nm_driver)
785     continue;
786    
787     if (bay->nm_driver->nm_show_info != NULL)
788     bay->nm_driver->nm_show_info(router,i);
789     }
790    
791     return(0);
792     }
793    
794     /* Maximum number of tokens in a NM description */
795     #define NM_DESC_MAX_TOKENS 8
796    
797     /* Create a Network Module (command line) */
798     int c3725_cmd_nm_create(c3725_t *router,char *str)
799     {
800     char *tokens[NM_DESC_MAX_TOKENS];
801     int i,count,res;
802     u_int nm_bay;
803    
804     /* A port adapter description is like "1:NM-1FE" */
805     if ((count = m_strsplit(str,':',tokens,NM_DESC_MAX_TOKENS)) != 2) {
806     vm_error(router->vm,"unable to parse NM description '%s'.\n",str);
807     return(-1);
808     }
809    
810     /* Parse the NM bay id */
811     nm_bay = atoi(tokens[0]);
812    
813     /* Add this new NM to the current NM list */
814     res = c3725_nm_add_binding(router,tokens[1],nm_bay);
815    
816     /* The complete array was cleaned by strsplit */
817     for(i=0;i<NM_DESC_MAX_TOKENS;i++)
818     free(tokens[i]);
819    
820     return(res);
821     }
822    
823     /* Add a Network IO descriptor binding (command line) */
824     int c3725_cmd_add_nio(c3725_t *router,char *str)
825     {
826     char *tokens[NM_DESC_MAX_TOKENS];
827     int i,count,nio_type,res=-1;
828     u_int nm_bay,port_id;
829     netio_desc_t *nio;
830     char nio_name[128];
831    
832     /* A port adapter description is like "1:3:tap:tap0" */
833     if ((count = m_strsplit(str,':',tokens,NM_DESC_MAX_TOKENS)) < 3) {
834     vm_error(router->vm,"unable to parse NIO description '%s'.\n",str);
835     return(-1);
836     }
837    
838     /* Parse the NM bay */
839     nm_bay = atoi(tokens[0]);
840    
841     /* Parse the NM port id */
842     port_id = atoi(tokens[1]);
843    
844     /* Autogenerate a NIO name */
845     snprintf(nio_name,sizeof(nio_name),"c3725-i%u/%u/%u",
846     router->vm->instance_id,nm_bay,port_id);
847    
848     /* Create the Network IO descriptor */
849     nio = NULL;
850     nio_type = netio_get_type(tokens[2]);
851    
852     switch(nio_type) {
853     case NETIO_TYPE_UNIX:
854     if (count != 5) {
855     vm_error(router->vm,
856     "invalid number of arguments for UNIX NIO '%s'\n",str);
857     goto done;
858     }
859    
860     nio = netio_desc_create_unix(nio_name,tokens[3],tokens[4]);
861     break;
862    
863     case NETIO_TYPE_VDE:
864     if (count != 5) {
865     vm_error(router->vm,
866     "invalid number of arguments for VDE NIO '%s'\n",str);
867     goto done;
868     }
869    
870     nio = netio_desc_create_vde(nio_name,tokens[3],tokens[4]);
871     break;
872    
873     case NETIO_TYPE_TAP:
874     if (count != 4) {
875     vm_error(router->vm,
876     "invalid number of arguments for TAP NIO '%s'\n",str);
877     goto done;
878     }
879    
880     nio = netio_desc_create_tap(nio_name,tokens[3]);
881     break;
882    
883     case NETIO_TYPE_UDP:
884     if (count != 6) {
885     vm_error(router->vm,
886     "invalid number of arguments for UDP NIO '%s'\n",str);
887     goto done;
888     }
889    
890     nio = netio_desc_create_udp(nio_name,atoi(tokens[3]),
891     tokens[4],atoi(tokens[5]));
892     break;
893    
894     case NETIO_TYPE_TCP_CLI:
895     if (count != 5) {
896     vm_error(router->vm,
897     "invalid number of arguments for TCP CLI NIO '%s'\n",str);
898     goto done;
899     }
900    
901     nio = netio_desc_create_tcp_cli(nio_name,tokens[3],tokens[4]);
902     break;
903    
904     case NETIO_TYPE_TCP_SER:
905     if (count != 4) {
906     vm_error(router->vm,
907     "invalid number of arguments for TCP SER NIO '%s'\n",str);
908     goto done;
909     }
910    
911     nio = netio_desc_create_tcp_ser(nio_name,tokens[3]);
912     break;
913    
914     case NETIO_TYPE_NULL:
915     nio = netio_desc_create_null(nio_name);
916     break;
917    
918     #ifdef LINUX_ETH
919     case NETIO_TYPE_LINUX_ETH:
920     if (count != 4) {
921     vm_error(router->vm,
922     "invalid number of arguments for Linux Eth NIO '%s'\n",
923     str);
924     goto done;
925     }
926    
927     nio = netio_desc_create_lnxeth(nio_name,tokens[3]);
928     break;
929     #endif
930    
931     #ifdef GEN_ETH
932     case NETIO_TYPE_GEN_ETH:
933     if (count != 4) {
934     vm_error(router->vm,
935     "invalid number of arguments for Generic Eth NIO '%s'\n",
936     str);
937     goto done;
938     }
939    
940     nio = netio_desc_create_geneth(nio_name,tokens[3]);
941     break;
942     #endif
943    
944     default:
945     vm_error(router->vm,"unknown NETIO type '%s'\n",tokens[2]);
946     goto done;
947     }
948    
949     if (!nio) {
950     vm_error(router->vm,"unable to create NETIO "
951     "descriptor for NM slot %u\n",nm_bay);
952     goto done;
953     }
954    
955     if (c3725_nm_add_nio_binding(router,nm_bay,port_id,nio_name) == -1) {
956     vm_error(router->vm,"unable to add NETIO binding for slot %u\n",nm_bay);
957     netio_release(nio_name);
958     netio_delete(nio_name);
959     goto done;
960     }
961    
962     netio_release(nio_name);
963     res = 0;
964    
965     done:
966     /* The complete array was cleaned by strsplit */
967     for(i=0;i<NM_DESC_MAX_TOKENS;i++)
968     free(tokens[i]);
969    
970     return(res);
971     }
972    
973     /* Show the list of available NM drivers */
974     void c3725_nm_show_drivers(void)
975     {
976     int i;
977    
978     printf("Available C3725 Network Module drivers:\n");
979    
980     for(i=0;nm_drivers[i];i++) {
981     printf(" * %s %s\n",
982     nm_drivers[i]->dev_type,
983     !nm_drivers[i]->supported ? "(NOT WORKING)" : "");
984     }
985    
986     printf("\n");
987     }
988    
989     /* Set the base MAC address of the chassis */
990     static int c3725_burn_mac_addr(c3725_t *router,n_eth_addr_t *addr)
991     {
992     m_uint8_t eeprom_ver;
993     size_t offset;
994    
995     /* Read EEPROM format version */
996     cisco_eeprom_get_byte(&router->mb_eeprom,0,&eeprom_ver);
997    
998     switch(eeprom_ver) {
999     case 0:
1000     cisco_eeprom_set_region(&router->mb_eeprom,2,addr->eth_addr_byte,6);
1001     break;
1002    
1003     case 4:
1004     if (!cisco_eeprom_v4_find_field(&router->mb_eeprom,0xC3,&offset)) {
1005     cisco_eeprom_set_region(&router->mb_eeprom,offset,
1006     addr->eth_addr_byte,6);
1007     }
1008     break;
1009    
1010     default:
1011     vm_error(router->vm,"c3725_burn_mac_addr: unable to handle "
1012     "EEPROM version %u\n",eeprom_ver);
1013     return(-1);
1014     }
1015    
1016     return(0);
1017     }
1018    
1019     /* Set chassis MAC address */
1020     int c3725_chassis_set_mac_addr(c3725_t *router,char *mac_addr)
1021     {
1022     if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) {
1023     vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr);
1024     return(-1);
1025     }
1026    
1027     /* Set the chassis base MAC address */
1028     c3725_burn_mac_addr(router,&router->mac_addr);
1029     return(0);
1030     }
1031    
1032     /* Create the two main PCI busses for a GT64120 based system */
1033     static int c3725_init_gt96100(c3725_t *router)
1034     {
1035     vm_instance_t *vm = router->vm;
1036    
1037     vm->pci_bus[0] = pci_bus_create("PCI bus #0",0);
1038     vm->pci_bus[1] = pci_bus_create("PCI bus #1",0);
1039    
1040     if (!vm->pci_bus[0] || !vm->pci_bus[1]) {
1041     vm_error(router->vm,"unable to create PCI data.\n");
1042     return(-1);
1043     }
1044    
1045     return(dev_gt96100_init(vm,"gt96100",C3725_GT96K_ADDR,0x200000,
1046 dpavlin 8 C3725_GT96K_IRQ,c3725_net_irq_for_slot_port(0,0)));
1047 dpavlin 4 }
1048    
1049     /* Initialize a Cisco 3725 */
1050     static int c3725_init(c3725_t *router)
1051     {
1052     vm_instance_t *vm = router->vm;
1053    
1054     /* Set the processor type: R7000 */
1055 dpavlin 7 mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R7000);
1056 dpavlin 4
1057     /* Initialize the Galileo GT-96100 PCI controller */
1058     if (c3725_init_gt96100(router) == -1)
1059     return(-1);
1060    
1061     /* Initialize PCI map (NM slot 1 & 2) */
1062     router->nm_bay[1].pci_map = vm->pci_bus[1];
1063     router->nm_bay[2].pci_map = vm->pci_bus[1];
1064    
1065     vm->elf_machine_id = C3725_ELF_MACHINE_ID;
1066     return(0);
1067     }
1068    
1069     /* Show C3725 hardware info */
1070     void c3725_show_hardware(c3725_t *router)
1071     {
1072     vm_instance_t *vm = router->vm;
1073    
1074     printf("C3725 instance '%s' (id %d):\n",vm->name,vm->instance_id);
1075    
1076     printf(" VM Status : %d\n",vm->status);
1077     printf(" RAM size : %u Mb\n",vm->ram_size);
1078     printf(" NVRAM size : %u Kb\n",vm->nvram_size);
1079     printf(" IOS image : %s\n\n",vm->ios_image);
1080    
1081     if (vm->debug_level > 0) {
1082     dev_show_list(vm);
1083     pci_dev_show_list(vm->pci_bus[0]);
1084     pci_dev_show_list(vm->pci_bus[1]);
1085     printf("\n");
1086     }
1087     }
1088    
1089     /* Initialize default parameters for a C3725 */
1090     void c3725_init_defaults(c3725_t *router)
1091     {
1092     vm_instance_t *vm = router->vm;
1093     n_eth_addr_t *m;
1094     m_uint16_t pid;
1095    
1096     pid = (m_uint16_t)getpid();
1097    
1098     /* Generate a chassis MAC address based on the instance ID */
1099     m = &router->mac_addr;
1100     m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
1101     m->eth_addr_byte[1] = vm->instance_id & 0xFF;
1102     m->eth_addr_byte[2] = pid >> 8;
1103     m->eth_addr_byte[3] = pid & 0xFF;
1104     m->eth_addr_byte[4] = 0x00;
1105     m->eth_addr_byte[5] = 0x00;
1106    
1107     c3725_init_eeprom_groups(router);
1108     cisco_eeprom_copy(&router->mb_eeprom,&eeprom_c3725_mainboard);
1109     c3725_burn_mac_addr(router,&router->mac_addr);
1110    
1111     vm->ram_mmap = C3725_DEFAULT_RAM_MMAP;
1112     vm->ram_size = C3725_DEFAULT_RAM_SIZE;
1113     vm->rom_size = C3725_DEFAULT_ROM_SIZE;
1114     vm->nvram_size = C3725_DEFAULT_NVRAM_SIZE;
1115     vm->conf_reg_setup = C3725_DEFAULT_CONF_REG;
1116     vm->clock_divisor = C3725_DEFAULT_CLOCK_DIV;
1117     vm->nvram_rom_space = C3725_NVRAM_ROM_RES_SIZE;
1118     router->nm_iomem_size = C3725_DEFAULT_IOMEM_SIZE;
1119    
1120     vm->pcmcia_disk_size[0] = C3725_DEFAULT_DISK0_SIZE;
1121     vm->pcmcia_disk_size[1] = C3725_DEFAULT_DISK1_SIZE;
1122    
1123     /* Enable NVRAM operations to load/store configs */
1124     vm->nvram_extract_config = c3725_nvram_extract_config;
1125     vm->nvram_push_config = c3725_nvram_push_config;
1126     }
1127    
1128     /* Initialize the C3725 Platform */
1129     int c3725_init_platform(c3725_t *router)
1130     {
1131     vm_instance_t *vm = router->vm;
1132     struct c3725_nm_bay *nm_bay;
1133     cpu_mips_t *cpu;
1134 dpavlin 7 cpu_gen_t *gen;
1135 dpavlin 4 vm_obj_t *obj;
1136     int i;
1137    
1138     /* Copy config register setup into "active" config register */
1139     vm->conf_reg = vm->conf_reg_setup;
1140    
1141     /* Create Console and AUX ports */
1142     vm_init_vtty(vm);
1143    
1144     /* Create a CPU group */
1145     vm->cpu_group = cpu_group_create("System CPU");
1146    
1147     /* Initialize the virtual MIPS processor */
1148 dpavlin 7 if (!(gen = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
1149 dpavlin 4 vm_error(vm,"unable to create CPU!\n");
1150     return(-1);
1151     }
1152    
1153 dpavlin 7 cpu = CPU_MIPS64(gen);
1154    
1155 dpavlin 4 /* Add this CPU to the system CPU group */
1156 dpavlin 7 cpu_group_add(vm->cpu_group,gen);
1157     vm->boot_cpu = gen;
1158 dpavlin 4
1159 dpavlin 7 /* Initialize the IRQ routing vectors */
1160     vm->set_irq = mips64_vm_set_irq;
1161     vm->clear_irq = mips64_vm_clear_irq;
1162    
1163 dpavlin 4 /* Mark the Network IO interrupt as high priority */
1164     cpu->irq_idle_preempt[C3725_NETIO_IRQ] = TRUE;
1165     cpu->irq_idle_preempt[C3725_GT96K_IRQ] = TRUE;
1166     cpu->irq_idle_preempt[C3725_DUART_IRQ] = TRUE;
1167    
1168     /* Copy some parameters from VM to CPU (idle PC, ...) */
1169     cpu->idle_pc = vm->idle_pc;
1170    
1171     if (vm->timer_irq_check_itv)
1172     cpu->timer_irq_check_itv = vm->timer_irq_check_itv;
1173    
1174     /* Remote emulator control */
1175     dev_remote_control_init(vm,0x16000000,0x1000);
1176    
1177     /* Specific Storage Area (SSA) */
1178 dpavlin 7 dev_ram_init(vm,"ssa",TRUE,FALSE,NULL,FALSE,0x16001000ULL,0x7000);
1179 dpavlin 4
1180     /* IO FPGA */
1181     if (dev_c3725_iofpga_init(router,C3725_IOFPGA_ADDR,0x40000) == -1)
1182     return(-1);
1183    
1184 dpavlin 8 if (!(obj = vm_object_find(router->vm,"io_fpga")))
1185     return(-1);
1186    
1187     router->iofpga_data = obj->data;
1188    
1189 dpavlin 4 #if 0
1190     /* PCI IO space */
1191     if (!(vm->pci_io_space = pci_io_data_init(vm,C3725_PCI_IO_ADDR)))
1192     return(-1);
1193     #endif
1194    
1195     /* Initialize the chassis */
1196     if (c3725_init(router) == -1)
1197     return(-1);
1198    
1199     /* Initialize RAM */
1200     vm_ram_init(vm,0x00000000ULL);
1201    
1202     /* Initialize ROM (as a Flash) */
1203     if (!(obj = dev_flash_init(vm,"rom",C3725_ROM_ADDR,vm->rom_size*1048576)))
1204     return(-1);
1205    
1206 dpavlin 7 dev_flash_copy_data(obj,0,mips64_microcode,mips64_microcode_len);
1207 dpavlin 4 c3725_nvram_check_empty_config(vm);
1208    
1209     /* Initialize the NS16552 DUART */
1210     dev_ns16552_init(vm,C3725_DUART_ADDR,0x1000,3,C3725_DUART_IRQ,
1211     vm->vtty_con,vm->vtty_aux);
1212    
1213     /* PCMCIA Slot 0 */
1214     dev_pcmcia_disk_init(vm,"slot0",C3725_SLOT0_ADDR,0x200000,
1215     vm->pcmcia_disk_size[0],1);
1216    
1217     /* PCMCIA Slot 1 */
1218     dev_pcmcia_disk_init(vm,"slot1",C3725_SLOT1_ADDR,0x200000,
1219     vm->pcmcia_disk_size[1],1);
1220    
1221     /* The GT96100 system controller has 2 integrated FastEthernet ports */
1222     c3725_nm_add_binding(router,"GT96100-FE",0);
1223    
1224     /* Initialize Network Modules */
1225     for(i=0;i<C3725_MAX_NM_BAYS;i++) {
1226     nm_bay = &router->nm_bay[i];
1227    
1228     if (!nm_bay->dev_type)
1229     continue;
1230    
1231     if (c3725_nm_init(router,i) == -1) {
1232     vm_error(vm,"unable to create Network Module \"%s\"\n",
1233     nm_bay->dev_type);
1234     return(-1);
1235     }
1236     }
1237    
1238     /* Show device list */
1239     c3725_show_hardware(router);
1240     return(0);
1241     }
1242    
1243     /* Boot the IOS image */
1244     int c3725_boot_ios(c3725_t *router)
1245     {
1246     vm_instance_t *vm = router->vm;
1247 dpavlin 7 cpu_mips_t *cpu;
1248 dpavlin 4
1249     if (!vm->boot_cpu)
1250     return(-1);
1251    
1252     /* Suspend CPU activity since we will restart directly from ROM */
1253     vm_suspend(vm);
1254    
1255     /* Check that CPU activity is really suspended */
1256     if (cpu_group_sync_state(vm->cpu_group) == -1) {
1257     vm_error(vm,"unable to sync with system CPUs.\n");
1258     return(-1);
1259     }
1260    
1261     /* Reset the boot CPU */
1262 dpavlin 7 cpu = CPU_MIPS64(vm->boot_cpu);
1263     mips64_reset(cpu);
1264 dpavlin 4
1265     /* Load IOS image */
1266 dpavlin 7 if (mips64_load_elf_image(cpu,vm->ios_image,
1267 dpavlin 4 (vm->ghost_status == VM_GHOST_RAM_USE),
1268     &vm->ios_entry_point) < 0)
1269     {
1270     vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
1271     return(-1);
1272     }
1273    
1274     /* Launch the simulation */
1275     printf("\nC3725 '%s': starting simulation (CPU0 PC=0x%llx), "
1276     "JIT %sabled.\n",
1277 dpavlin 7 vm->name,cpu->pc,vm->jit_use ? "en":"dis");
1278 dpavlin 4
1279     vm_log(vm,"C3725_BOOT",
1280     "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
1281 dpavlin 7 cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
1282 dpavlin 4
1283     /* Start main CPU */
1284     if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
1285     vm->status = VM_STATUS_RUNNING;
1286     cpu_start(vm->boot_cpu);
1287     } else {
1288     vm->status = VM_STATUS_SHUTDOWN;
1289     }
1290     return(0);
1291     }
1292    
1293 dpavlin 8 /* Set an IRQ */
1294     static void c3725_set_irq(vm_instance_t *vm,u_int irq)
1295     {
1296     c3725_t *router = VM_C3725(vm);
1297     cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
1298     u_int slot,port;
1299    
1300     switch(irq) {
1301     case 0 ... 7:
1302     mips64_set_irq(cpu0,irq);
1303    
1304     if (cpu0->irq_idle_preempt[irq])
1305     cpu_idle_break_wait(cpu0->gen);
1306     break;
1307    
1308     case C3725_NETIO_IRQ_BASE ... C3725_NETIO_IRQ_END:
1309     c3725_net_irq_get_slot_port(irq,&slot,&port);
1310     dev_c3725_iofpga_net_set_irq(router->iofpga_data,slot,port);
1311     break;
1312     }
1313     }
1314    
1315     /* Clear an IRQ */
1316     static void c3725_clear_irq(vm_instance_t *vm,u_int irq)
1317     {
1318     c3725_t *router = VM_C3725(vm);
1319     cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
1320     u_int slot,port;
1321    
1322     switch(irq) {
1323     case 0 ... 7:
1324     mips64_clear_irq(cpu0,irq);
1325     break;
1326    
1327     case C3725_NETIO_IRQ_BASE ... C3725_NETIO_IRQ_END:
1328     c3725_net_irq_get_slot_port(irq,&slot,&port);
1329     dev_c3725_iofpga_net_clear_irq(router->iofpga_data,slot,port);
1330     break;
1331     }
1332     }
1333    
1334 dpavlin 4 /* Initialize a Cisco 3725 instance */
1335     int c3725_init_instance(c3725_t *router)
1336     {
1337     vm_instance_t *vm = router->vm;
1338     m_uint32_t rom_entry_point;
1339     cpu_mips_t *cpu0;
1340    
1341     if (!vm->ios_image) {
1342     vm_error(vm,"no Cisco IOS image defined.");
1343     return(-1);
1344     }
1345    
1346     /* Initialize the C3725 platform */
1347     if (c3725_init_platform(router) == -1) {
1348     vm_error(vm,"unable to initialize the platform hardware.\n");
1349     return(-1);
1350     }
1351    
1352 dpavlin 8 /* IRQ routing */
1353     vm->set_irq = c3725_set_irq;
1354     vm->clear_irq = c3725_clear_irq;
1355    
1356 dpavlin 4 /* Load IOS configuration file */
1357     if (vm->ios_config != NULL) {
1358     vm_nvram_push_config(vm,vm->ios_config);
1359     vm->conf_reg &= ~0x40;
1360     }
1361    
1362     /* Load ROM (ELF image or embedded) */
1363 dpavlin 7 cpu0 = CPU_MIPS64(vm->boot_cpu);
1364 dpavlin 4 rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
1365    
1366     if ((vm->rom_filename != NULL) &&
1367     (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
1368     {
1369     vm_error(vm,"unable to load alternate ROM '%s', "
1370     "fallback to embedded ROM.\n\n",vm->rom_filename);
1371     vm->rom_filename = NULL;
1372     }
1373    
1374     /* Load symbol file */
1375     if (vm->sym_filename) {
1376     mips64_sym_load_file(cpu0,vm->sym_filename);
1377     cpu0->sym_trace = 1;
1378     }
1379    
1380     return(c3725_boot_ios(router));
1381     }
1382    
1383     /* Stop a Cisco 3725 instance */
1384     int c3725_stop_instance(c3725_t *router)
1385     {
1386     vm_instance_t *vm = router->vm;
1387    
1388     printf("\nC3725 '%s': stopping simulation.\n",vm->name);
1389     vm_log(vm,"C3725_STOP","stopping simulation.\n");
1390    
1391     /* Stop all CPUs */
1392     if (vm->cpu_group != NULL) {
1393     vm_stop(vm);
1394    
1395     if (cpu_group_sync_state(vm->cpu_group) == -1) {
1396     vm_error(vm,"unable to sync with system CPUs.\n");
1397     return(-1);
1398     }
1399     }
1400    
1401     /* Free resources that were used during execution to emulate hardware */
1402     c3725_nm_shutdown_all(router);
1403     vm_hardware_shutdown(vm);
1404     return(0);
1405     }

  ViewVC Help
Powered by ViewVC 1.1.26