/[dynamips]/trunk/dev_c1700.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_c1700.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (hide annotations)
Sat Oct 6 16:33:40 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.8-RC1/dev_c1700.c
File MIME type: text/plain
File size: 22339 byte(s)
dynamips-0.2.8-RC1

1 dpavlin 11 /*
2     * Cisco router simulation platform.
3     * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4     *
5     * Generic Cisco 1700 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_c1700.h"
26     #include "dev_c1700_iofpga.h"
27     #include "dev_vtty.h"
28     #include "registry.h"
29    
30     /* ======================================================================== */
31     /* EEPROM definitions */
32     /* ======================================================================== */
33    
34     /* Cisco 1700 mainboard EEPROM */
35     static m_uint16_t eeprom_c1700_mb_data[] = {
36     0x0101, 0x0404, 0x0000, 0x0000, 0x4320, 0x00FF, 0x00B2, 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 c1700_mb_id {
47     char *name;
48     char *mb_driver;
49     m_uint16_t id;
50     int supported;
51     };
52    
53     struct c1700_mb_id c1700_mainboard_id[] = {
54     { "1710" , "C1710-MB-1FE-1E" , 0x02F6, TRUE },
55     { "1720" , "C1700-MB-1ETH" , 0x00B2, TRUE },
56     { "1721" , "C1700-MB-1ETH" , 0x035A, TRUE },
57     { "1750" , "C1700-MB-1ETH" , 0x00C9, TRUE },
58     { "1751" , "C1700-MB-1ETH" , 0x024D, TRUE },
59     { "1760" , "C1700-MB-1ETH" , 0x0316, TRUE },
60     { NULL , NULL , 0x0000, 0 },
61     };
62    
63     /* ======================================================================== */
64     /* Network Module Drivers */
65     /* ======================================================================== */
66     static struct cisco_card_driver *nm_drivers[] = {
67     &dev_c1700_mb_eth_driver,
68     &dev_c1710_mb_eth_driver,
69     NULL,
70     };
71    
72     /* ======================================================================== */
73     /* Cisco 1700 router instances */
74     /* ======================================================================== */
75    
76     /* Initialize default parameters for a C1700 */
77     static void c1700_init_defaults(c1700_t *router);
78    
79     /* Directly extract the configuration from the NVRAM device */
80     static ssize_t c1700_nvram_extract_config(vm_instance_t *vm,u_char **buffer)
81     {
82     u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;
83     m_uint32_t start,nvlen;
84     m_uint16_t magic1,magic2;
85     struct vdevice *nvram_dev;
86     off_t nvram_size;
87     int fd;
88    
89     if ((nvram_dev = dev_get_by_name(vm,"nvram")))
90     dev_sync(nvram_dev);
91    
92     fd = vm_mmap_open_file(vm,"nvram",&base_ptr,&nvram_size);
93    
94     if (fd == -1)
95     return(-1);
96    
97     ios_ptr = base_ptr + vm->nvram_rom_space;
98     end_ptr = base_ptr + nvram_size;
99    
100     if ((ios_ptr + 0x30) >= end_ptr) {
101     vm_error(vm,"NVRAM file too small\n");
102     return(-1);
103     }
104    
105     magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06));
106     magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08));
107    
108     if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) {
109     vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n",
110     magic1,magic2);
111     return(-1);
112     }
113    
114     start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1;
115     nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18));
116    
117     if (!(*buffer = malloc(nvlen+1))) {
118     vm_error(vm,"unable to allocate config buffer (%u bytes)\n",nvlen);
119     return(-1);
120     }
121    
122     cfg_ptr = ios_ptr + start + 0x08;
123    
124     if ((cfg_ptr + nvlen) > end_ptr) {
125     vm_error(vm,"NVRAM file too small\n");
126     return(-1);
127     }
128    
129     memcpy(*buffer,cfg_ptr,nvlen-1);
130     (*buffer)[nvlen-1] = 0;
131     return(nvlen-1);
132     }
133    
134     /* Directly push the IOS configuration to the NVRAM device */
135     static int c1700_nvram_push_config(vm_instance_t *vm,u_char *buffer,size_t len)
136     {
137     u_char *base_ptr,*ios_ptr,*cfg_ptr;
138     m_uint32_t cfg_offset,cklen,tmp;
139     m_uint16_t cksum;
140     int fd;
141    
142     fd = vm_mmap_create_file(vm,"nvram",vm->nvram_size*1024,&base_ptr);
143    
144     if (fd == -1)
145     return(-1);
146    
147     cfg_offset = 0x2c;
148     ios_ptr = base_ptr + vm->nvram_rom_space;
149     cfg_ptr = ios_ptr + cfg_offset;
150    
151     /* Write IOS tag, uncompressed config... */
152     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5);
153     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD);
154     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001);
155     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000);
156     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0c04);
157    
158     /* Store file contents to NVRAM */
159     memcpy(cfg_ptr,buffer,len);
160    
161     /* Write config addresses + size */
162     tmp = cfg_offset - 0x08;
163    
164     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(tmp);
165     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(tmp + len);
166     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len);
167    
168     /* Compute the checksum */
169     cklen = (vm->nvram_size*1024) - (vm->nvram_rom_space + 0x08);
170     cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen);
171     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum);
172    
173     vm_mmap_close_file(fd,base_ptr,vm->nvram_size*1024);
174     return(0);
175     }
176    
177     /* Create a new router instance */
178     static int c1700_create_instance(vm_instance_t *vm)
179     {
180     c1700_t *router;
181    
182     if (!(router = malloc(sizeof(*router)))) {
183     fprintf(stderr,"C1700 '%s': Unable to create new instance!\n",vm->name);
184     return(-1);
185     }
186    
187     memset(router,0,sizeof(*router));
188     router->vm = vm;
189     vm->hw_data = router;
190    
191     c1700_init_defaults(router);
192     return(0);
193     }
194    
195     /* Free resources used by a router instance */
196     static int c1700_delete_instance(vm_instance_t *vm)
197     {
198     c1700_t *router = VM_C1700(vm);
199     int i;
200    
201     /* Stop all CPUs */
202     if (vm->cpu_group != NULL) {
203     vm_stop(vm);
204    
205     if (cpu_group_sync_state(vm->cpu_group) == -1) {
206     vm_error(vm,"unable to sync with system CPUs.\n");
207     return(FALSE);
208     }
209     }
210    
211     /* Remove NIO bindings */
212     for(i=0;i<vm->nr_slots;i++)
213     vm_slot_remove_all_nio_bindings(vm,i);
214    
215     /* Shutdown all Network Modules */
216     vm_slot_shutdown_all(vm);
217    
218     /* Free mainboard EEPROM */
219     cisco_eeprom_free(&router->mb_eeprom);
220    
221     /* Free all resources used by VM */
222     vm_free(vm);
223    
224     /* Free the router structure */
225     free(router);
226     return(TRUE);
227     }
228    
229     /* Save configuration of a C1700 instance */
230     void c1700_save_config(vm_instance_t *vm,FILE *fd)
231     {
232     c1700_t *router = VM_C1700(vm);
233    
234     fprintf(fd,"c1700 set_chassis %s %s\n\n",vm->name,router->mainboard_type);
235     }
236    
237     /* Set EEPROM for the specified slot */
238     int c1700_set_slot_eeprom(c1700_t *router,u_int slot,
239     struct cisco_eeprom *eeprom)
240     {
241     switch(slot) {
242     case 1:
243     router->nm_eeprom_group.eeprom[0] = eeprom;
244     return(0);
245     default:
246     return(-1);
247     }
248     }
249    
250     /* Get slot/port corresponding to specified network IRQ */
251     static inline void
252     c1700_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port)
253     {
254     irq -= C1700_NETIO_IRQ_BASE;
255     *port = irq & C1700_NETIO_IRQ_PORT_MASK;
256     *slot = irq >> C1700_NETIO_IRQ_PORT_BITS;
257     }
258    
259     /* Get network IRQ for specified slot/port */
260     u_int c1700_net_irq_for_slot_port(u_int slot,u_int port)
261     {
262     u_int irq;
263    
264     irq = (slot << C1700_NETIO_IRQ_PORT_BITS) + port;
265     irq += C1700_NETIO_IRQ_BASE;
266    
267     return(irq);
268     }
269    
270     /* Find Cisco 1700 Mainboard info */
271     static struct c1700_mb_id *c1700_get_mb_info(char *mainboard_type)
272     {
273     int i;
274    
275     for(i=0;c1700_mainboard_id[i].name;i++)
276     if (!strcmp(c1700_mainboard_id[i].name,mainboard_type))
277     return(&c1700_mainboard_id[i]);
278    
279     return NULL;
280     }
281    
282     /* Show all available mainboards */
283     static void c1700_mainboard_show_drivers(void)
284     {
285     int i;
286    
287     printf("Available C1700 chassis drivers:\n");
288    
289     for(i=0;c1700_mainboard_id[i].name;i++)
290     printf(" * %s %s\n",
291     c1700_mainboard_id[i].name,
292     !c1700_mainboard_id[i].supported ? "(NOT WORKING)" : "");
293    
294     printf("\n");
295     }
296    
297     /* Set the base MAC address of the chassis */
298     static int c1700_burn_mac_addr(c1700_t *router,n_eth_addr_t *addr)
299     {
300     int i;
301    
302     for(i=0;i<3;i++) {
303     router->vm->chassis_cookie[i+1] = addr->eth_addr_byte[i*2] << 8;
304     router->vm->chassis_cookie[i+1] |= addr->eth_addr_byte[(i*2)+1];
305     }
306    
307     return(0);
308     }
309    
310     /* Set mainboard type */
311     int c1700_mainboard_set_type(c1700_t *router,char *mainboard_type)
312     {
313     struct c1700_mb_id *mb_info;
314    
315     if (router->vm->status == VM_STATUS_RUNNING) {
316     vm_error(router->vm,"unable to change mainboard type when online.\n");
317     return(-1);
318     }
319    
320     if (!(mb_info = c1700_get_mb_info(mainboard_type))) {
321     vm_error(router->vm,"unknown mainboard '%s'\n",mainboard_type);
322     return(-1);
323     }
324    
325     router->mainboard_type = mainboard_type;
326    
327     /* Set the cookie */
328     memcpy(router->vm->chassis_cookie,
329     eeprom_c1700_mb_data,sizeof(eeprom_c1700_mb_data));
330    
331     router->vm->chassis_cookie[6] = mb_info->id;
332    
333     /* Set the chassis base MAC address */
334     c1700_burn_mac_addr(router,&router->mac_addr);
335    
336     /* Set the mainboard driver */
337     if (vm_slot_active(router->vm,0,0))
338     vm_slot_remove_binding(router->vm,0,0);
339    
340     vm_slot_add_binding(router->vm,mb_info->mb_driver,0,0);
341     return(0);
342     }
343    
344     /* Set chassis MAC address */
345     int c1700_chassis_set_mac_addr(c1700_t *router,char *mac_addr)
346     {
347     if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) {
348     vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr);
349     return(-1);
350     }
351    
352     /* Set the chassis base MAC address */
353     c1700_burn_mac_addr(router,&router->mac_addr);
354     return(0);
355     }
356    
357     /* Initialize a Cisco 1700 */
358     static int c1700_init(c1700_t *router)
359     {
360     vm_instance_t *vm = router->vm;
361    
362     /* Create the PCI bus */
363     if (!(vm->pci_bus[0] = pci_bus_create("PCI0",0))) {
364     vm_error(vm,"unable to create PCI data.\n");
365     return(-1);
366     }
367    
368     /* Bind PCI bus to slots 0 and 1 */
369     vm->slots_pci_bus[0] = vm->pci_bus[0];
370     vm->slots_pci_bus[1] = vm->pci_bus[0];
371    
372     vm->elf_machine_id = C1700_ELF_MACHINE_ID;
373     return(0);
374     }
375    
376     /* Show C1700 hardware info */
377     void c1700_show_hardware(c1700_t *router)
378     {
379     vm_instance_t *vm = router->vm;
380    
381     printf("C1700 instance '%s' (id %d):\n",vm->name,vm->instance_id);
382    
383     printf(" VM Status : %d\n",vm->status);
384     printf(" RAM size : %u Mb\n",vm->ram_size);
385     printf(" NVRAM size : %u Kb\n",vm->nvram_size);
386     printf(" IOS image : %s\n\n",vm->ios_image);
387    
388     if (vm->debug_level > 0) {
389     dev_show_list(vm);
390     pci_dev_show_list(vm->pci_bus[0]);
391     pci_dev_show_list(vm->pci_bus[1]);
392     printf("\n");
393     }
394     }
395    
396     /* Initialize default parameters for a C1700 */
397     static void c1700_init_defaults(c1700_t *router)
398     {
399     vm_instance_t *vm = router->vm;
400     n_eth_addr_t *m;
401     m_uint16_t pid;
402    
403     /* Set platform slots characteristics */
404     vm->nr_slots = C1700_MAX_NM_BAYS;
405     vm->slots_type = CISCO_CARD_TYPE_NM;
406     vm->slots_drivers = nm_drivers;
407    
408     pid = (m_uint16_t)getpid();
409    
410     /* Generate a chassis MAC address based on the instance ID */
411     m = &router->mac_addr;
412     m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
413     m->eth_addr_byte[1] = vm->instance_id & 0xFF;
414     m->eth_addr_byte[2] = pid >> 8;
415     m->eth_addr_byte[3] = pid & 0xFF;
416     m->eth_addr_byte[4] = 0x00;
417     m->eth_addr_byte[5] = 0x00;
418    
419     c1700_init_eeprom_groups(router);
420     c1700_mainboard_set_type(router,C1700_DEFAULT_MAINBOARD);
421     c1700_burn_mac_addr(router,&router->mac_addr);
422    
423     vm->ram_mmap = C1700_DEFAULT_RAM_MMAP;
424     vm->ram_size = C1700_DEFAULT_RAM_SIZE;
425     vm->rom_size = C1700_DEFAULT_ROM_SIZE;
426     vm->nvram_size = C1700_DEFAULT_NVRAM_SIZE;
427     vm->conf_reg_setup = C1700_DEFAULT_CONF_REG;
428     vm->clock_divisor = C1700_DEFAULT_CLOCK_DIV;
429     vm->nvram_rom_space = C1700_NVRAM_ROM_RES_SIZE;
430     vm->nm_iomem_size = C1700_DEFAULT_IOMEM_SIZE;
431    
432     vm->pcmcia_disk_size[0] = C1700_DEFAULT_DISK0_SIZE;
433     vm->pcmcia_disk_size[1] = C1700_DEFAULT_DISK1_SIZE;
434     }
435    
436     /* Set an IRQ */
437     static void c1700_set_irq(vm_instance_t *vm,u_int irq)
438     {
439     c1700_t *router = VM_C1700(vm);
440     cpu_ppc_t *cpu = CPU_PPC32(vm->boot_cpu);
441     u_int slot,port;
442    
443     switch(irq) {
444     case C1700_VTIMER_IRQ:
445     mpc860_set_pending_irq(router->mpc_data,30);
446     break;
447     case C1700_DUART_IRQ:
448     mpc860_set_pending_irq(router->mpc_data,29);
449     break;
450     case C1700_NETIO_IRQ:
451     mpc860_set_pending_irq(router->mpc_data,25);
452     break;
453     case C1700_PA_MGMT_IRQ:
454     mpc860_set_pending_irq(router->mpc_data,27);
455     break;
456    
457     case C1700_NETIO_IRQ_BASE ... C1700_NETIO_IRQ_END:
458     c1700_net_irq_get_slot_port(irq,&slot,&port);
459     dev_c1700_iofpga_net_set_irq(router->iofpga_data,slot,port);
460     break;
461    
462     /* IRQ test */
463     case 255:
464     mpc860_set_pending_irq(router->mpc_data,24);
465     break;
466     }
467    
468     if (vm->irq_idle_preempt[irq])
469     cpu_idle_break_wait(cpu->gen);
470     }
471    
472     /* Clear an IRQ */
473     static void c1700_clear_irq(vm_instance_t *vm,u_int irq)
474     {
475     c1700_t *router = VM_C1700(vm);
476     u_int slot,port;
477    
478     switch(irq) {
479     case C1700_VTIMER_IRQ:
480     mpc860_clear_pending_irq(router->mpc_data,30);
481     break;
482     case C1700_DUART_IRQ:
483     mpc860_clear_pending_irq(router->mpc_data,29);
484     break;
485     case C1700_NETIO_IRQ:
486     mpc860_clear_pending_irq(router->mpc_data,25);
487     break;
488     case C1700_PA_MGMT_IRQ:
489     mpc860_clear_pending_irq(router->mpc_data,27);
490     break;
491    
492     case C1700_NETIO_IRQ_BASE ... C1700_NETIO_IRQ_END:
493     c1700_net_irq_get_slot_port(irq,&slot,&port);
494     dev_c1700_iofpga_net_clear_irq(router->iofpga_data,slot,port);
495     break;
496    
497     /* IRQ test */
498     case 255:
499     mpc860_clear_pending_irq(router->mpc_data,24);
500     break;
501     }
502     }
503    
504     /* Initialize the C1700 Platform */
505     static int c1700_init_platform(c1700_t *router)
506     {
507     vm_instance_t *vm = router->vm;
508     vm_obj_t *obj;
509     cpu_ppc_t *cpu;
510     cpu_gen_t *gen;
511    
512     /* Copy config register setup into "active" config register */
513     vm->conf_reg = vm->conf_reg_setup;
514    
515     /* Create Console and AUX ports */
516     vm_init_vtty(vm);
517    
518     /* Create a CPU group */
519     vm->cpu_group = cpu_group_create("System CPU");
520    
521     /* Initialize the virtual PowerPC processor */
522     if (!(gen = cpu_create(vm,CPU_TYPE_PPC32,0))) {
523     vm_error(vm,"unable to create CPU!\n");
524     return(-1);
525     }
526    
527     cpu = CPU_PPC32(gen);
528    
529     /* Add this CPU to the system CPU group */
530     cpu_group_add(vm->cpu_group,gen);
531     vm->boot_cpu = gen;
532    
533     /* Set processor ID */
534     ppc32_set_pvr(cpu,0x00500202);
535    
536     /* Mark the Network IO interrupt as high priority */
537     vm->irq_idle_preempt[C1700_NETIO_IRQ] = TRUE;
538     vm->irq_idle_preempt[C1700_DUART_IRQ] = TRUE;
539    
540     /* Copy some parameters from VM to CPU (idle PC, ...) */
541     cpu->idle_pc = vm->idle_pc;
542    
543     if (vm->timer_irq_check_itv)
544     cpu->timer_irq_check_itv = vm->timer_irq_check_itv;
545    
546     /* Remote emulator control */
547     dev_remote_control_init(vm,0xf6000000,0x1000);
548    
549     /* MPC860 */
550     cpu->mpc860_immr = C1700_MPC860_ADDR;
551    
552     if (dev_mpc860_init(vm,"MPC860",C1700_MPC860_ADDR,0x10000) == -1)
553     return(-1);
554    
555     if (!(obj = vm_object_find(router->vm,"MPC860")))
556     return(-1);
557    
558     router->mpc_data = obj->data;
559    
560     /* IO FPGA */
561     if (dev_c1700_iofpga_init(router,C1700_IOFPGA_ADDR,0x10000) == -1)
562     return(-1);
563    
564     if (!(obj = vm_object_find(router->vm,"io_fpga")))
565     return(-1);
566    
567     router->iofpga_data = obj->data;
568    
569     /* Initialize the chassis */
570     if (c1700_init(router) == -1)
571     return(-1);
572    
573     /* Initialize RAM */
574     vm_ram_init(vm,0x00000000ULL);
575    
576     /* Initialize ROM */
577     if (!vm->rom_filename) {
578     /* use embedded ROM */
579     dev_rom_init(vm,"rom",C1700_ROM_ADDR,512*1024,
580     ppc32_microcode,ppc32_microcode_len);
581     } else {
582     /* use alternate ROM */
583     dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE,C1700_ROM_ADDR,512*1024);
584     }
585    
586     /* RAM aliasing */
587     dev_create_ram_alias(vm,"ram_alias","ram",0x80000000,vm->ram_size*1048576);
588    
589     /* NVRAM */
590     dev_nvram_init(vm,"nvram",
591     C1700_NVRAM_ADDR,vm->nvram_size*1024,&vm->conf_reg);
592    
593    
594     /* Bootflash (4 Mb) */
595     dev_bootflash_init(vm,"bootflash","c1700-bootflash-4mb",C1700_FLASH_ADDR);
596    
597     /* Initialize the NS16552 DUART */
598     dev_ns16552_init(vm,C1700_DUART_ADDR,0x1000,0,C1700_DUART_IRQ,
599     vm->vtty_con,vm->vtty_aux);
600    
601     /* Initialize Network Modules */
602     if (vm_slot_init_all(vm) == -1)
603     return(-1);
604    
605     /* Show device list */
606     c1700_show_hardware(router);
607     return(0);
608     }
609    
610     static struct ppc32_bat_prog bat_array[] = {
611     { PPC32_IBAT_IDX, 0, 0xfff0001e, 0xfff00001 },
612     { PPC32_IBAT_IDX, 1, 0x00001ffe, 0x00000001 },
613     { PPC32_IBAT_IDX, 2, 0x00000000, 0xee3e0072 },
614     { PPC32_IBAT_IDX, 3, 0x80001ffe, 0x00000001 },
615    
616     { PPC32_DBAT_IDX, 0, 0x80001ffe, 0x00000042 },
617     { PPC32_DBAT_IDX, 1, 0x00001ffe, 0x0000002a },
618     { PPC32_DBAT_IDX, 2, 0x40007ffe, 0x4000002a },
619     { PPC32_DBAT_IDX, 3, 0xf0001ffe, 0xf000002a },
620     { -1, -1, 0, 0 },
621     };
622    
623     /* Boot the IOS image */
624     static int c1700_boot_ios(c1700_t *router)
625     {
626     vm_instance_t *vm = router->vm;
627     cpu_ppc_t *cpu;
628    
629     if (!vm->boot_cpu)
630     return(-1);
631    
632     /* Suspend CPU activity since we will restart directly from ROM */
633     vm_suspend(vm);
634    
635     /* Check that CPU activity is really suspended */
636     if (cpu_group_sync_state(vm->cpu_group) == -1) {
637     vm_error(vm,"unable to sync with system CPUs.\n");
638     return(-1);
639     }
640    
641     /* Reset the boot CPU */
642     cpu = CPU_PPC32(vm->boot_cpu);
643     ppc32_reset(cpu);
644    
645     /* Adjust stack pointer */
646     cpu->gpr[1] |= 0x80000000;
647    
648     /* Load BAT registers */
649     printf("Loading BAT registers\n");
650     ppc32_load_bat_array(cpu,bat_array);
651     cpu->msr |= PPC32_MSR_IR|PPC32_MSR_DR;
652    
653     /* IRQ routing */
654     vm->set_irq = c1700_set_irq;
655     vm->clear_irq = c1700_clear_irq;
656    
657     /* Load IOS image */
658     if (ppc32_load_elf_image(cpu,vm->ios_image,
659     (vm->ghost_status == VM_GHOST_RAM_USE),
660     &vm->ios_entry_point) < 0)
661     {
662     vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
663     return(-1);
664     }
665    
666     /* Launch the simulation */
667     printf("\nC1700 '%s': starting simulation (CPU0 IA=0x%8.8x), "
668     "JIT %sabled.\n",
669     vm->name,cpu->ia,vm->jit_use ? "en":"dis");
670    
671     vm_log(vm,"C1700_BOOT",
672     "starting instance (CPU0 PC=0x%8.8x,idle_pc=0x%8.8x,JIT %s)\n",
673     cpu->ia,cpu->idle_pc,vm->jit_use ? "on":"off");
674    
675     /* Start main CPU */
676     if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
677     vm->status = VM_STATUS_RUNNING;
678     cpu_start(vm->boot_cpu);
679     } else {
680     vm->status = VM_STATUS_SHUTDOWN;
681     }
682     return(0);
683     }
684    
685     /* Initialize a Cisco 1700 instance */
686     static int c1700_init_instance(vm_instance_t *vm)
687     {
688     c1700_t *router = VM_C1700(vm);
689     m_uint32_t rom_entry_point;
690     cpu_ppc_t *cpu0;
691    
692     if (!vm->ios_image) {
693     vm_error(vm,"no Cisco IOS image defined.");
694     return(-1);
695     }
696    
697     /* Initialize the C1700 platform */
698     if (c1700_init_platform(router) == -1) {
699     vm_error(vm,"unable to initialize the platform hardware.\n");
700     return(-1);
701     }
702    
703     /* Load IOS configuration file */
704     if (vm->ios_config != NULL) {
705     vm_nvram_push_config(vm,vm->ios_config);
706     vm->conf_reg &= ~0x40;
707     }
708    
709     /* Load ROM (ELF image or embedded) */
710     cpu0 = CPU_PPC32(vm->boot_cpu);
711     rom_entry_point = (m_uint32_t)PPC32_ROM_START;
712    
713     if ((vm->rom_filename != NULL) &&
714     (ppc32_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
715     {
716     vm_error(vm,"unable to load alternate ROM '%s', "
717     "fallback to embedded ROM.\n\n",vm->rom_filename);
718     vm->rom_filename = NULL;
719     }
720    
721     return(c1700_boot_ios(router));
722     }
723    
724     /* Stop a Cisco 1700 instance */
725     static int c1700_stop_instance(vm_instance_t *vm)
726     {
727     printf("\nC1700 '%s': stopping simulation.\n",vm->name);
728     vm_log(vm,"C1700_STOP","stopping simulation.\n");
729    
730     /* Stop all CPUs */
731     if (vm->cpu_group != NULL) {
732     vm_stop(vm);
733    
734     if (cpu_group_sync_state(vm->cpu_group) == -1) {
735     vm_error(vm,"unable to sync with system CPUs.\n");
736     return(-1);
737     }
738     }
739    
740     /* Free resources that were used during execution to emulate hardware */
741     vm_slot_shutdown_all(vm);
742     vm_hardware_shutdown(vm);
743     return(0);
744     }
745    
746     /* Get MAC address MSB */
747     static u_int c1700_get_mac_addr_msb(void)
748     {
749     return(0xD0);
750     }
751    
752     /* Parse specific options for the Cisco 1700 platform */
753     static int c1700_cli_parse_options(vm_instance_t *vm,int option)
754     {
755     c1700_t *router = VM_C1700(vm);
756    
757     switch(option) {
758     /* IO memory reserved for NMs (in percents!) */
759     case OPT_IOMEM_SIZE:
760     vm->nm_iomem_size = 0x8000 | atoi(optarg);
761     break;
762    
763     /* Mainboard type */
764     case 't':
765     c1700_mainboard_set_type(router,optarg);
766     break;
767    
768     /* Unknown option */
769     default:
770     return(-1);
771     }
772    
773     return(0);
774     }
775    
776     /* Show specific CLI options */
777     static void c1700_cli_show_options(vm_instance_t *vm)
778     {
779     printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n"
780     " -t <chassis_type> : Select Chassis type\n"
781     " -p <wic_desc> : Define a WIC Module\n"
782     " -s <wic_nio> : Bind a Network IO interface to a WIC\n",
783     vm->nm_iomem_size);
784     }
785    
786     /* Platform definition */
787     static vm_platform_t c1700_platform = {
788     "c1700", "C1700", "1700",
789     c1700_create_instance,
790     c1700_delete_instance,
791     c1700_init_instance,
792     c1700_stop_instance,
793     c1700_nvram_extract_config,
794     c1700_nvram_push_config,
795     c1700_get_mac_addr_msb,
796     c1700_save_config,
797     c1700_cli_parse_options,
798     c1700_cli_show_options,
799     c1700_mainboard_show_drivers,
800     };
801    
802     /* Register the c1700 platform */
803     int c1700_platform_register(void)
804     {
805     if (vm_platform_register(&c1700_platform) == -1)
806     return(-1);
807    
808     return(hypervisor_c1700_init(&c1700_platform));
809     }

  ViewVC Help
Powered by ViewVC 1.1.26