/[dynamips]/trunk/dev_c2691.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_c2691.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_c2691.c
File MIME type: text/plain
File size: 37047 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 2691 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_c2691.h"
25 dpavlin 8 #include "dev_c2691_iofpga.h"
26 dpavlin 4 #include "dev_vtty.h"
27     #include "registry.h"
28    
29     /* ======================================================================== */
30     /* EEPROM definitions */
31     /* ======================================================================== */
32    
33     /* Cisco 2691 mainboard EEPROM */
34     static m_uint16_t eeprom_c2691_mainboard_data[] = {
35     0x04FF, 0xC18B, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0x5809,
36     0x6640, 0x0258, 0xC046, 0x0320, 0x0025, 0x9002, 0x4246, 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, 0x1280, 0xD387,
40     0xC043, 0x0020, 0xC508, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x4100,
41     0x0101, 0x01FF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
42     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
43     };
44    
45     struct cisco_eeprom eeprom_c2691_mainboard = {
46     "C2691 Backplane",
47     eeprom_c2691_mainboard_data,
48     sizeof(eeprom_c2691_mainboard_data)/2,
49     };
50    
51     /* ======================================================================== */
52     /* Network Module Drivers */
53     /* ======================================================================== */
54     static struct c2691_nm_driver *nm_drivers[] = {
55     &dev_c2691_nm_1fe_tx_driver,
56     &dev_c2691_nm_16esw_driver,
57     &dev_c2691_gt96100_fe_driver,
58     &dev_c2691_nm_4t_driver,
59     NULL,
60     };
61    
62     /* ======================================================================== */
63     /* Cisco 2691 router instances */
64     /* ======================================================================== */
65    
66     /* Directly extract the configuration from the NVRAM device */
67     ssize_t c2691_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 + C2691_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 c2691_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 = C2691_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 c2691_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 + C2691_NVRAM_OFFSET;
168    
169     /* Normal config */
170     c2691_nvram_push_config_part(vm,buffer,len,ios_ptr);
171    
172     /* Backup config */
173     c2691_nvram_push_config_part(vm,buffer,len,ios_ptr + C2691_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 c2691_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 + C2691_NVRAM_OFFSET;
190     len = C2691_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     c2691_t *c2691_create_instance(char *name,int instance_id)
208     {
209     c2691_t *router;
210    
211     if (!(router = malloc(sizeof(*router)))) {
212     fprintf(stderr,"C2691 '%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_C2691))) {
219     fprintf(stderr,"C2691 '%s': unable to create VM instance!\n",name);
220     goto err_vm;
221     }
222    
223     c2691_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 c2691_free_instance(void *data,void *arg)
234     {
235     vm_instance_t *vm = data;
236     c2691_t *router;
237     int i;
238    
239     if (vm->type == VM_TYPE_C2691) {
240     router = VM_C2691(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<C2691_MAX_NM_BAYS;i++)
254     c2691_nm_remove_all_nio_bindings(router,i);
255    
256     /* Shutdown all Network Modules */
257     c2691_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 c2691_delete_instance(char *name)
275     {
276     return(registry_delete_if_unused(name,OBJ_TYPE_VM,
277     c2691_free_instance,NULL));
278     }
279    
280     /* Delete all router instances */
281     int c2691_delete_all_instances(void)
282     {
283     return(registry_delete_type(OBJ_TYPE_VM,c2691_free_instance,NULL));
284     }
285    
286     /* Save configuration of a C2691 instance */
287     void c2691_save_config(c2691_t *router,FILE *fd)
288     {
289     vm_instance_t *vm = router->vm;
290     struct c2691_nio_binding *nb;
291     struct c2691_nm_bay *bay;
292     int i;
293    
294     /* General settings */
295     fprintf(fd,"c2691 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<C2691_MAX_NM_BAYS;i++) {
302     if (!(bay = c2691_nm_get_info(router,i)))
303     continue;
304    
305     if (bay->dev_type) {
306     fprintf(fd,"c2691 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,"c2691 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 C2691 instances */
320     static void c2691_reg_save_config(registry_entry_t *entry,void *opt,int *err)
321     {
322     vm_instance_t *vm = entry->data;
323     c2691_t *router = VM_C2691(vm);
324    
325     if (vm->type == VM_TYPE_C2691)
326     c2691_save_config(router,(FILE *)opt);
327     }
328    
329     void c2691_save_config_all(FILE *fd)
330     {
331     registry_foreach_type(OBJ_TYPE_VM,c2691_reg_save_config,fd,NULL);
332     }
333    
334 dpavlin 8 /* Get slot/port corresponding to specified network IRQ */
335     static inline void
336     c2691_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port)
337     {
338     irq -= C2691_NETIO_IRQ_BASE;
339     *port = irq & C2691_NETIO_IRQ_PORT_MASK;
340     *slot = irq >> C2691_NETIO_IRQ_PORT_BITS;
341     }
342    
343     /* Get network IRQ for specified slot/port */
344     u_int c2691_net_irq_for_slot_port(u_int slot,u_int port)
345     {
346     u_int irq;
347    
348     irq = (slot << C2691_NETIO_IRQ_PORT_BITS) + port;
349     irq += C2691_NETIO_IRQ_BASE;
350    
351     return(irq);
352     }
353    
354 dpavlin 4 /* Set NM EEPROM definition */
355     int c2691_nm_set_eeprom(c2691_t *router,u_int nm_bay,
356     const struct cisco_eeprom *eeprom)
357     {
358     if (nm_bay != 1) {
359     vm_error(router->vm,"c2691_nm_set_eeprom: invalid NM Bay %u.\n",nm_bay);
360     return(-1);
361     }
362    
363     if (cisco_eeprom_copy(&router->nm_bay[nm_bay].eeprom,eeprom) == -1) {
364     vm_error(router->vm,"c2691_nm_set_eeprom: no memory.\n");
365     return(-1);
366     }
367    
368     return(0);
369     }
370    
371     /* Unset NM EEPROM definition (empty bay) */
372     int c2691_nm_unset_eeprom(c2691_t *router,u_int nm_bay)
373     {
374     if (nm_bay != 1) {
375     vm_error(router->vm,"c2691_nm_set_eeprom: invalid NM Bay %u.\n",nm_bay);
376     return(-1);
377     }
378    
379     cisco_eeprom_free(&router->nm_bay[nm_bay].eeprom);
380     return(0);
381     }
382    
383     /* Check if a bay has a port adapter */
384     int c2691_nm_check_eeprom(c2691_t *router,u_int nm_bay)
385     {
386     if (nm_bay != 1)
387     return(FALSE);
388    
389     return(cisco_eeprom_valid(&router->nm_bay[nm_bay].eeprom));
390     }
391    
392     /* Get bay info */
393     struct c2691_nm_bay *c2691_nm_get_info(c2691_t *router,u_int nm_bay)
394     {
395     if (nm_bay >= C2691_MAX_NM_BAYS)
396     return NULL;
397    
398     return(&router->nm_bay[nm_bay]);
399     }
400    
401     /* Get NM type */
402     char *c2691_nm_get_type(c2691_t *router,u_int nm_bay)
403     {
404     struct c2691_nm_bay *bay;
405    
406     bay = c2691_nm_get_info(router,nm_bay);
407     return((bay != NULL) ? bay->dev_type : NULL);
408     }
409    
410     /* Get driver info about the specified slot */
411     void *c2691_nm_get_drvinfo(c2691_t *router,u_int nm_bay)
412     {
413     struct c2691_nm_bay *bay;
414    
415     bay = c2691_nm_get_info(router,nm_bay);
416     return((bay != NULL) ? bay->drv_info : NULL);
417     }
418    
419     /* Set driver info for the specified slot */
420     int c2691_nm_set_drvinfo(c2691_t *router,u_int nm_bay,void *drv_info)
421     {
422     struct c2691_nm_bay *bay;
423    
424     if (!(bay = c2691_nm_get_info(router,nm_bay)))
425     return(-1);
426    
427     bay->drv_info = drv_info;
428     return(0);
429     }
430    
431     /* Get a NM driver */
432     static struct c2691_nm_driver *c2691_nm_get_driver(char *dev_type)
433     {
434     int i;
435    
436     for(i=0;nm_drivers[i];i++)
437     if (!strcmp(nm_drivers[i]->dev_type,dev_type))
438     return nm_drivers[i];
439    
440     return NULL;
441     }
442    
443     /* Add a NM binding */
444     int c2691_nm_add_binding(c2691_t *router,char *dev_type,u_int nm_bay)
445     {
446     struct c2691_nm_driver *nm_driver;
447     struct c2691_nm_bay *bay;
448    
449     if (!(bay = c2691_nm_get_info(router,nm_bay)))
450     return(-1);
451    
452     /* check that this bay is empty */
453     if (bay->dev_type != NULL) {
454     vm_error(router->vm,"a NM already exists in slot %u.\n",nm_bay);
455     return(-1);
456     }
457    
458     /* find the NM driver */
459     if (!(nm_driver = c2691_nm_get_driver(dev_type))) {
460     vm_error(router->vm,"unknown NM type '%s'.\n",dev_type);
461     return(-1);
462     }
463    
464     bay->dev_type = nm_driver->dev_type;
465     bay->nm_driver = nm_driver;
466     return(0);
467     }
468    
469     /* Remove a NM binding */
470     int c2691_nm_remove_binding(c2691_t *router,u_int nm_bay)
471     {
472     struct c2691_nm_bay *bay;
473    
474     if (!(bay = c2691_nm_get_info(router,nm_bay)))
475     return(-1);
476    
477     /* stop if this bay is still active */
478     if (bay->drv_info != NULL) {
479     vm_error(router->vm,"slot %u still active.\n",nm_bay);
480     return(-1);
481     }
482    
483     /* check that this bay is not empty */
484     if (bay->dev_type == NULL) {
485     vm_error(router->vm,"slot %u is empty.\n",nm_bay);
486     return(-1);
487     }
488    
489     /* remove all NIOs bindings */
490     c2691_nm_remove_all_nio_bindings(router,nm_bay);
491    
492     bay->dev_type = NULL;
493     bay->nm_driver = NULL;
494     return(0);
495     }
496    
497     /* Find a NIO binding */
498     struct c2691_nio_binding *
499     c2691_nm_find_nio_binding(c2691_t *router,u_int nm_bay,u_int port_id)
500     {
501     struct c2691_nio_binding *nb;
502     struct c2691_nm_bay *bay;
503    
504     if (!(bay = c2691_nm_get_info(router,nm_bay)))
505     return NULL;
506    
507     for(nb=bay->nio_list;nb;nb=nb->next)
508     if (nb->port_id == port_id)
509     return nb;
510    
511     return NULL;
512     }
513    
514     /* Add a network IO binding */
515     int c2691_nm_add_nio_binding(c2691_t *router,u_int nm_bay,u_int port_id,
516     char *nio_name)
517     {
518     struct c2691_nio_binding *nb;
519     struct c2691_nm_bay *bay;
520     netio_desc_t *nio;
521    
522     if (!(bay = c2691_nm_get_info(router,nm_bay)))
523     return(-1);
524    
525     /* check that a NIO is not already bound to this port */
526     if (c2691_nm_find_nio_binding(router,nm_bay,port_id) != NULL) {
527     vm_error(router->vm,"a NIO already exists for interface %u/%u.\n",
528     nm_bay,port_id);
529     return(-1);
530     }
531    
532     /* acquire a reference on the NIO object */
533     if (!(nio = netio_acquire(nio_name))) {
534     vm_error(router->vm,"unable to find NIO '%s'.\n",nio_name);
535     return(-1);
536     }
537    
538     /* create a new binding */
539     if (!(nb = malloc(sizeof(*nb)))) {
540     vm_error(router->vm,"unable to create NIO binding "
541     "for interface %u/%u.\n",nm_bay,port_id);
542     netio_release(nio_name);
543     return(-1);
544     }
545    
546     memset(nb,0,sizeof(*nb));
547     nb->nio = nio;
548     nb->port_id = port_id;
549     nb->next = bay->nio_list;
550     if (nb->next) nb->next->prev = nb;
551     bay->nio_list = nb;
552     return(0);
553     }
554    
555     /* Remove a NIO binding */
556     int c2691_nm_remove_nio_binding(c2691_t *router,u_int nm_bay,u_int port_id)
557     {
558     struct c2691_nio_binding *nb;
559     struct c2691_nm_bay *bay;
560    
561     if (!(bay = c2691_nm_get_info(router,nm_bay)))
562     return(-1);
563    
564     if (!(nb = c2691_nm_find_nio_binding(router,nm_bay,port_id)))
565     return(-1); /* no nio binding for this slot/port */
566    
567     /* tell the NM driver to stop using this NIO */
568     if (bay->nm_driver)
569     bay->nm_driver->nm_unset_nio(router,nm_bay,port_id);
570    
571     /* remove this entry from the double linked list */
572     if (nb->next)
573     nb->next->prev = nb->prev;
574    
575     if (nb->prev) {
576     nb->prev->next = nb->next;
577     } else {
578     bay->nio_list = nb->next;
579     }
580    
581     /* unreference NIO object */
582     netio_release(nb->nio->name);
583     free(nb);
584     return(0);
585     }
586    
587     /* Remove all NIO bindings for the specified NM */
588     int c2691_nm_remove_all_nio_bindings(c2691_t *router,u_int nm_bay)
589     {
590     struct c2691_nio_binding *nb,*next;
591     struct c2691_nm_bay *bay;
592    
593     if (!(bay = c2691_nm_get_info(router,nm_bay)))
594     return(-1);
595    
596     for(nb=bay->nio_list;nb;nb=next) {
597     next = nb->next;
598    
599     /* tell the NM driver to stop using this NIO */
600     if (bay->nm_driver)
601     bay->nm_driver->nm_unset_nio(router,nm_bay,nb->port_id);
602    
603     /* unreference NIO object */
604     netio_release(nb->nio->name);
605     free(nb);
606     }
607    
608     bay->nio_list = NULL;
609     return(0);
610     }
611    
612     /* Enable a Network IO descriptor for a Network Module */
613     int c2691_nm_enable_nio(c2691_t *router,u_int nm_bay,u_int port_id)
614     {
615     struct c2691_nio_binding *nb;
616     struct c2691_nm_bay *bay;
617    
618     if (!(bay = c2691_nm_get_info(router,nm_bay)))
619     return(-1);
620    
621     /* check that we have an NIO binding for this interface */
622     if (!(nb = c2691_nm_find_nio_binding(router,nm_bay,port_id)))
623     return(-1);
624    
625     /* check that the driver is defined and successfully initialized */
626     if (!bay->nm_driver || !bay->drv_info)
627     return(-1);
628    
629     return(bay->nm_driver->nm_set_nio(router,nm_bay,port_id,nb->nio));
630     }
631    
632     /* Disable Network IO descriptor of a Network Module */
633     int c2691_nm_disable_nio(c2691_t *router,u_int nm_bay,u_int port_id)
634     {
635     struct c2691_nm_bay *bay;
636    
637     if (!(bay = c2691_nm_get_info(router,nm_bay)))
638     return(-1);
639    
640     /* check that the driver is defined and successfully initialized */
641     if (!bay->nm_driver || !bay->drv_info)
642     return(-1);
643    
644     return(bay->nm_driver->nm_unset_nio(router,nm_bay,port_id));
645     }
646    
647     /* Enable all NIO of the specified NM */
648     int c2691_nm_enable_all_nio(c2691_t *router,u_int nm_bay)
649     {
650     struct c2691_nio_binding *nb;
651     struct c2691_nm_bay *bay;
652    
653     if (!(bay = c2691_nm_get_info(router,nm_bay)))
654     return(-1);
655    
656     /* check that the driver is defined and successfully initialized */
657     if (!bay->nm_driver || !bay->drv_info)
658     return(-1);
659    
660     for(nb=bay->nio_list;nb;nb=nb->next)
661     bay->nm_driver->nm_set_nio(router,nm_bay,nb->port_id,nb->nio);
662    
663     return(0);
664     }
665    
666     /* Disable all NIO of the specified NM */
667     int c2691_nm_disable_all_nio(c2691_t *router,u_int nm_bay)
668     {
669     struct c2691_nio_binding *nb;
670     struct c2691_nm_bay *bay;
671    
672     if (!(bay = c2691_nm_get_info(router,nm_bay)))
673     return(-1);
674    
675     /* check that the driver is defined and successfully initialized */
676     if (!bay->nm_driver || !bay->drv_info)
677     return(-1);
678    
679     for(nb=bay->nio_list;nb;nb=nb->next)
680     bay->nm_driver->nm_unset_nio(router,nm_bay,nb->port_id);
681    
682     return(0);
683     }
684    
685     /* Initialize a Network Module */
686     int c2691_nm_init(c2691_t *router,u_int nm_bay)
687     {
688     struct c2691_nm_bay *bay;
689     size_t len;
690    
691     if (!(bay = c2691_nm_get_info(router,nm_bay)))
692     return(-1);
693    
694     /* Check that a device type is defined for this bay */
695     if (!bay->dev_type || !bay->nm_driver) {
696     vm_error(router->vm,"trying to init empty slot %u.\n",nm_bay);
697     return(-1);
698     }
699    
700     /* Allocate device name */
701     len = strlen(bay->dev_type) + 10;
702     if (!(bay->dev_name = malloc(len))) {
703     vm_error(router->vm,"unable to allocate device name.\n");
704     return(-1);
705     }
706    
707     snprintf(bay->dev_name,len,"%s(%u)",bay->dev_type,nm_bay);
708    
709     /* Initialize NM driver */
710 dpavlin 8 if (bay->nm_driver->nm_init(router,bay->dev_name,nm_bay) == -1) {
711 dpavlin 4 vm_error(router->vm,"unable to initialize NM %u.\n",nm_bay);
712     return(-1);
713     }
714    
715     /* Enable all NIO */
716     c2691_nm_enable_all_nio(router,nm_bay);
717     return(0);
718     }
719    
720     /* Shutdown a Network Module */
721     int c2691_nm_shutdown(c2691_t *router,u_int nm_bay)
722     {
723     struct c2691_nm_bay *bay;
724    
725     if (!(bay = c2691_nm_get_info(router,nm_bay)))
726     return(-1);
727    
728     /* Check that a device type is defined for this bay */
729     if (!bay->dev_type || !bay->nm_driver) {
730     vm_error(router->vm,"trying to shut down empty slot %u.\n",nm_bay);
731     return(-1);
732     }
733    
734     /* Disable all NIO */
735     c2691_nm_disable_all_nio(router,nm_bay);
736    
737     /* Shutdown the NM driver */
738     if (bay->drv_info && (bay->nm_driver->nm_shutdown(router,nm_bay) == -1)) {
739     vm_error(router->vm,"unable to shutdown NM %u.\n",nm_bay);
740     return(-1);
741     }
742    
743     free(bay->dev_name);
744     bay->dev_name = NULL;
745     bay->drv_info = NULL;
746     return(0);
747     }
748    
749     /* Shutdown all NM of a router */
750     int c2691_nm_shutdown_all(c2691_t *router)
751     {
752     int i;
753    
754     for(i=0;i<C2691_MAX_NM_BAYS;i++) {
755     if (!router->nm_bay[i].dev_type)
756     continue;
757    
758     c2691_nm_shutdown(router,i);
759     }
760    
761     return(0);
762     }
763    
764     /* Show info about all NMs */
765     int c2691_nm_show_all_info(c2691_t *router)
766     {
767     struct c2691_nm_bay *bay;
768     int i;
769    
770     for(i=0;i<C2691_MAX_NM_BAYS;i++) {
771     if (!(bay = c2691_nm_get_info(router,i)) || !bay->nm_driver)
772     continue;
773    
774     if (bay->nm_driver->nm_show_info != NULL)
775     bay->nm_driver->nm_show_info(router,i);
776     }
777    
778     return(0);
779     }
780    
781     /* Maximum number of tokens in a NM description */
782     #define NM_DESC_MAX_TOKENS 8
783    
784     /* Create a Network Module (command line) */
785     int c2691_cmd_nm_create(c2691_t *router,char *str)
786     {
787     char *tokens[NM_DESC_MAX_TOKENS];
788     int i,count,res;
789     u_int nm_bay;
790    
791     /* A port adapter description is like "1:NM-1FE" */
792     if ((count = m_strsplit(str,':',tokens,NM_DESC_MAX_TOKENS)) != 2) {
793     vm_error(router->vm,"unable to parse NM description '%s'.\n",str);
794     return(-1);
795     }
796    
797     /* Parse the NM bay id */
798     nm_bay = atoi(tokens[0]);
799    
800     /* Add this new NM to the current NM list */
801     res = c2691_nm_add_binding(router,tokens[1],nm_bay);
802    
803     /* The complete array was cleaned by strsplit */
804     for(i=0;i<NM_DESC_MAX_TOKENS;i++)
805     free(tokens[i]);
806    
807     return(res);
808     }
809    
810     /* Add a Network IO descriptor binding (command line) */
811     int c2691_cmd_add_nio(c2691_t *router,char *str)
812     {
813     char *tokens[NM_DESC_MAX_TOKENS];
814     int i,count,nio_type,res=-1;
815     u_int nm_bay,port_id;
816     netio_desc_t *nio;
817     char nio_name[128];
818    
819     /* A port adapter description is like "1:3:tap:tap0" */
820     if ((count = m_strsplit(str,':',tokens,NM_DESC_MAX_TOKENS)) < 3) {
821     vm_error(router->vm,"unable to parse NIO description '%s'.\n",str);
822     return(-1);
823     }
824    
825     /* Parse the NM bay */
826     nm_bay = atoi(tokens[0]);
827    
828     /* Parse the NM port id */
829     port_id = atoi(tokens[1]);
830    
831     /* Autogenerate a NIO name */
832     snprintf(nio_name,sizeof(nio_name),"c2691-i%u/%u/%u",
833     router->vm->instance_id,nm_bay,port_id);
834    
835     /* Create the Network IO descriptor */
836     nio = NULL;
837     nio_type = netio_get_type(tokens[2]);
838    
839     switch(nio_type) {
840     case NETIO_TYPE_UNIX:
841     if (count != 5) {
842     vm_error(router->vm,
843     "invalid number of arguments for UNIX NIO '%s'\n",str);
844     goto done;
845     }
846    
847     nio = netio_desc_create_unix(nio_name,tokens[3],tokens[4]);
848     break;
849    
850     case NETIO_TYPE_VDE:
851     if (count != 5) {
852     vm_error(router->vm,
853     "invalid number of arguments for VDE NIO '%s'\n",str);
854     goto done;
855     }
856    
857     nio = netio_desc_create_vde(nio_name,tokens[3],tokens[4]);
858     break;
859    
860     case NETIO_TYPE_TAP:
861     if (count != 4) {
862     vm_error(router->vm,
863     "invalid number of arguments for TAP NIO '%s'\n",str);
864     goto done;
865     }
866    
867     nio = netio_desc_create_tap(nio_name,tokens[3]);
868     break;
869    
870     case NETIO_TYPE_UDP:
871     if (count != 6) {
872     vm_error(router->vm,
873     "invalid number of arguments for UDP NIO '%s'\n",str);
874     goto done;
875     }
876    
877     nio = netio_desc_create_udp(nio_name,atoi(tokens[3]),
878     tokens[4],atoi(tokens[5]));
879     break;
880    
881     case NETIO_TYPE_TCP_CLI:
882     if (count != 5) {
883     vm_error(router->vm,
884     "invalid number of arguments for TCP CLI NIO '%s'\n",str);
885     goto done;
886     }
887    
888     nio = netio_desc_create_tcp_cli(nio_name,tokens[3],tokens[4]);
889     break;
890    
891     case NETIO_TYPE_TCP_SER:
892     if (count != 4) {
893     vm_error(router->vm,
894     "invalid number of arguments for TCP SER NIO '%s'\n",str);
895     goto done;
896     }
897    
898     nio = netio_desc_create_tcp_ser(nio_name,tokens[3]);
899     break;
900    
901     case NETIO_TYPE_NULL:
902     nio = netio_desc_create_null(nio_name);
903     break;
904    
905     #ifdef LINUX_ETH
906     case NETIO_TYPE_LINUX_ETH:
907     if (count != 4) {
908     vm_error(router->vm,
909     "invalid number of arguments for Linux Eth NIO '%s'\n",
910     str);
911     goto done;
912     }
913    
914     nio = netio_desc_create_lnxeth(nio_name,tokens[3]);
915     break;
916     #endif
917    
918     #ifdef GEN_ETH
919     case NETIO_TYPE_GEN_ETH:
920     if (count != 4) {
921     vm_error(router->vm,
922     "invalid number of arguments for Generic Eth NIO '%s'\n",
923     str);
924     goto done;
925     }
926    
927     nio = netio_desc_create_geneth(nio_name,tokens[3]);
928     break;
929     #endif
930    
931     default:
932     vm_error(router->vm,"unknown NETIO type '%s'\n",tokens[2]);
933     goto done;
934     }
935    
936     if (!nio) {
937     vm_error(router->vm,"unable to create NETIO "
938     "descriptor for NM slot %u\n",nm_bay);
939     goto done;
940     }
941    
942     if (c2691_nm_add_nio_binding(router,nm_bay,port_id,nio_name) == -1) {
943     vm_error(router->vm,"unable to add NETIO binding for slot %u\n",nm_bay);
944     netio_release(nio_name);
945     netio_delete(nio_name);
946     goto done;
947     }
948    
949     netio_release(nio_name);
950     res = 0;
951    
952     done:
953     /* The complete array was cleaned by strsplit */
954     for(i=0;i<NM_DESC_MAX_TOKENS;i++)
955     free(tokens[i]);
956    
957     return(res);
958     }
959    
960     /* Show the list of available NM drivers */
961     void c2691_nm_show_drivers(void)
962     {
963     int i;
964    
965     printf("Available C2691 Network Module drivers:\n");
966    
967     for(i=0;nm_drivers[i];i++) {
968     printf(" * %s %s\n",
969     nm_drivers[i]->dev_type,
970     !nm_drivers[i]->supported ? "(NOT WORKING)" : "");
971     }
972    
973     printf("\n");
974     }
975    
976     /* Set the base MAC address of the chassis */
977     static int c2691_burn_mac_addr(c2691_t *router,n_eth_addr_t *addr)
978     {
979     m_uint8_t eeprom_ver;
980     size_t offset;
981    
982     /* Read EEPROM format version */
983     cisco_eeprom_get_byte(&router->mb_eeprom,0,&eeprom_ver);
984    
985     switch(eeprom_ver) {
986     case 0:
987     cisco_eeprom_set_region(&router->mb_eeprom,2,addr->eth_addr_byte,6);
988     break;
989    
990     case 4:
991     if (!cisco_eeprom_v4_find_field(&router->mb_eeprom,0xC3,&offset)) {
992     cisco_eeprom_set_region(&router->mb_eeprom,offset,
993     addr->eth_addr_byte,6);
994     }
995     break;
996    
997     default:
998     vm_error(router->vm,"c2691_burn_mac_addr: unable to handle "
999     "EEPROM version %u\n",eeprom_ver);
1000     return(-1);
1001     }
1002    
1003     return(0);
1004     }
1005    
1006     /* Set chassis MAC address */
1007     int c2691_chassis_set_mac_addr(c2691_t *router,char *mac_addr)
1008     {
1009     if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) {
1010     vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr);
1011     return(-1);
1012     }
1013    
1014     /* Set the chassis base MAC address */
1015     c2691_burn_mac_addr(router,&router->mac_addr);
1016     return(0);
1017     }
1018    
1019     /* Create the two main PCI busses for a GT64120 based system */
1020     static int c2691_init_gt96100(c2691_t *router)
1021     {
1022     vm_instance_t *vm = router->vm;
1023    
1024     vm->pci_bus[0] = pci_bus_create("PCI bus #0",0);
1025     vm->pci_bus[1] = pci_bus_create("PCI bus #1",0);
1026    
1027     if (!vm->pci_bus[0] || !vm->pci_bus[1]) {
1028     vm_error(router->vm,"unable to create PCI data.\n");
1029     return(-1);
1030     }
1031    
1032     return(dev_gt96100_init(vm,"gt96100",C2691_GT96K_ADDR,0x200000,
1033 dpavlin 8 C2691_GT96K_IRQ,c2691_net_irq_for_slot_port(0,0)));
1034 dpavlin 4 }
1035    
1036     /* Initialize a Cisco 2691 */
1037     static int c2691_init(c2691_t *router)
1038     {
1039     vm_instance_t *vm = router->vm;
1040    
1041     /* Set the processor type: R7000 */
1042 dpavlin 7 mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R7000);
1043 dpavlin 4
1044     /* Initialize the Galileo GT-96100 PCI controller */
1045     if (c2691_init_gt96100(router) == -1)
1046     return(-1);
1047    
1048     /* Initialize PCI map (NM slot 1) */
1049     router->nm_bay[1].pci_map = vm->pci_bus[1];
1050    
1051     vm->elf_machine_id = C2691_ELF_MACHINE_ID;
1052     return(0);
1053     }
1054    
1055     /* Show C2691 hardware info */
1056     void c2691_show_hardware(c2691_t *router)
1057     {
1058     vm_instance_t *vm = router->vm;
1059    
1060     printf("C2691 instance '%s' (id %d):\n",vm->name,vm->instance_id);
1061    
1062     printf(" VM Status : %d\n",vm->status);
1063     printf(" RAM size : %u Mb\n",vm->ram_size);
1064     printf(" NVRAM size : %u Kb\n",vm->nvram_size);
1065     printf(" IOS image : %s\n\n",vm->ios_image);
1066    
1067     if (vm->debug_level > 0) {
1068     dev_show_list(vm);
1069     pci_dev_show_list(vm->pci_bus[0]);
1070     pci_dev_show_list(vm->pci_bus[1]);
1071     printf("\n");
1072     }
1073     }
1074    
1075     /* Initialize default parameters for a C2691 */
1076     void c2691_init_defaults(c2691_t *router)
1077     {
1078     vm_instance_t *vm = router->vm;
1079     n_eth_addr_t *m;
1080     m_uint16_t pid;
1081    
1082     pid = (m_uint16_t)getpid();
1083    
1084     /* Generate a chassis MAC address based on the instance ID */
1085     m = &router->mac_addr;
1086     m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
1087     m->eth_addr_byte[1] = vm->instance_id & 0xFF;
1088     m->eth_addr_byte[2] = pid >> 8;
1089     m->eth_addr_byte[3] = pid & 0xFF;
1090     m->eth_addr_byte[4] = 0x00;
1091     m->eth_addr_byte[5] = 0x00;
1092    
1093     c2691_init_eeprom_groups(router);
1094     cisco_eeprom_copy(&router->mb_eeprom,&eeprom_c2691_mainboard);
1095     c2691_burn_mac_addr(router,&router->mac_addr);
1096    
1097     vm->ram_mmap = C2691_DEFAULT_RAM_MMAP;
1098     vm->ram_size = C2691_DEFAULT_RAM_SIZE;
1099     vm->rom_size = C2691_DEFAULT_ROM_SIZE;
1100     vm->nvram_size = C2691_DEFAULT_NVRAM_SIZE;
1101     vm->conf_reg_setup = C2691_DEFAULT_CONF_REG;
1102     vm->clock_divisor = C2691_DEFAULT_CLOCK_DIV;
1103     vm->nvram_rom_space = C2691_NVRAM_ROM_RES_SIZE;
1104     router->nm_iomem_size = C2691_DEFAULT_IOMEM_SIZE;
1105    
1106     vm->pcmcia_disk_size[0] = C2691_DEFAULT_DISK0_SIZE;
1107     vm->pcmcia_disk_size[1] = C2691_DEFAULT_DISK1_SIZE;
1108    
1109     /* Enable NVRAM operations to load/store configs */
1110     vm->nvram_extract_config = c2691_nvram_extract_config;
1111     vm->nvram_push_config = c2691_nvram_push_config;
1112     }
1113    
1114     /* Initialize the C2691 Platform */
1115     int c2691_init_platform(c2691_t *router)
1116     {
1117     vm_instance_t *vm = router->vm;
1118     struct c2691_nm_bay *nm_bay;
1119     cpu_mips_t *cpu;
1120 dpavlin 7 cpu_gen_t *gen;
1121 dpavlin 4 vm_obj_t *obj;
1122     int i;
1123    
1124     /* Copy config register setup into "active" config register */
1125     vm->conf_reg = vm->conf_reg_setup;
1126    
1127     /* Create Console and AUX ports */
1128     vm_init_vtty(vm);
1129    
1130     /* Create a CPU group */
1131     vm->cpu_group = cpu_group_create("System CPU");
1132    
1133     /* Initialize the virtual MIPS processor */
1134 dpavlin 7 if (!(gen = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
1135 dpavlin 4 vm_error(vm,"unable to create CPU!\n");
1136     return(-1);
1137     }
1138    
1139 dpavlin 7 cpu = CPU_MIPS64(gen);
1140    
1141 dpavlin 4 /* Add this CPU to the system CPU group */
1142 dpavlin 7 cpu_group_add(vm->cpu_group,gen);
1143     vm->boot_cpu = gen;
1144 dpavlin 4
1145 dpavlin 7 /* Initialize the IRQ routing vectors */
1146     vm->set_irq = mips64_vm_set_irq;
1147     vm->clear_irq = mips64_vm_clear_irq;
1148    
1149 dpavlin 4 /* Mark the Network IO interrupt as high priority */
1150     cpu->irq_idle_preempt[C2691_NETIO_IRQ] = TRUE;
1151     cpu->irq_idle_preempt[C2691_GT96K_IRQ] = TRUE;
1152     cpu->irq_idle_preempt[C2691_DUART_IRQ] = TRUE;
1153    
1154     /* Copy some parameters from VM to CPU (idle PC, ...) */
1155     cpu->idle_pc = vm->idle_pc;
1156    
1157     if (vm->timer_irq_check_itv)
1158     cpu->timer_irq_check_itv = vm->timer_irq_check_itv;
1159    
1160     /* Remote emulator control */
1161     dev_remote_control_init(vm,0x16000000,0x1000);
1162    
1163     /* Specific Storage Area (SSA) */
1164 dpavlin 7 dev_ram_init(vm,"ssa",TRUE,FALSE,NULL,FALSE,0x16001000ULL,0x7000);
1165 dpavlin 4
1166     /* IO FPGA */
1167     if (dev_c2691_iofpga_init(router,C2691_IOFPGA_ADDR,0x40000) == -1)
1168     return(-1);
1169    
1170 dpavlin 8 if (!(obj = vm_object_find(router->vm,"io_fpga")))
1171     return(-1);
1172    
1173     router->iofpga_data = obj->data;
1174    
1175 dpavlin 4 #if 0
1176     /* PCI IO space */
1177     if (!(vm->pci_io_space = pci_io_data_init(vm,C2691_PCI_IO_ADDR)))
1178     return(-1);
1179     #endif
1180    
1181     /* Initialize the chassis */
1182     if (c2691_init(router) == -1)
1183     return(-1);
1184    
1185     /* Initialize RAM */
1186     vm_ram_init(vm,0x00000000ULL);
1187    
1188     /* Initialize ROM (as a Flash) */
1189     if (!(obj = dev_flash_init(vm,"rom",C2691_ROM_ADDR,vm->rom_size*1048576)))
1190     return(-1);
1191    
1192 dpavlin 7 dev_flash_copy_data(obj,0,mips64_microcode,mips64_microcode_len);
1193 dpavlin 4 c2691_nvram_check_empty_config(vm);
1194    
1195     /* Initialize the NS16552 DUART */
1196     dev_ns16552_init(vm,C2691_DUART_ADDR,0x1000,3,C2691_DUART_IRQ,
1197     vm->vtty_con,vm->vtty_aux);
1198    
1199     /* PCMCIA Slot 0 */
1200     dev_pcmcia_disk_init(vm,"slot0",C2691_SLOT0_ADDR,0x200000,
1201     vm->pcmcia_disk_size[0],1);
1202    
1203     /* PCMCIA Slot 1 */
1204     dev_pcmcia_disk_init(vm,"slot1",C2691_SLOT1_ADDR,0x200000,
1205     vm->pcmcia_disk_size[1],1);
1206    
1207     /* The GT96100 system controller has 2 integrated FastEthernet ports */
1208     c2691_nm_add_binding(router,"GT96100-FE",0);
1209    
1210     /* Initialize Network Modules */
1211     for(i=0;i<C2691_MAX_NM_BAYS;i++) {
1212     nm_bay = &router->nm_bay[i];
1213    
1214     if (!nm_bay->dev_type)
1215     continue;
1216    
1217     if (c2691_nm_init(router,i) == -1) {
1218     vm_error(vm,"unable to create Network Module \"%s\"\n",
1219     nm_bay->dev_type);
1220     return(-1);
1221     }
1222     }
1223    
1224     /* Show device list */
1225     c2691_show_hardware(router);
1226     return(0);
1227     }
1228    
1229     /* Boot the IOS image */
1230     int c2691_boot_ios(c2691_t *router)
1231     {
1232     vm_instance_t *vm = router->vm;
1233 dpavlin 7 cpu_mips_t *cpu;
1234 dpavlin 4
1235     if (!vm->boot_cpu)
1236     return(-1);
1237    
1238     /* Suspend CPU activity since we will restart directly from ROM */
1239     vm_suspend(vm);
1240    
1241     /* Check that CPU activity is really suspended */
1242     if (cpu_group_sync_state(vm->cpu_group) == -1) {
1243     vm_error(vm,"unable to sync with system CPUs.\n");
1244     return(-1);
1245     }
1246    
1247     /* Reset the boot CPU */
1248 dpavlin 7 cpu = CPU_MIPS64(vm->boot_cpu);
1249     mips64_reset(cpu);
1250 dpavlin 4
1251     /* Load IOS image */
1252 dpavlin 7 if (mips64_load_elf_image(cpu,vm->ios_image,
1253 dpavlin 4 (vm->ghost_status == VM_GHOST_RAM_USE),
1254     &vm->ios_entry_point) < 0)
1255     {
1256     vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
1257     return(-1);
1258     }
1259    
1260     /* Launch the simulation */
1261     printf("\nC2691 '%s': starting simulation (CPU0 PC=0x%llx), "
1262     "JIT %sabled.\n",
1263 dpavlin 7 vm->name,cpu->pc,vm->jit_use ? "en":"dis");
1264 dpavlin 4
1265     vm_log(vm,"C2691_BOOT",
1266     "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
1267 dpavlin 7 cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
1268 dpavlin 4
1269     /* Start main CPU */
1270     if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
1271     vm->status = VM_STATUS_RUNNING;
1272     cpu_start(vm->boot_cpu);
1273     } else {
1274     vm->status = VM_STATUS_SHUTDOWN;
1275     }
1276     return(0);
1277     }
1278    
1279 dpavlin 8 /* Set an IRQ */
1280     static void c2691_set_irq(vm_instance_t *vm,u_int irq)
1281     {
1282     c2691_t *router = VM_C2691(vm);
1283     cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
1284     u_int slot,port;
1285    
1286     switch(irq) {
1287     case 0 ... 7:
1288     mips64_set_irq(cpu0,irq);
1289    
1290     if (cpu0->irq_idle_preempt[irq])
1291     cpu_idle_break_wait(cpu0->gen);
1292     break;
1293    
1294     case C2691_NETIO_IRQ_BASE ... C2691_NETIO_IRQ_END:
1295     c2691_net_irq_get_slot_port(irq,&slot,&port);
1296     dev_c2691_iofpga_net_set_irq(router->iofpga_data,slot,port);
1297     break;
1298     }
1299     }
1300    
1301     /* Clear an IRQ */
1302     static void c2691_clear_irq(vm_instance_t *vm,u_int irq)
1303     {
1304     c2691_t *router = VM_C2691(vm);
1305     cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
1306     u_int slot,port;
1307    
1308     switch(irq) {
1309     case 0 ... 7:
1310     mips64_clear_irq(cpu0,irq);
1311     break;
1312    
1313     case C2691_NETIO_IRQ_BASE ... C2691_NETIO_IRQ_END:
1314     c2691_net_irq_get_slot_port(irq,&slot,&port);
1315     dev_c2691_iofpga_net_clear_irq(router->iofpga_data,slot,port);
1316     break;
1317     }
1318     }
1319    
1320 dpavlin 4 /* Initialize a Cisco 2691 instance */
1321     int c2691_init_instance(c2691_t *router)
1322     {
1323     vm_instance_t *vm = router->vm;
1324     m_uint32_t rom_entry_point;
1325     cpu_mips_t *cpu0;
1326    
1327     if (!vm->ios_image) {
1328     vm_error(vm,"no Cisco IOS image defined.");
1329     return(-1);
1330     }
1331    
1332     /* Initialize the C2691 platform */
1333     if (c2691_init_platform(router) == -1) {
1334     vm_error(vm,"unable to initialize the platform hardware.\n");
1335     return(-1);
1336     }
1337    
1338 dpavlin 8 /* IRQ routing */
1339     vm->set_irq = c2691_set_irq;
1340     vm->clear_irq = c2691_clear_irq;
1341    
1342 dpavlin 4 /* Load IOS configuration file */
1343     if (vm->ios_config != NULL) {
1344     vm_nvram_push_config(vm,vm->ios_config);
1345     vm->conf_reg &= ~0x40;
1346     }
1347    
1348     /* Load ROM (ELF image or embedded) */
1349 dpavlin 7 cpu0 = CPU_MIPS64(vm->boot_cpu);
1350 dpavlin 4 rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
1351    
1352     if ((vm->rom_filename != NULL) &&
1353     (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
1354     {
1355     vm_error(vm,"unable to load alternate ROM '%s', "
1356     "fallback to embedded ROM.\n\n",vm->rom_filename);
1357     vm->rom_filename = NULL;
1358     }
1359    
1360     /* Load symbol file */
1361     if (vm->sym_filename) {
1362     mips64_sym_load_file(cpu0,vm->sym_filename);
1363     cpu0->sym_trace = 1;
1364     }
1365    
1366     return(c2691_boot_ios(router));
1367     }
1368    
1369     /* Stop a Cisco 2691 instance */
1370     int c2691_stop_instance(c2691_t *router)
1371     {
1372     vm_instance_t *vm = router->vm;
1373    
1374     printf("\nC2691 '%s': stopping simulation.\n",vm->name);
1375     vm_log(vm,"C2691_STOP","stopping simulation.\n");
1376    
1377     /* Stop all CPUs */
1378     if (vm->cpu_group != NULL) {
1379     vm_stop(vm);
1380    
1381     if (cpu_group_sync_state(vm->cpu_group) == -1) {
1382     vm_error(vm,"unable to sync with system CPUs.\n");
1383     return(-1);
1384     }
1385     }
1386    
1387     /* Free resources that were used during execution to emulate hardware */
1388     c2691_nm_shutdown_all(router);
1389     vm_hardware_shutdown(vm);
1390     return(0);
1391     }

  ViewVC Help
Powered by ViewVC 1.1.26