/[dynamips]/trunk/dev_c3745.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_c3745.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: 23565 byte(s)
make working copy

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

  ViewVC Help
Powered by ViewVC 1.1.26