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

Annotation of /trunk/dev_c3725.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 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: 21691 byte(s)
make working copy

1 dpavlin 4 /*
2 dpavlin 8 * Cisco router simulation platform.
3 dpavlin 4 * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4     *
5     * Generic Cisco 3725 routines and definitions (EEPROM,...).
6     */
7    
8     #include <stdio.h>
9     #include <stdlib.h>
10     #include <string.h>
11     #include <unistd.h>
12     #include <sys/types.h>
13     #include <assert.h>
14    
15 dpavlin 7 #include "cpu.h"
16     #include "vm.h"
17 dpavlin 4 #include "dynamips.h"
18     #include "memory.h"
19     #include "device.h"
20     #include "pci_io.h"
21     #include "dev_gt.h"
22     #include "cisco_eeprom.h"
23 dpavlin 7 #include "dev_rom.h"
24 dpavlin 4 #include "dev_c3725.h"
25 dpavlin 8 #include "dev_c3725_iofpga.h"
26 dpavlin 4 #include "dev_vtty.h"
27     #include "registry.h"
28    
29     /* ======================================================================== */
30     /* EEPROM definitions */
31     /* ======================================================================== */
32    
33     /* Cisco 3725 mainboard EEPROM */
34     static m_uint16_t eeprom_c3725_mainboard_data[] = {
35     0x04FF, 0xC18B, 0x5858, 0x5858, 0x5858, 0x5858, 0x5858, 0x5809,
36     0x6140, 0x0259, 0xC046, 0x0320, 0x003F, 0x1302, 0x4244, 0x3085,
37     0x1C10, 0x8206, 0x80FF, 0xFFFF, 0xFFC4, 0x08FF, 0xFFFF, 0xFFFF,
38     0xFFFF, 0xFF81, 0xFFFF, 0xFFFF, 0x03FF, 0x04FF, 0xC28B, 0x5858,
39     0x5858, 0x5858, 0x5858, 0x5858, 0x58C3, 0x0600, 0x1319, 0x5C6F,
40     0x7043, 0x0030, 0xC508, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x4100,
41     0x0101, 0x02FF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
42     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
43     };
44    
45     struct cisco_eeprom eeprom_c3725_mainboard = {
46     "C3725 Backplane",
47     eeprom_c3725_mainboard_data,
48     sizeof(eeprom_c3725_mainboard_data)/2,
49     };
50    
51     /* ======================================================================== */
52     /* Network Module Drivers */
53     /* ======================================================================== */
54 dpavlin 11 static struct cisco_card_driver *nm_drivers[] = {
55 dpavlin 4 &dev_c3725_nm_1fe_tx_driver,
56     &dev_c3725_nm_16esw_driver,
57     &dev_c3725_gt96100_fe_driver,
58     &dev_c3725_nm_4t_driver,
59 dpavlin 11 &dev_c3725_nm_nam_driver,
60     &dev_c3725_nm_cids_driver,
61 dpavlin 4 NULL,
62     };
63    
64     /* ======================================================================== */
65     /* Cisco 3725 router instances */
66     /* ======================================================================== */
67    
68 dpavlin 11 /* Initialize default parameters for a C3725 */
69     static void c3725_init_defaults(c3725_t *router);
70    
71 dpavlin 4 /* Directly extract the configuration from the NVRAM device */
72 dpavlin 11 static ssize_t c3725_nvram_extract_config(vm_instance_t *vm,u_char **buffer)
73 dpavlin 4 {
74     u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;
75     m_uint32_t start,nvlen;
76     m_uint16_t magic1,magic2;
77     struct vdevice *nvram_dev;
78     off_t nvram_size;
79     int fd;
80    
81     if ((nvram_dev = dev_get_by_name(vm,"rom")))
82     dev_sync(nvram_dev);
83    
84     fd = vm_mmap_open_file(vm,"rom",&base_ptr,&nvram_size);
85    
86     if (fd == -1)
87     return(-1);
88    
89     ios_ptr = base_ptr + C3725_NVRAM_OFFSET;
90     end_ptr = base_ptr + nvram_size;
91    
92     if ((ios_ptr + 0x30) >= end_ptr) {
93     vm_error(vm,"NVRAM file too small\n");
94     return(-1);
95     }
96    
97     magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06));
98     magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08));
99    
100     if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) {
101     vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n",
102     magic1,magic2);
103     return(-1);
104     }
105    
106     start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1;
107     nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18));
108    
109     if (!(*buffer = malloc(nvlen+1))) {
110     vm_error(vm,"unable to allocate config buffer (%u bytes)\n",nvlen);
111     return(-1);
112     }
113    
114     cfg_ptr = ios_ptr + start + 0x08;
115    
116     if ((cfg_ptr + nvlen) > end_ptr) {
117     vm_error(vm,"NVRAM file too small\n");
118     return(-1);
119     }
120    
121     memcpy(*buffer,cfg_ptr,nvlen-1);
122     (*buffer)[nvlen-1] = 0;
123     return(nvlen-1);
124     }
125    
126     static int c3725_nvram_push_config_part(vm_instance_t *vm,
127 dpavlin 11 u_char *buffer,size_t len,
128 dpavlin 4 u_char *ios_ptr)
129     {
130     m_uint32_t cfg_offset,cklen,tmp;
131     m_uint16_t cksum;
132     u_char *cfg_ptr;
133    
134     cfg_offset = 0x2c;
135     cfg_ptr = ios_ptr + cfg_offset;
136    
137     /* Write IOS tag, uncompressed config... */
138     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5);
139     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD);
140     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001);
141     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000);
142     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0c04);
143    
144     /* Store file contents to NVRAM */
145     memcpy(cfg_ptr,buffer,len);
146    
147     /* Write config addresses + size */
148     tmp = cfg_offset - 0x08;
149    
150     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(tmp);
151     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(tmp + len);
152     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len);
153    
154     /* Compute the checksum */
155     cklen = C3725_NVRAM_SIZE - 0x08;
156     cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen);
157     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum);
158     return(0);
159     }
160    
161     /* Directly push the IOS configuration to the NVRAM device */
162 dpavlin 11 int c3725_nvram_push_config(vm_instance_t *vm,u_char *buffer,size_t len)
163 dpavlin 4 {
164     u_char *base_ptr,*ios_ptr;
165     int fd;
166    
167     fd = vm_mmap_create_file(vm,"rom",vm->rom_size*1048576,&base_ptr);
168    
169     if (fd == -1)
170     return(-1);
171    
172     ios_ptr = base_ptr + C3725_NVRAM_OFFSET;
173    
174     /* Normal config */
175     c3725_nvram_push_config_part(vm,buffer,len,ios_ptr);
176    
177     /* Backup config */
178     c3725_nvram_push_config_part(vm,buffer,len,ios_ptr + C3725_NVRAM_SIZE);
179    
180     vm_mmap_close_file(fd,base_ptr,vm->rom_size*1048576);
181     return(0);
182     }
183    
184     /* Check for empty config */
185 dpavlin 11 static int c3725_nvram_check_empty_config(vm_instance_t *vm)
186 dpavlin 4 {
187     struct vdevice *rom_dev;
188     m_uint64_t addr;
189     size_t len;
190    
191     if (!(rom_dev = dev_get_by_name(vm,"rom")))
192     return(-1);
193    
194     addr = rom_dev->phys_addr + C3725_NVRAM_OFFSET;
195     len = C3725_NVRAM_SIZE;
196    
197     while(len > 0) {
198     if (physmem_copy_u32_from_vm(vm,addr) != 0)
199     return(0);
200    
201     addr += sizeof(m_uint32_t);
202     len -= sizeof(m_uint32_t);
203     }
204    
205     /* Empty NVRAM */
206     vm->conf_reg |= 0x0040;
207     printf("NVRAM is empty, setting config register to 0x%x\n",vm->conf_reg);
208     return(0);
209     }
210    
211     /* Create a new router instance */
212 dpavlin 11 static int c3725_create_instance(vm_instance_t *vm)
213 dpavlin 4 {
214     c3725_t *router;
215    
216     if (!(router = malloc(sizeof(*router)))) {
217 dpavlin 11 fprintf(stderr,"C3725 '%s': Unable to create new instance!\n",vm->name);
218     return(-1);
219 dpavlin 4 }
220    
221     memset(router,0,sizeof(*router));
222 dpavlin 11 router->vm = vm;
223     vm->hw_data = router;
224 dpavlin 4
225     c3725_init_defaults(router);
226 dpavlin 11 return(0);
227 dpavlin 4 }
228    
229     /* Free resources used by a router instance */
230 dpavlin 11 static int c3725_delete_instance(vm_instance_t *vm)
231 dpavlin 4 {
232 dpavlin 11 c3725_t *router = VM_C3725(vm);
233 dpavlin 4 int i;
234    
235 dpavlin 11 /* Stop all CPUs */
236     if (vm->cpu_group != NULL) {
237     vm_stop(vm);
238 dpavlin 4
239 dpavlin 11 if (cpu_group_sync_state(vm->cpu_group) == -1) {
240     vm_error(vm,"unable to sync with system CPUs.\n");
241     return(FALSE);
242 dpavlin 4 }
243 dpavlin 11 }
244 dpavlin 4
245 dpavlin 11 /* Remove NIO bindings */
246     for(i=0;i<vm->nr_slots;i++)
247     vm_slot_remove_all_nio_bindings(vm,i);
248 dpavlin 4
249 dpavlin 11 /* Shutdown all Network Modules */
250     vm_slot_shutdown_all(vm);
251 dpavlin 4
252 dpavlin 11 /* Free mainboard EEPROM */
253     cisco_eeprom_free(&router->mb_eeprom);
254 dpavlin 4
255 dpavlin 11 /* Free all resources used by VM */
256     vm_free(vm);
257 dpavlin 4
258 dpavlin 11 /* Free the router structure */
259     free(router);
260     return(TRUE);
261 dpavlin 4 }
262    
263 dpavlin 11 /* Get WIC device address for the specified onboard port */
264     int c3725_get_onboard_wic_addr(u_int slot,m_uint64_t *phys_addr)
265 dpavlin 4 {
266 dpavlin 11 if (slot >= C3725_MAX_WIC_BAYS)
267     return(-1);
268 dpavlin 4
269 dpavlin 11 *phys_addr = C3725_WIC_ADDR + (slot * C3725_WIC_SIZE);
270     return(0);
271 dpavlin 4 }
272    
273 dpavlin 11 /* Set EEPROM for the specified slot */
274     int c3725_set_slot_eeprom(c3725_t *router,u_int slot,
275     struct cisco_eeprom *eeprom)
276 dpavlin 4 {
277 dpavlin 11 if ((slot < 1) || (slot >= C3725_MAX_NM_BAYS))
278     return(-1);
279 dpavlin 4
280 dpavlin 11 router->nm_eeprom_group[slot-1].eeprom[0] = eeprom;
281     return(0);
282 dpavlin 4 }
283    
284 dpavlin 8 /* Get slot/port corresponding to specified network IRQ */
285     static inline void
286     c3725_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port)
287     {
288     irq -= C3725_NETIO_IRQ_BASE;
289     *port = irq & C3725_NETIO_IRQ_PORT_MASK;
290     *slot = irq >> C3725_NETIO_IRQ_PORT_BITS;
291     }
292    
293     /* Get network IRQ for specified slot/port */
294     u_int c3725_net_irq_for_slot_port(u_int slot,u_int port)
295     {
296     u_int irq;
297    
298     irq = (slot << C3725_NETIO_IRQ_PORT_BITS) + port;
299     irq += C3725_NETIO_IRQ_BASE;
300    
301     return(irq);
302     }
303    
304 dpavlin 4 /* Get PCI device for the specified NM bay */
305     int c3725_nm_get_pci_device(u_int nm_bay)
306     {
307     switch(nm_bay) {
308     case 1:
309     return(0x06);
310     case 2:
311     return(0x0A);
312     default:
313     return(-1);
314     }
315     }
316    
317     /* Set the base MAC address of the chassis */
318     static int c3725_burn_mac_addr(c3725_t *router,n_eth_addr_t *addr)
319     {
320     m_uint8_t eeprom_ver;
321     size_t offset;
322    
323     /* Read EEPROM format version */
324     cisco_eeprom_get_byte(&router->mb_eeprom,0,&eeprom_ver);
325    
326     switch(eeprom_ver) {
327     case 0:
328     cisco_eeprom_set_region(&router->mb_eeprom,2,addr->eth_addr_byte,6);
329     break;
330    
331     case 4:
332     if (!cisco_eeprom_v4_find_field(&router->mb_eeprom,0xC3,&offset)) {
333     cisco_eeprom_set_region(&router->mb_eeprom,offset,
334     addr->eth_addr_byte,6);
335     }
336     break;
337    
338     default:
339     vm_error(router->vm,"c3725_burn_mac_addr: unable to handle "
340     "EEPROM version %u\n",eeprom_ver);
341     return(-1);
342     }
343    
344     return(0);
345     }
346    
347     /* Set chassis MAC address */
348     int c3725_chassis_set_mac_addr(c3725_t *router,char *mac_addr)
349     {
350     if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) {
351     vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr);
352     return(-1);
353     }
354    
355     /* Set the chassis base MAC address */
356     c3725_burn_mac_addr(router,&router->mac_addr);
357     return(0);
358     }
359    
360     /* Create the two main PCI busses for a GT64120 based system */
361     static int c3725_init_gt96100(c3725_t *router)
362     {
363     vm_instance_t *vm = router->vm;
364 dpavlin 11 vm_obj_t *obj;
365 dpavlin 4
366     vm->pci_bus[0] = pci_bus_create("PCI bus #0",0);
367     vm->pci_bus[1] = pci_bus_create("PCI bus #1",0);
368    
369     if (!vm->pci_bus[0] || !vm->pci_bus[1]) {
370     vm_error(router->vm,"unable to create PCI data.\n");
371     return(-1);
372     }
373    
374 dpavlin 11 if (dev_gt96100_init(vm,"gt96100",C3725_GT96K_ADDR,0x200000,
375     C3725_GT96K_IRQ,
376     C3725_EXT_IRQ,
377     c3725_net_irq_for_slot_port(0,0),
378     255) == -1)
379     return(-1);
380    
381     if (!(obj = vm_object_find(router->vm,"gt96100")))
382     return(-1);
383    
384     router->gt_data = obj->data;
385     return(0);
386 dpavlin 4 }
387    
388     /* Initialize a Cisco 3725 */
389     static int c3725_init(c3725_t *router)
390     {
391     vm_instance_t *vm = router->vm;
392    
393     /* Set the processor type: R7000 */
394 dpavlin 7 mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R7000);
395 dpavlin 4
396     /* Initialize the Galileo GT-96100 PCI controller */
397     if (c3725_init_gt96100(router) == -1)
398     return(-1);
399    
400 dpavlin 11 /* Initialize PCI map (NM slots 1 & 2) */
401     vm->slots_pci_bus[1] = vm->pci_bus[1];
402     vm->slots_pci_bus[2] = vm->pci_bus[1];
403 dpavlin 4
404     vm->elf_machine_id = C3725_ELF_MACHINE_ID;
405     return(0);
406     }
407    
408     /* Show C3725 hardware info */
409     void c3725_show_hardware(c3725_t *router)
410     {
411     vm_instance_t *vm = router->vm;
412    
413     printf("C3725 instance '%s' (id %d):\n",vm->name,vm->instance_id);
414    
415     printf(" VM Status : %d\n",vm->status);
416     printf(" RAM size : %u Mb\n",vm->ram_size);
417     printf(" NVRAM size : %u Kb\n",vm->nvram_size);
418     printf(" IOS image : %s\n\n",vm->ios_image);
419    
420     if (vm->debug_level > 0) {
421     dev_show_list(vm);
422     pci_dev_show_list(vm->pci_bus[0]);
423     pci_dev_show_list(vm->pci_bus[1]);
424     printf("\n");
425     }
426     }
427    
428     /* Initialize default parameters for a C3725 */
429 dpavlin 11 static void c3725_init_defaults(c3725_t *router)
430 dpavlin 4 {
431     vm_instance_t *vm = router->vm;
432     n_eth_addr_t *m;
433     m_uint16_t pid;
434    
435 dpavlin 11 /* Set platform slots characteristics */
436     vm->nr_slots = C3725_MAX_NM_BAYS;
437     vm->slots_type = CISCO_CARD_TYPE_NM;
438     vm->slots_drivers = nm_drivers;
439    
440 dpavlin 4 pid = (m_uint16_t)getpid();
441    
442     /* Generate a chassis MAC address based on the instance ID */
443     m = &router->mac_addr;
444     m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
445     m->eth_addr_byte[1] = vm->instance_id & 0xFF;
446     m->eth_addr_byte[2] = pid >> 8;
447     m->eth_addr_byte[3] = pid & 0xFF;
448     m->eth_addr_byte[4] = 0x00;
449     m->eth_addr_byte[5] = 0x00;
450    
451     c3725_init_eeprom_groups(router);
452     cisco_eeprom_copy(&router->mb_eeprom,&eeprom_c3725_mainboard);
453     c3725_burn_mac_addr(router,&router->mac_addr);
454    
455 dpavlin 11 /* The GT96100 system controller has 2 integrated FastEthernet ports */
456     vm_slot_add_binding(vm,"GT96100-FE",0,0);
457    
458 dpavlin 4 vm->ram_mmap = C3725_DEFAULT_RAM_MMAP;
459     vm->ram_size = C3725_DEFAULT_RAM_SIZE;
460     vm->rom_size = C3725_DEFAULT_ROM_SIZE;
461     vm->nvram_size = C3725_DEFAULT_NVRAM_SIZE;
462     vm->conf_reg_setup = C3725_DEFAULT_CONF_REG;
463     vm->clock_divisor = C3725_DEFAULT_CLOCK_DIV;
464     vm->nvram_rom_space = C3725_NVRAM_ROM_RES_SIZE;
465 dpavlin 11 vm->nm_iomem_size = C3725_DEFAULT_IOMEM_SIZE;
466 dpavlin 4
467     vm->pcmcia_disk_size[0] = C3725_DEFAULT_DISK0_SIZE;
468     vm->pcmcia_disk_size[1] = C3725_DEFAULT_DISK1_SIZE;
469     }
470    
471     /* Initialize the C3725 Platform */
472 dpavlin 11 static int c3725_init_platform(c3725_t *router)
473 dpavlin 4 {
474     vm_instance_t *vm = router->vm;
475     cpu_mips_t *cpu;
476 dpavlin 7 cpu_gen_t *gen;
477 dpavlin 4 vm_obj_t *obj;
478    
479     /* Copy config register setup into "active" config register */
480     vm->conf_reg = vm->conf_reg_setup;
481    
482     /* Create Console and AUX ports */
483     vm_init_vtty(vm);
484    
485     /* Create a CPU group */
486     vm->cpu_group = cpu_group_create("System CPU");
487    
488     /* Initialize the virtual MIPS processor */
489 dpavlin 7 if (!(gen = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
490 dpavlin 4 vm_error(vm,"unable to create CPU!\n");
491     return(-1);
492     }
493    
494 dpavlin 7 cpu = CPU_MIPS64(gen);
495    
496 dpavlin 4 /* Add this CPU to the system CPU group */
497 dpavlin 7 cpu_group_add(vm->cpu_group,gen);
498     vm->boot_cpu = gen;
499 dpavlin 4
500 dpavlin 7 /* Initialize the IRQ routing vectors */
501     vm->set_irq = mips64_vm_set_irq;
502     vm->clear_irq = mips64_vm_clear_irq;
503    
504 dpavlin 4 /* Mark the Network IO interrupt as high priority */
505     cpu->irq_idle_preempt[C3725_NETIO_IRQ] = TRUE;
506     cpu->irq_idle_preempt[C3725_GT96K_IRQ] = TRUE;
507     cpu->irq_idle_preempt[C3725_DUART_IRQ] = TRUE;
508    
509     /* Copy some parameters from VM to CPU (idle PC, ...) */
510     cpu->idle_pc = vm->idle_pc;
511    
512     if (vm->timer_irq_check_itv)
513     cpu->timer_irq_check_itv = vm->timer_irq_check_itv;
514    
515     /* Remote emulator control */
516     dev_remote_control_init(vm,0x16000000,0x1000);
517    
518     /* Specific Storage Area (SSA) */
519 dpavlin 7 dev_ram_init(vm,"ssa",TRUE,FALSE,NULL,FALSE,0x16001000ULL,0x7000);
520 dpavlin 4
521     /* IO FPGA */
522     if (dev_c3725_iofpga_init(router,C3725_IOFPGA_ADDR,0x40000) == -1)
523     return(-1);
524    
525 dpavlin 8 if (!(obj = vm_object_find(router->vm,"io_fpga")))
526     return(-1);
527    
528     router->iofpga_data = obj->data;
529    
530 dpavlin 4 #if 0
531     /* PCI IO space */
532     if (!(vm->pci_io_space = pci_io_data_init(vm,C3725_PCI_IO_ADDR)))
533     return(-1);
534     #endif
535    
536     /* Initialize the chassis */
537     if (c3725_init(router) == -1)
538     return(-1);
539    
540     /* Initialize RAM */
541     vm_ram_init(vm,0x00000000ULL);
542    
543     /* Initialize ROM (as a Flash) */
544     if (!(obj = dev_flash_init(vm,"rom",C3725_ROM_ADDR,vm->rom_size*1048576)))
545     return(-1);
546    
547 dpavlin 7 dev_flash_copy_data(obj,0,mips64_microcode,mips64_microcode_len);
548 dpavlin 4 c3725_nvram_check_empty_config(vm);
549    
550 dpavlin 11 /* Byte swapping */
551     dev_bswap_init(vm,"mem_bswap",C3725_BSWAP_ADDR,1024*1048576,0x00000000ULL);
552    
553 dpavlin 4 /* Initialize the NS16552 DUART */
554     dev_ns16552_init(vm,C3725_DUART_ADDR,0x1000,3,C3725_DUART_IRQ,
555     vm->vtty_con,vm->vtty_aux);
556    
557     /* PCMCIA Slot 0 */
558     dev_pcmcia_disk_init(vm,"slot0",C3725_SLOT0_ADDR,0x200000,
559     vm->pcmcia_disk_size[0],1);
560    
561     /* PCMCIA Slot 1 */
562     dev_pcmcia_disk_init(vm,"slot1",C3725_SLOT1_ADDR,0x200000,
563     vm->pcmcia_disk_size[1],1);
564    
565     /* Initialize Network Modules */
566 dpavlin 11 if (vm_slot_init_all(vm) == -1)
567     return(-1);
568 dpavlin 4
569     /* Show device list */
570     c3725_show_hardware(router);
571     return(0);
572     }
573    
574     /* Boot the IOS image */
575 dpavlin 11 static int c3725_boot_ios(c3725_t *router)
576 dpavlin 4 {
577     vm_instance_t *vm = router->vm;
578 dpavlin 7 cpu_mips_t *cpu;
579 dpavlin 4
580     if (!vm->boot_cpu)
581     return(-1);
582    
583     /* Suspend CPU activity since we will restart directly from ROM */
584     vm_suspend(vm);
585    
586     /* Check that CPU activity is really suspended */
587     if (cpu_group_sync_state(vm->cpu_group) == -1) {
588     vm_error(vm,"unable to sync with system CPUs.\n");
589     return(-1);
590     }
591    
592     /* Reset the boot CPU */
593 dpavlin 7 cpu = CPU_MIPS64(vm->boot_cpu);
594     mips64_reset(cpu);
595 dpavlin 4
596     /* Load IOS image */
597 dpavlin 7 if (mips64_load_elf_image(cpu,vm->ios_image,
598 dpavlin 4 (vm->ghost_status == VM_GHOST_RAM_USE),
599     &vm->ios_entry_point) < 0)
600     {
601     vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
602     return(-1);
603     }
604    
605     /* Launch the simulation */
606     printf("\nC3725 '%s': starting simulation (CPU0 PC=0x%llx), "
607     "JIT %sabled.\n",
608 dpavlin 7 vm->name,cpu->pc,vm->jit_use ? "en":"dis");
609 dpavlin 4
610     vm_log(vm,"C3725_BOOT",
611     "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
612 dpavlin 7 cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
613 dpavlin 4
614     /* Start main CPU */
615     if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
616     vm->status = VM_STATUS_RUNNING;
617     cpu_start(vm->boot_cpu);
618     } else {
619     vm->status = VM_STATUS_SHUTDOWN;
620     }
621     return(0);
622     }
623    
624 dpavlin 8 /* Set an IRQ */
625     static void c3725_set_irq(vm_instance_t *vm,u_int irq)
626     {
627     c3725_t *router = VM_C3725(vm);
628     cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
629     u_int slot,port;
630    
631     switch(irq) {
632     case 0 ... 7:
633     mips64_set_irq(cpu0,irq);
634    
635     if (cpu0->irq_idle_preempt[irq])
636     cpu_idle_break_wait(cpu0->gen);
637     break;
638    
639     case C3725_NETIO_IRQ_BASE ... C3725_NETIO_IRQ_END:
640     c3725_net_irq_get_slot_port(irq,&slot,&port);
641     dev_c3725_iofpga_net_set_irq(router->iofpga_data,slot,port);
642     break;
643     }
644     }
645    
646     /* Clear an IRQ */
647     static void c3725_clear_irq(vm_instance_t *vm,u_int irq)
648     {
649     c3725_t *router = VM_C3725(vm);
650     cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
651     u_int slot,port;
652    
653     switch(irq) {
654     case 0 ... 7:
655     mips64_clear_irq(cpu0,irq);
656     break;
657    
658     case C3725_NETIO_IRQ_BASE ... C3725_NETIO_IRQ_END:
659     c3725_net_irq_get_slot_port(irq,&slot,&port);
660     dev_c3725_iofpga_net_clear_irq(router->iofpga_data,slot,port);
661     break;
662     }
663     }
664    
665 dpavlin 4 /* Initialize a Cisco 3725 instance */
666 dpavlin 11 static int c3725_init_instance(vm_instance_t *vm)
667 dpavlin 4 {
668 dpavlin 11 c3725_t *router = VM_C3725(vm);
669 dpavlin 4 m_uint32_t rom_entry_point;
670     cpu_mips_t *cpu0;
671    
672     if (!vm->ios_image) {
673     vm_error(vm,"no Cisco IOS image defined.");
674     return(-1);
675     }
676    
677     /* Initialize the C3725 platform */
678     if (c3725_init_platform(router) == -1) {
679     vm_error(vm,"unable to initialize the platform hardware.\n");
680     return(-1);
681     }
682    
683 dpavlin 8 /* IRQ routing */
684     vm->set_irq = c3725_set_irq;
685     vm->clear_irq = c3725_clear_irq;
686    
687 dpavlin 4 /* Load IOS configuration file */
688     if (vm->ios_config != NULL) {
689     vm_nvram_push_config(vm,vm->ios_config);
690     vm->conf_reg &= ~0x40;
691     }
692    
693     /* Load ROM (ELF image or embedded) */
694 dpavlin 7 cpu0 = CPU_MIPS64(vm->boot_cpu);
695 dpavlin 4 rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
696    
697     if ((vm->rom_filename != NULL) &&
698     (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
699     {
700     vm_error(vm,"unable to load alternate ROM '%s', "
701     "fallback to embedded ROM.\n\n",vm->rom_filename);
702     vm->rom_filename = NULL;
703     }
704    
705     /* Load symbol file */
706     if (vm->sym_filename) {
707     mips64_sym_load_file(cpu0,vm->sym_filename);
708     cpu0->sym_trace = 1;
709     }
710    
711     return(c3725_boot_ios(router));
712     }
713    
714     /* Stop a Cisco 3725 instance */
715 dpavlin 11 static int c3725_stop_instance(vm_instance_t *vm)
716 dpavlin 4 {
717     printf("\nC3725 '%s': stopping simulation.\n",vm->name);
718     vm_log(vm,"C3725_STOP","stopping simulation.\n");
719    
720     /* Stop all CPUs */
721     if (vm->cpu_group != NULL) {
722     vm_stop(vm);
723    
724     if (cpu_group_sync_state(vm->cpu_group) == -1) {
725     vm_error(vm,"unable to sync with system CPUs.\n");
726     return(-1);
727     }
728     }
729    
730     /* Free resources that were used during execution to emulate hardware */
731 dpavlin 11 vm_slot_shutdown_all(vm);
732 dpavlin 4 vm_hardware_shutdown(vm);
733     return(0);
734     }
735 dpavlin 11
736     /* Get MAC address MSB */
737     static u_int c3725_get_mac_addr_msb(void)
738     {
739     return(0xC2);
740     }
741    
742     /* Parse specific options for the Cisco 3725 platform */
743     static int c3725_cli_parse_options(vm_instance_t *vm,int option)
744     {
745     switch(option) {
746     /* IO memory reserved for NMs (in percents!) */
747     case OPT_IOMEM_SIZE:
748     vm->nm_iomem_size = 0x8000 | atoi(optarg);
749     break;
750    
751     /* Unknown option */
752     default:
753     return(-1);
754     }
755    
756     return(0);
757     }
758    
759     /* Show specific CLI options */
760     static void c3725_cli_show_options(vm_instance_t *vm)
761     {
762     printf(" --iomem-size <val> : IO memory (in percents, default: %u)\n"
763     " -p <nm_desc> : Define a Network Module\n"
764     " -s <nm_nio> : Bind a Network IO interface to a "
765     "Network Module\n",
766     vm->nm_iomem_size);
767     }
768    
769     /* Platform definition */
770     static vm_platform_t c3725_platform = {
771     "c3725", "C3725", "3725",
772     c3725_create_instance,
773     c3725_delete_instance,
774     c3725_init_instance,
775     c3725_stop_instance,
776     c3725_nvram_extract_config,
777     c3725_nvram_push_config,
778     c3725_get_mac_addr_msb,
779     NULL,
780     c3725_cli_parse_options,
781     c3725_cli_show_options,
782     NULL,
783     };
784    
785     /* Register the c3725 platform */
786     int c3725_platform_register(void)
787     {
788     if (vm_platform_register(&c3725_platform) == -1)
789     return(-1);
790    
791     return(hypervisor_c3725_init(&c3725_platform));
792     }

  ViewVC Help
Powered by ViewVC 1.1.26