/[dynamips]/trunk/dev_c2600.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_c2600.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: 26687 byte(s)
make working copy

1 dpavlin 7 /*
2     * Cisco router simulation platform.
3     * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4     *
5     * Generic Cisco 2600 routines and definitions (EEPROM,...).
6     */
7    
8     #include <stdio.h>
9     #include <stdlib.h>
10     #include <string.h>
11     #include <unistd.h>
12     #include <sys/types.h>
13     #include <assert.h>
14    
15     #include "cpu.h"
16     #include "vm.h"
17     #include "dynamips.h"
18     #include "memory.h"
19     #include "device.h"
20     #include "ppc32_mem.h"
21     #include "pci_io.h"
22     #include "cisco_eeprom.h"
23     #include "dev_mpc860.h"
24     #include "dev_rom.h"
25     #include "dev_c2600.h"
26 dpavlin 8 #include "dev_c2600_iofpga.h"
27 dpavlin 7 #include "dev_vtty.h"
28     #include "registry.h"
29    
30     /* ======================================================================== */
31     /* EEPROM definitions */
32     /* ======================================================================== */
33    
34     /* Cisco 2600 mainboard EEPROM */
35     static m_uint16_t eeprom_c2600_mb_data[] = {
36     0x0101, 0x0404, 0x0000, 0x0000, 0x4320, 0x00FF, 0x0091, 0x0020,
37     0x0000, 0x0000, 0x0000, 0x0000, 0x3030, 0x3000, 0x0030, 0x3030,
38     0x3002, 0x0200, 0x0000, 0x0000, 0x00FF, 0xFFFF, 0x5006, 0x490B,
39     0x1709, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
40     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
41     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
42     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
43     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
44     };
45    
46     struct c2600_mb_id {
47     char *name;
48     char *mb_driver;
49     m_uint16_t id;
50 dpavlin 11 int xm_model;
51 dpavlin 7 int supported;
52     };
53    
54     struct c2600_mb_id c2600_mainboard_id[] = {
55 dpavlin 11 { "2610" , "CISCO2600-MB-1E" , 0x0091, FALSE, TRUE },
56     { "2611" , "CISCO2600-MB-2E" , 0x0092, FALSE, TRUE },
57     { "2620" , "CISCO2600-MB-1FE" , 0x0094, FALSE, TRUE },
58     { "2621" , "CISCO2600-MB-2FE" , 0x00a2, FALSE, TRUE },
59     { "2610XM" , "CISCO2600-MB-1FE" , 0x036a, TRUE, TRUE },
60     { "2611XM" , "CISCO2600-MB-2FE" , 0x036b, TRUE, FALSE },
61     { "2620XM" , "CISCO2600-MB-1FE" , 0x036c, TRUE, TRUE },
62     { "2621XM" , "CISCO2600-MB-2FE" , 0x036d, TRUE, FALSE },
63     { "2650XM" , "CISCO2600-MB-1FE" , 0x036e, TRUE, TRUE },
64     { "2651XM" , "CISCO2600-MB-2FE" , 0x036f, TRUE, FALSE },
65     { NULL , NULL , 0x0000, FALSE, FALSE },
66 dpavlin 7 };
67    
68     /* ======================================================================== */
69     /* Network Module Drivers */
70     /* ======================================================================== */
71 dpavlin 11 static struct cisco_card_driver *nm_drivers[] = {
72 dpavlin 7 &dev_c2600_mb1e_eth_driver,
73     &dev_c2600_mb2e_eth_driver,
74     &dev_c2600_mb1fe_eth_driver,
75     &dev_c2600_mb2fe_eth_driver,
76    
77     &dev_c2600_nm_1e_driver,
78     &dev_c2600_nm_4e_driver,
79     &dev_c2600_nm_1fe_tx_driver,
80     &dev_c2600_nm_16esw_driver,
81 dpavlin 8
82 dpavlin 11 &dev_c2600_nm_nam_driver,
83     &dev_c2600_nm_cids_driver,
84    
85 dpavlin 7 NULL,
86     };
87    
88     /* ======================================================================== */
89     /* Cisco 2600 router instances */
90     /* ======================================================================== */
91    
92 dpavlin 11 /* Initialize default parameters for a C2600 */
93     static void c2600_init_defaults(c2600_t *router);
94    
95 dpavlin 7 /* Read a byte from the NVRAM */
96     static inline m_uint8_t nvram_read_byte(u_char *base,u_int offset)
97     {
98     m_uint8_t *ptr;
99    
100     ptr = (m_uint8_t *)base + (offset << 2);
101     return(*ptr);
102     }
103    
104     /* Write a byte to the NVRAM */
105     static inline void nvram_write_byte(u_char *base,u_int offset,m_uint8_t val)
106     {
107     m_uint8_t *ptr;
108    
109     ptr = (m_uint8_t *)base + (offset << 2);
110     *ptr = val;
111     }
112    
113     /* Read a 16-bit value from NVRAM */
114     static m_uint16_t nvram_read16(u_char *base,u_int offset)
115     {
116     m_uint16_t val;
117     val = nvram_read_byte(base,offset) << 8;
118     val |= nvram_read_byte(base,offset+1);
119     return(val);
120     }
121    
122     /* Write a 16-bit value to NVRAM */
123     static void nvram_write16(u_char *base,u_int offset,m_uint16_t val)
124     {
125     nvram_write_byte(base,offset,val >> 8);
126     nvram_write_byte(base,offset+1,val & 0xFF);
127     }
128    
129     /* Read a 32-bit value from NVRAM */
130     static m_uint32_t nvram_read32(u_char *base,u_int offset)
131     {
132     m_uint32_t val;
133     val = nvram_read_byte(base,offset) << 24;
134     val |= nvram_read_byte(base,offset+1) << 16;
135     val |= nvram_read_byte(base,offset+2) << 8;
136     val |= nvram_read_byte(base,offset+3);
137     return(val);
138     }
139    
140     /* Write a 32-bit value to NVRAM */
141     static void nvram_write32(u_char *base,u_int offset,m_uint32_t val)
142     {
143     nvram_write_byte(base,offset,val >> 24);
144     nvram_write_byte(base,offset+1,val >> 16);
145     nvram_write_byte(base,offset+2,val >> 8);
146     nvram_write_byte(base,offset+3,val & 0xFF);
147     }
148    
149     /* Read a buffer from NVRAM */
150     static void nvram_memcpy_from(u_char *base,u_int offset,u_char *data,u_int len)
151     {
152     u_int i;
153    
154     for(i=0;i<len;i++) {
155     *data = nvram_read_byte(base,offset+i);
156     data++;
157     }
158     }
159    
160     /* Write a buffer from NVRAM */
161     static void nvram_memcpy_to(u_char *base,u_int offset,u_char *data,u_int len)
162     {
163     u_int i;
164    
165     for(i=0;i<len;i++) {
166     nvram_write_byte(base,offset+i,*data);
167     data++;
168     }
169     }
170    
171     /* Directly extract the configuration from the NVRAM device */
172 dpavlin 11 ssize_t c2600_nvram_extract_config(vm_instance_t *vm,u_char **buffer)
173 dpavlin 7 {
174     u_char *base_ptr;
175     u_int ios_ptr,cfg_ptr,end_ptr;
176     m_uint32_t start,nvlen;
177     m_uint16_t magic1,magic2;
178     struct vdevice *nvram_dev;
179     off_t nvram_size;
180     int fd;
181    
182     if ((nvram_dev = dev_get_by_name(vm,"nvram")))
183     dev_sync(nvram_dev);
184    
185     fd = vm_mmap_open_file(vm,"nvram",&base_ptr,&nvram_size);
186    
187     if (fd == -1)
188     return(-1);
189    
190     ios_ptr = vm->nvram_rom_space;
191     end_ptr = nvram_size;
192    
193     if ((ios_ptr + 0x30) >= end_ptr) {
194     vm_error(vm,"NVRAM file too small\n");
195     return(-1);
196     }
197    
198     magic1 = nvram_read16(base_ptr,ios_ptr+0x06);
199     magic2 = nvram_read16(base_ptr,ios_ptr+0x08);
200    
201     if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) {
202     vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n",
203     magic1,magic2);
204     return(-1);
205     }
206    
207     start = nvram_read32(base_ptr,ios_ptr+0x10) + 1;
208     nvlen = nvram_read32(base_ptr,ios_ptr+0x18);
209    
210     printf("START = 0x%8.8x, LEN = 0x%8.8x\n",start,nvlen);
211     printf("END = 0x%8.8x\n",nvram_read32(base_ptr,ios_ptr+0x14));
212    
213     if (!(*buffer = malloc(nvlen+1))) {
214     vm_error(vm,"unable to allocate config buffer (%u bytes)\n",nvlen);
215     return(-1);
216     }
217    
218     cfg_ptr = ios_ptr + start + 0x08;
219    
220     if ((cfg_ptr + nvlen) > end_ptr) {
221     vm_error(vm,"NVRAM file too small\n");
222     return(-1);
223     }
224    
225     nvram_memcpy_from(base_ptr,cfg_ptr,*buffer,nvlen-1);
226     (*buffer)[nvlen-1] = 0;
227     return(nvlen-1);
228     }
229    
230     /* Compute NVRAM checksum */
231     static m_uint16_t c2600_nvram_cksum(u_char *base_ptr,u_int offset,size_t count)
232     {
233     m_uint32_t sum = 0;
234    
235     while(count > 1) {
236     sum = sum + nvram_read16(base_ptr,offset);
237     offset += 2;
238     count -= sizeof(m_uint16_t);
239     }
240    
241     if (count > 0)
242     sum = sum + ((nvram_read16(base_ptr,offset) & 0xFF) << 8);
243    
244     while(sum>>16)
245     sum = (sum & 0xffff) + (sum >> 16);
246    
247     return(~sum);
248     }
249    
250     /* Directly push the IOS configuration to the NVRAM device */
251 dpavlin 11 int c2600_nvram_push_config(vm_instance_t *vm,u_char *buffer,size_t len)
252 dpavlin 7 {
253     m_uint32_t cfg_offset,cklen,tmp,ios_ptr,cfg_ptr;
254     m_uint16_t cksum;
255     u_char *base_ptr;
256     int fd;
257    
258     fd = vm_mmap_create_file(vm,"nvram",vm->nvram_size*4096,&base_ptr);
259    
260     if (fd == -1)
261     return(-1);
262    
263     cfg_offset = 0x2c;
264     ios_ptr = vm->nvram_rom_space;
265     cfg_ptr = ios_ptr + cfg_offset;
266    
267     /* Write IOS tag, uncompressed config... */
268     nvram_write16(base_ptr,ios_ptr+0x06,0xF0A5);
269     nvram_write16(base_ptr,ios_ptr+0x08,0xABCD);
270     nvram_write16(base_ptr,ios_ptr+0x0a,0x0001);
271     nvram_write16(base_ptr,ios_ptr+0x0c,0x0000);
272     nvram_write16(base_ptr,ios_ptr+0x0e,0x0c04);
273    
274     /* Store file contents to NVRAM */
275     nvram_memcpy_to(base_ptr,cfg_ptr,buffer,len);
276    
277     /* Write config addresses + size */
278     tmp = cfg_offset - 0x08;
279    
280     nvram_write32(base_ptr,ios_ptr+0x10,tmp);
281     nvram_write32(base_ptr,ios_ptr+0x14,tmp + len);
282     nvram_write32(base_ptr,ios_ptr+0x18,len);
283    
284     /* Compute the checksum */
285     cklen = (vm->nvram_size*1024) - (vm->nvram_rom_space + 0x08);
286     cksum = c2600_nvram_cksum(base_ptr,ios_ptr+0x08,cklen);
287     nvram_write16(base_ptr,ios_ptr+0x0c,cksum);
288    
289     vm_mmap_close_file(fd,base_ptr,vm->nvram_size*4096);
290     return(0);
291     }
292    
293     /* Check for empty config */
294     int c2600_nvram_check_empty_config(vm_instance_t *vm)
295     {
296     struct vdevice *dev;
297     m_uint64_t addr;
298     m_uint32_t len;
299    
300     if (!(dev = dev_get_by_name(vm,"nvram")))
301     return(-1);
302    
303     addr = dev->phys_addr + (vm->nvram_rom_space << 2);
304     len = dev->phys_len - (vm->nvram_rom_space << 2);
305    
306     while(len > 0) {
307     if (physmem_copy_u32_from_vm(vm,addr) != 0)
308     return(0);
309    
310     addr += sizeof(m_uint32_t);
311     len -= sizeof(m_uint32_t);
312     }
313    
314     /* Empty NVRAM */
315     vm->conf_reg |= 0x0040;
316     printf("NVRAM is empty, setting config register to 0x%x\n",vm->conf_reg);
317     return(0);
318     }
319    
320     /* Create a new router instance */
321 dpavlin 11 static int c2600_create_instance(vm_instance_t *vm)
322 dpavlin 7 {
323     c2600_t *router;
324    
325     if (!(router = malloc(sizeof(*router)))) {
326 dpavlin 11 fprintf(stderr,"C2600 '%s': Unable to create new instance!\n",vm->name);
327     return(-1);
328 dpavlin 7 }
329    
330     memset(router,0,sizeof(*router));
331 dpavlin 11 router->vm = vm;
332     vm->hw_data = router;
333 dpavlin 7
334     c2600_init_defaults(router);
335 dpavlin 11 return(0);
336 dpavlin 7 }
337    
338     /* Free resources used by a router instance */
339 dpavlin 11 static int c2600_delete_instance(vm_instance_t *vm)
340 dpavlin 7 {
341 dpavlin 11 c2600_t *router = VM_C2600(vm);
342 dpavlin 7 int i;
343    
344 dpavlin 11 /* Stop all CPUs */
345     if (vm->cpu_group != NULL) {
346     vm_stop(vm);
347 dpavlin 7
348 dpavlin 11 if (cpu_group_sync_state(vm->cpu_group) == -1) {
349     vm_error(vm,"unable to sync with system CPUs.\n");
350     return(FALSE);
351 dpavlin 7 }
352 dpavlin 11 }
353 dpavlin 7
354 dpavlin 11 /* Remove NIO bindings */
355     for(i=0;i<vm->nr_slots;i++)
356     vm_slot_remove_all_nio_bindings(vm,i);
357 dpavlin 7
358 dpavlin 11 /* Shutdown all Network Modules */
359     vm_slot_shutdown_all(vm);
360    
361     /* Free mainboard EEPROM */
362     cisco_eeprom_free(&router->mb_eeprom);
363 dpavlin 7
364 dpavlin 11 /* Free all resources used by VM */
365     vm_free(vm);
366 dpavlin 7
367 dpavlin 11 /* Free the router structure */
368     free(router);
369     return(TRUE);
370 dpavlin 7 }
371    
372     /* Save configuration of a C2600 instance */
373 dpavlin 11 void c2600_save_config(vm_instance_t *vm,FILE *fd)
374 dpavlin 7 {
375 dpavlin 11 c2600_t *router = VM_C2600(vm);
376 dpavlin 7
377 dpavlin 11 fprintf(fd,"c2600 set_chassis %s %s\n\n",vm->name,router->mainboard_type);
378 dpavlin 7 }
379    
380 dpavlin 11 /* Get WIC device address for the specified onboard port */
381     int c2600_get_onboard_wic_addr(u_int slot,m_uint64_t *phys_addr)
382 dpavlin 7 {
383 dpavlin 11 if (slot >= C2600_MAX_WIC_BAYS)
384     return(-1);
385 dpavlin 7
386 dpavlin 11 *phys_addr = C2600_WIC_ADDR + (slot * C2600_WIC_SIZE);
387     return(0);
388 dpavlin 7 }
389    
390 dpavlin 11 /* Set EEPROM for the specified slot */
391     int c2600_set_slot_eeprom(c2600_t *router,u_int slot,
392     struct cisco_eeprom *eeprom)
393 dpavlin 7 {
394 dpavlin 11 switch(slot) {
395     case 1:
396     router->nm_eeprom_group.eeprom[0] = eeprom;
397     return(0);
398     default:
399     return(-1);
400     }
401 dpavlin 7 }
402    
403 dpavlin 8 /* Get slot/port corresponding to specified network IRQ */
404     static inline void
405     c2600_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port)
406     {
407     irq -= C2600_NETIO_IRQ_BASE;
408     *port = irq & C2600_NETIO_IRQ_PORT_MASK;
409     *slot = irq >> C2600_NETIO_IRQ_PORT_BITS;
410     }
411    
412     /* Get network IRQ for specified slot/port */
413     u_int c2600_net_irq_for_slot_port(u_int slot,u_int port)
414     {
415     u_int irq;
416    
417     irq = (slot << C2600_NETIO_IRQ_PORT_BITS) + port;
418     irq += C2600_NETIO_IRQ_BASE;
419    
420     return(irq);
421     }
422    
423 dpavlin 7 /* Find Cisco 2600 Mainboard info */
424     static struct c2600_mb_id *c2600_get_mb_info(char *mainboard_type)
425     {
426     int i;
427    
428     for(i=0;c2600_mainboard_id[i].name;i++)
429     if (!strcmp(c2600_mainboard_id[i].name,mainboard_type))
430     return(&c2600_mainboard_id[i]);
431    
432     return NULL;
433     }
434    
435     /* Show all available mainboards */
436     void c2600_mainboard_show_drivers(void)
437     {
438     int i;
439    
440     printf("Available C2600 chassis drivers:\n");
441    
442     for(i=0;c2600_mainboard_id[i].name;i++)
443     printf(" * %s %s\n",
444     c2600_mainboard_id[i].name,
445     !c2600_mainboard_id[i].supported ? "(NOT WORKING)" : "");
446    
447     printf("\n");
448     }
449    
450     /* Show the list of available NM drivers */
451     void c2600_nm_show_drivers(void)
452     {
453     int i;
454    
455     printf("Available C2600 Network Module drivers:\n");
456    
457     for(i=0;nm_drivers[i];i++) {
458     printf(" * %s %s\n",
459     nm_drivers[i]->dev_type,
460     !nm_drivers[i]->supported ? "(NOT WORKING)" : "");
461     }
462    
463     printf("\n");
464     }
465    
466     /* Set the base MAC address of the chassis */
467     static int c2600_burn_mac_addr(c2600_t *router,n_eth_addr_t *addr)
468     {
469     int i;
470    
471     for(i=0;i<3;i++) {
472     router->vm->chassis_cookie[i+1] = addr->eth_addr_byte[i*2] << 8;
473     router->vm->chassis_cookie[i+1] |= addr->eth_addr_byte[(i*2)+1];
474     }
475    
476     return(0);
477     }
478    
479     /* Set mainboard type */
480     int c2600_mainboard_set_type(c2600_t *router,char *mainboard_type)
481     {
482     struct c2600_mb_id *mb_info;
483    
484     if (router->vm->status == VM_STATUS_RUNNING) {
485     vm_error(router->vm,"unable to change mainboard type when online.\n");
486     return(-1);
487     }
488    
489     if (!(mb_info = c2600_get_mb_info(mainboard_type))) {
490     vm_error(router->vm,"unknown mainboard '%s'\n",mainboard_type);
491     return(-1);
492     }
493    
494     router->mainboard_type = mainboard_type;
495 dpavlin 11 router->xm_model = mb_info->xm_model;
496 dpavlin 7
497     /* Set the cookie */
498     memcpy(router->vm->chassis_cookie,
499     eeprom_c2600_mb_data,sizeof(eeprom_c2600_mb_data));
500    
501     router->vm->chassis_cookie[6] = mb_info->id;
502    
503     /* Set the chassis base MAC address */
504     c2600_burn_mac_addr(router,&router->mac_addr);
505 dpavlin 11
506     /* Set the mainboard driver */
507     if (vm_slot_active(router->vm,0,0))
508     vm_slot_remove_binding(router->vm,0,0);
509    
510     vm_slot_add_binding(router->vm,mb_info->mb_driver,0,0);
511 dpavlin 7 return(0);
512     }
513    
514     /* Set chassis MAC address */
515     int c2600_chassis_set_mac_addr(c2600_t *router,char *mac_addr)
516     {
517     if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) {
518     vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr);
519     return(-1);
520     }
521    
522     /* Set the chassis base MAC address */
523     c2600_burn_mac_addr(router,&router->mac_addr);
524     return(0);
525     }
526    
527     /* Initialize a Cisco 2600 */
528     static int c2600_init(c2600_t *router)
529     {
530     vm_instance_t *vm = router->vm;
531    
532     /* Create the PCI bus */
533     if (!(vm->pci_bus[0] = pci_bus_create("PCI0",0))) {
534     vm_error(vm,"unable to create PCI data.\n");
535     return(-1);
536     }
537    
538     /* Create the PCI controller */
539 dpavlin 11 if (dev_c2600_pci_init(vm,"c2600_pci",C2600_PCICTRL_ADDR,0x10000,
540 dpavlin 7 vm->pci_bus[0]) == -1)
541     return(-1);
542    
543     /* Bind PCI bus to slots 0 and 1 */
544 dpavlin 11 vm->slots_pci_bus[0] = vm->pci_bus[0];
545     vm->slots_pci_bus[1] = vm->pci_bus[0];
546 dpavlin 7
547     vm->elf_machine_id = C2600_ELF_MACHINE_ID;
548     return(0);
549     }
550    
551     /* Show C2600 hardware info */
552     void c2600_show_hardware(c2600_t *router)
553     {
554     vm_instance_t *vm = router->vm;
555    
556     printf("C2600 instance '%s' (id %d):\n",vm->name,vm->instance_id);
557    
558     printf(" VM Status : %d\n",vm->status);
559     printf(" RAM size : %u Mb\n",vm->ram_size);
560     printf(" NVRAM size : %u Kb\n",vm->nvram_size);
561     printf(" IOS image : %s\n\n",vm->ios_image);
562    
563     if (vm->debug_level > 0) {
564     dev_show_list(vm);
565     pci_dev_show_list(vm->pci_bus[0]);
566     pci_dev_show_list(vm->pci_bus[1]);
567     printf("\n");
568     }
569     }
570    
571     /* Initialize default parameters for a C2600 */
572 dpavlin 11 static void c2600_init_defaults(c2600_t *router)
573 dpavlin 7 {
574     vm_instance_t *vm = router->vm;
575     n_eth_addr_t *m;
576     m_uint16_t pid;
577    
578 dpavlin 11 /* Set platform slots characteristics */
579     vm->nr_slots = C2600_MAX_NM_BAYS;
580     vm->slots_type = CISCO_CARD_TYPE_NM;
581     vm->slots_drivers = nm_drivers;
582    
583 dpavlin 7 pid = (m_uint16_t)getpid();
584    
585     /* Generate a chassis MAC address based on the instance ID */
586     m = &router->mac_addr;
587     m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
588     m->eth_addr_byte[1] = vm->instance_id & 0xFF;
589     m->eth_addr_byte[2] = pid >> 8;
590     m->eth_addr_byte[3] = pid & 0xFF;
591     m->eth_addr_byte[4] = 0x00;
592     m->eth_addr_byte[5] = 0x00;
593    
594     c2600_init_eeprom_groups(router);
595     c2600_mainboard_set_type(router,C2600_DEFAULT_MAINBOARD);
596     c2600_burn_mac_addr(router,&router->mac_addr);
597    
598     vm->ram_mmap = C2600_DEFAULT_RAM_MMAP;
599     vm->ram_size = C2600_DEFAULT_RAM_SIZE;
600     vm->rom_size = C2600_DEFAULT_ROM_SIZE;
601     vm->nvram_size = C2600_DEFAULT_NVRAM_SIZE;
602     vm->conf_reg_setup = C2600_DEFAULT_CONF_REG;
603     vm->clock_divisor = C2600_DEFAULT_CLOCK_DIV;
604     vm->nvram_rom_space = C2600_NVRAM_ROM_RES_SIZE;
605 dpavlin 11 vm->nm_iomem_size = C2600_DEFAULT_IOMEM_SIZE;
606 dpavlin 7
607     vm->pcmcia_disk_size[0] = C2600_DEFAULT_DISK0_SIZE;
608     vm->pcmcia_disk_size[1] = C2600_DEFAULT_DISK1_SIZE;
609     }
610    
611     /* Set an IRQ */
612     static void c2600_set_irq(vm_instance_t *vm,u_int irq)
613     {
614     c2600_t *router = VM_C2600(vm);
615     cpu_ppc_t *cpu = CPU_PPC32(vm->boot_cpu);
616 dpavlin 8 u_int slot,port;
617    
618 dpavlin 7 switch(irq) {
619     case C2600_VTIMER_IRQ:
620     mpc860_set_pending_irq(router->mpc_data,30);
621     break;
622     case C2600_DUART_IRQ:
623     mpc860_set_pending_irq(router->mpc_data,29);
624     break;
625     case C2600_NETIO_IRQ:
626     mpc860_set_pending_irq(router->mpc_data,25);
627     break;
628     case C2600_PA_MGMT_IRQ:
629     mpc860_set_pending_irq(router->mpc_data,27);
630     break;
631    
632 dpavlin 8 case C2600_NETIO_IRQ_BASE ... C2600_NETIO_IRQ_END:
633     c2600_net_irq_get_slot_port(irq,&slot,&port);
634     dev_c2600_iofpga_net_set_irq(router->iofpga_data,slot,port);
635     break;
636    
637 dpavlin 7 /* IRQ test */
638     case 255:
639     mpc860_set_pending_irq(router->mpc_data,24);
640     break;
641     }
642    
643 dpavlin 8 if (vm->irq_idle_preempt[irq])
644 dpavlin 7 cpu_idle_break_wait(cpu->gen);
645     }
646    
647     /* Clear an IRQ */
648     static void c2600_clear_irq(vm_instance_t *vm,u_int irq)
649     {
650     c2600_t *router = VM_C2600(vm);
651 dpavlin 8 u_int slot,port;
652 dpavlin 7
653     switch(irq) {
654     case C2600_VTIMER_IRQ:
655     mpc860_clear_pending_irq(router->mpc_data,30);
656     break;
657     case C2600_DUART_IRQ:
658     mpc860_clear_pending_irq(router->mpc_data,29);
659     break;
660     case C2600_NETIO_IRQ:
661     mpc860_clear_pending_irq(router->mpc_data,25);
662     break;
663     case C2600_PA_MGMT_IRQ:
664     mpc860_clear_pending_irq(router->mpc_data,27);
665     break;
666    
667 dpavlin 8 case C2600_NETIO_IRQ_BASE ... C2600_NETIO_IRQ_END:
668     c2600_net_irq_get_slot_port(irq,&slot,&port);
669     dev_c2600_iofpga_net_clear_irq(router->iofpga_data,slot,port);
670     break;
671    
672 dpavlin 7 /* IRQ test */
673     case 255:
674     mpc860_clear_pending_irq(router->mpc_data,24);
675     break;
676     }
677     }
678    
679     /* Initialize the C2600 Platform */
680 dpavlin 11 static int c2600_init_platform(c2600_t *router)
681 dpavlin 7 {
682     vm_instance_t *vm = router->vm;
683     vm_obj_t *obj;
684     cpu_ppc_t *cpu;
685     cpu_gen_t *gen;
686    
687     /* Copy config register setup into "active" config register */
688     vm->conf_reg = vm->conf_reg_setup;
689    
690     /* Create Console and AUX ports */
691     vm_init_vtty(vm);
692    
693     /* Create a CPU group */
694     vm->cpu_group = cpu_group_create("System CPU");
695    
696     /* Initialize the virtual PowerPC processor */
697     if (!(gen = cpu_create(vm,CPU_TYPE_PPC32,0))) {
698     vm_error(vm,"unable to create CPU!\n");
699     return(-1);
700     }
701    
702     cpu = CPU_PPC32(gen);
703    
704     /* Add this CPU to the system CPU group */
705     cpu_group_add(vm->cpu_group,gen);
706     vm->boot_cpu = gen;
707    
708     /* Set processor ID */
709     ppc32_set_pvr(cpu,0x00500202);
710 dpavlin 8
711 dpavlin 7 /* Mark the Network IO interrupt as high priority */
712 dpavlin 8 vm->irq_idle_preempt[C2600_NETIO_IRQ] = TRUE;
713     vm->irq_idle_preempt[C2600_DUART_IRQ] = TRUE;
714 dpavlin 7
715     /* Copy some parameters from VM to CPU (idle PC, ...) */
716     cpu->idle_pc = vm->idle_pc;
717    
718     if (vm->timer_irq_check_itv)
719     cpu->timer_irq_check_itv = vm->timer_irq_check_itv;
720    
721     /* Remote emulator control */
722     dev_remote_control_init(vm,0xf6000000,0x1000);
723    
724     /* MPC860 */
725 dpavlin 11 cpu->mpc860_immr = C2600_MPC860_ADDR;
726    
727 dpavlin 7 if (dev_mpc860_init(vm,"MPC860",C2600_MPC860_ADDR,0x10000) == -1)
728     return(-1);
729    
730     if (!(obj = vm_object_find(router->vm,"MPC860")))
731     return(-1);
732    
733     router->mpc_data = obj->data;
734    
735     /* IO FPGA */
736     if (dev_c2600_iofpga_init(router,C2600_IOFPGA_ADDR,0x10000) == -1)
737     return(-1);
738    
739 dpavlin 8 if (!(obj = vm_object_find(router->vm,"io_fpga")))
740     return(-1);
741    
742     router->iofpga_data = obj->data;
743    
744 dpavlin 7 /* Initialize the chassis */
745     if (c2600_init(router) == -1)
746     return(-1);
747    
748     /* Initialize RAM */
749     vm_ram_init(vm,0x00000000ULL);
750    
751     /* Initialize ROM */
752     if (!vm->rom_filename) {
753     /* use embedded ROM */
754     dev_rom_init(vm,"rom",C2600_ROM_ADDR,512*1024,
755     ppc32_microcode,ppc32_microcode_len);
756     } else {
757     /* use alternate ROM */
758     dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE,C2600_ROM_ADDR,512*1024);
759     }
760    
761     /* RAM aliasing */
762     dev_create_ram_alias(vm,"ram_alias","ram",0x80000000,vm->ram_size*1048576);
763    
764     /* NVRAM */
765     dev_ram_init(vm,"nvram",TRUE,FALSE,NULL,FALSE,
766     C2600_NVRAM_ADDR,vm->nvram_size*4096);
767     c2600_nvram_check_empty_config(vm);
768    
769     /* Bootflash */
770 dpavlin 11 dev_bootflash_init(vm,"flash0","c2600-bootflash-8mb",
771     C2600_FLASH_ADDR);
772     dev_bootflash_init(vm,"flash1","c2600-bootflash-8mb",
773     C2600_FLASH_ADDR+0x800000);
774 dpavlin 7
775     /* Initialize the NS16552 DUART */
776     dev_ns16552_init(vm,C2600_DUART_ADDR,0x1000,0,C2600_DUART_IRQ,
777     vm->vtty_con,vm->vtty_aux);
778    
779     /* Initialize Network Modules */
780 dpavlin 11 if (vm_slot_init_all(vm) == -1)
781     return(-1);
782 dpavlin 7
783     /* Show device list */
784     c2600_show_hardware(router);
785     return(0);
786     }
787    
788     static struct ppc32_bat_prog bat_array[] = {
789     { PPC32_IBAT_IDX, 0, 0xfff0001e, 0xfff00001 },
790     { PPC32_IBAT_IDX, 1, 0x00001ffe, 0x00000001 },
791     { PPC32_IBAT_IDX, 2, 0x00000000, 0xee3e0072 },
792 dpavlin 8 { PPC32_IBAT_IDX, 3, 0x80001ffe, 0x00000001 },
793 dpavlin 7
794 dpavlin 8 { PPC32_DBAT_IDX, 0, 0x80001ffe, 0x00000042 },
795 dpavlin 7 { PPC32_DBAT_IDX, 1, 0x00001ffe, 0x0000002a },
796     { PPC32_DBAT_IDX, 2, 0x40007ffe, 0x4000002a },
797 dpavlin 8 { PPC32_DBAT_IDX, 3, 0xf0001ffe, 0xf000002a },
798 dpavlin 7 { -1, -1, 0, 0 },
799     };
800    
801     /* Boot the IOS image */
802     int c2600_boot_ios(c2600_t *router)
803     {
804     vm_instance_t *vm = router->vm;
805     cpu_ppc_t *cpu;
806    
807     if (!vm->boot_cpu)
808     return(-1);
809    
810     /* Suspend CPU activity since we will restart directly from ROM */
811     vm_suspend(vm);
812    
813     /* Check that CPU activity is really suspended */
814     if (cpu_group_sync_state(vm->cpu_group) == -1) {
815     vm_error(vm,"unable to sync with system CPUs.\n");
816     return(-1);
817     }
818    
819     /* Reset the boot CPU */
820     cpu = CPU_PPC32(vm->boot_cpu);
821     ppc32_reset(cpu);
822    
823     /* Adjust stack pointer */
824     cpu->gpr[1] |= 0x80000000;
825    
826     /* Load BAT registers */
827     printf("Loading BAT registers\n");
828 dpavlin 8 ppc32_load_bat_array(cpu,bat_array);
829     cpu->msr |= PPC32_MSR_IR|PPC32_MSR_DR;
830 dpavlin 7
831     /* IRQ routing */
832     vm->set_irq = c2600_set_irq;
833     vm->clear_irq = c2600_clear_irq;
834    
835     /* Load IOS image */
836     if (ppc32_load_elf_image(cpu,vm->ios_image,
837     (vm->ghost_status == VM_GHOST_RAM_USE),
838     &vm->ios_entry_point) < 0)
839     {
840     vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
841     return(-1);
842     }
843    
844     /* Launch the simulation */
845     printf("\nC2600 '%s': starting simulation (CPU0 IA=0x%8.8x), "
846     "JIT %sabled.\n",
847     vm->name,cpu->ia,vm->jit_use ? "en":"dis");
848    
849     vm_log(vm,"C2600_BOOT",
850     "starting instance (CPU0 PC=0x%8.8x,idle_pc=0x%8.8x,JIT %s)\n",
851     cpu->ia,cpu->idle_pc,vm->jit_use ? "on":"off");
852    
853     /* Start main CPU */
854     if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
855     vm->status = VM_STATUS_RUNNING;
856     cpu_start(vm->boot_cpu);
857     } else {
858     vm->status = VM_STATUS_SHUTDOWN;
859     }
860     return(0);
861     }
862    
863     /* Initialize a Cisco 2600 instance */
864 dpavlin 11 static int c2600_init_instance(vm_instance_t *vm)
865 dpavlin 7 {
866 dpavlin 11 c2600_t *router = VM_C2600(vm);
867 dpavlin 7 m_uint32_t rom_entry_point;
868     cpu_ppc_t *cpu0;
869    
870     if (!vm->ios_image) {
871     vm_error(vm,"no Cisco IOS image defined.");
872     return(-1);
873     }
874    
875     /* Initialize the C2600 platform */
876     if (c2600_init_platform(router) == -1) {
877     vm_error(vm,"unable to initialize the platform hardware.\n");
878     return(-1);
879     }
880    
881     /* Load IOS configuration file */
882     if (vm->ios_config != NULL) {
883     vm_nvram_push_config(vm,vm->ios_config);
884     vm->conf_reg &= ~0x40;
885     }
886    
887     /* Load ROM (ELF image or embedded) */
888     cpu0 = CPU_PPC32(vm->boot_cpu);
889     rom_entry_point = (m_uint32_t)PPC32_ROM_START;
890    
891     if ((vm->rom_filename != NULL) &&
892     (ppc32_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
893     {
894     vm_error(vm,"unable to load alternate ROM '%s', "
895     "fallback to embedded ROM.\n\n",vm->rom_filename);
896     vm->rom_filename = NULL;
897     }
898    
899     return(c2600_boot_ios(router));
900     }
901    
902     /* Stop a Cisco 2600 instance */
903 dpavlin 11 int c2600_stop_instance(vm_instance_t *vm)
904 dpavlin 7 {
905     printf("\nC2600 '%s': stopping simulation.\n",vm->name);
906     vm_log(vm,"C2600_STOP","stopping simulation.\n");
907    
908     /* Stop all CPUs */
909     if (vm->cpu_group != NULL) {
910     vm_stop(vm);
911    
912     if (cpu_group_sync_state(vm->cpu_group) == -1) {
913     vm_error(vm,"unable to sync with system CPUs.\n");
914     return(-1);
915     }
916     }
917    
918     /* Free resources that were used during execution to emulate hardware */
919 dpavlin 11 vm_slot_shutdown_all(vm);
920 dpavlin 7 vm_hardware_shutdown(vm);
921     return(0);
922     }
923 dpavlin 11
924     /* Get MAC address MSB */
925     static u_int c2600_get_mac_addr_msb(void)
926     {
927     return(0xC8);
928     }
929    
930     /* Parse specific options for the Cisco 2600 platform */
931     static int c2600_cli_parse_options(vm_instance_t *vm,int option)
932     {
933     c2600_t *router = VM_C2600(vm);
934    
935     switch(option) {
936     /* IO memory reserved for NMs (in percents!) */
937     case OPT_IOMEM_SIZE:
938     vm->nm_iomem_size = 0x8000 | atoi(optarg);
939     break;
940    
941     /* Mainboard type */
942     case 't':
943     c2600_mainboard_set_type(router,optarg);
944     break;
945    
946     /* Unknown option */
947     default:
948     return(-1);
949     }
950    
951     return(0);
952     }
953    
954     /* Show specific CLI options */
955     static void c2600_cli_show_options(vm_instance_t *vm)
956     {
957     printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n"
958     " -p <nm_desc> : Define a Network Module\n"
959     " -s <nm_nio> : Bind a Network IO interface to a "
960     "Network Module\n",
961     vm->nm_iomem_size);
962     }
963    
964     /* Platform definition */
965     static vm_platform_t c2600_platform = {
966     "c2600", "C2600", "2600",
967     c2600_create_instance,
968     c2600_delete_instance,
969     c2600_init_instance,
970     c2600_stop_instance,
971     c2600_nvram_extract_config,
972     c2600_nvram_push_config,
973     c2600_get_mac_addr_msb,
974     c2600_save_config,
975     c2600_cli_parse_options,
976     c2600_cli_show_options,
977     c2600_mainboard_show_drivers,
978     };
979    
980     /* Register the c2600 platform */
981     int c2600_platform_register(void)
982     {
983     if (vm_platform_register(&c2600_platform) == -1)
984     return(-1);
985    
986     return(hypervisor_c2600_init(&c2600_platform));
987     }

  ViewVC Help
Powered by ViewVC 1.1.26