/[dynamips]/trunk/dev_c3600.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_c3600.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 dpavlin 1 /*
2     * Cisco 3600 simulation platform.
3     * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4     *
5     * Generic Cisco 3600 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 dpavlin 1 #include "dynamips.h"
17     #include "memory.h"
18     #include "device.h"
19     #include "pci_io.h"
20 dpavlin 4 #include "dev_gt.h"
21 dpavlin 1 #include "cisco_eeprom.h"
22 dpavlin 7 #include "dev_rom.h"
23 dpavlin 1 #include "dev_c3600.h"
24 dpavlin 8 #include "dev_c3600_iofpga.h"
25 dpavlin 1 #include "dev_c3600_bay.h"
26     #include "dev_vtty.h"
27     #include "registry.h"
28    
29     /* ======================================================================== */
30     /* EEPROM definitions */
31     /* ======================================================================== */
32    
33     /* Cisco 3620 mainboard EEPROM */
34 dpavlin 3 static m_uint16_t eeprom_c3620_mainboard_data[64] = {
35 dpavlin 1 0x0001, 0x0000, 0x0000, 0x0000, 0x0AFF, 0x7318, 0x5011, 0x0020,
36     0x0000, 0x0000, 0xA0FF, 0x9904, 0x19FF, 0xFFFF, 0xFFFF, 0x0002,
37     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
38     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
39     0xFFFF, 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     };
44    
45 dpavlin 3 struct cisco_eeprom eeprom_c3620_mainboard = {
46     "C3620 Mainboard",
47     eeprom_c3620_mainboard_data,
48     sizeof(eeprom_c3620_mainboard_data)/2,
49     };
50    
51 dpavlin 1 /* Cisco 3640 mainboard EEPROM */
52 dpavlin 3 static m_uint16_t eeprom_c3640_mainboard_data[64] = {
53 dpavlin 1 0x0001, 0x0000, 0x0000, 0x0000, 0x0AFF, 0x7316, 0x8514, 0x0040,
54     0x0000, 0x0000, 0xA1FF, 0x0102, 0x22FF, 0xFFFF, 0xFFFF, 0x0002,
55     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
56     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
57     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 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 dpavlin 3 struct cisco_eeprom eeprom_c3640_mainboard = {
64     "C3640 Mainboard",
65     eeprom_c3640_mainboard_data,
66     sizeof(eeprom_c3640_mainboard_data)/2,
67     };
68    
69 dpavlin 1 /* Cisco 3660 backplane EEPROM */
70 dpavlin 3 static m_uint16_t eeprom_c3660_backplane_data[64] = {
71 dpavlin 1 0x04FF, 0x4000, 0xC841, 0x0100, 0xC046, 0x0320, 0x0012, 0x8402,
72     0x4243, 0x3080, 0x0000, 0x0000, 0x0202, 0xC18B, 0x4841, 0x4430,
73     0x3434, 0x3431, 0x3135, 0x4A03, 0x0081, 0x0000, 0x0000, 0x0400,
74     0xC28B, 0x4A41, 0x4230, 0x3434, 0x3643, 0x304C, 0x32C3, 0x0600,
75     0x044D, 0x0EC2, 0xD043, 0x0070, 0xC408, 0x0000, 0x0000, 0x0000,
76     0x0000, 0x851C, 0x0A5B, 0x0201, 0x06FF, 0xFFFF, 0xFFFF, 0xFFFF,
77     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
78     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
79     };
80    
81 dpavlin 3 struct cisco_eeprom eeprom_c3660_backplane = {
82     "C3660 Backplane",
83     eeprom_c3660_backplane_data,
84     sizeof(eeprom_c3660_backplane_data)/2,
85     };
86    
87 dpavlin 1 /* ======================================================================== */
88     /* Chassis Drivers */
89     /* ======================================================================== */
90     static int c3620_init(c3600_t *router);
91     static int c3640_init(c3600_t *router);
92     static int c3660_init(c3600_t *router);
93    
94     static struct c3600_chassis_driver chassis_drivers[] = {
95 dpavlin 3 { "3620" , 3620, 1, c3620_init, &eeprom_c3620_mainboard },
96     { "3640" , 3640, 1, c3640_init, &eeprom_c3640_mainboard },
97     { "3660" , 3660, 1, c3660_init, &eeprom_c3660_backplane },
98     { NULL , -1, 0, NULL, NULL },
99 dpavlin 1 };
100    
101     /* ======================================================================== */
102     /* Network Module Drivers */
103     /* ======================================================================== */
104 dpavlin 11 static struct cisco_card_driver *nm_drivers[] = {
105 dpavlin 1 &dev_c3600_nm_1e_driver,
106     &dev_c3600_nm_4e_driver,
107     &dev_c3600_nm_1fe_tx_driver,
108     &dev_c3600_nm_4t_driver,
109     &dev_c3600_leopard_2fe_driver,
110 dpavlin 2 &dev_c3600_nm_16esw_driver,
111 dpavlin 1 NULL,
112     };
113    
114     /* ======================================================================== */
115     /* Cisco 3600 router instances */
116     /* ======================================================================== */
117    
118 dpavlin 11 /* Initialize default parameters for a C3600 */
119     static void c3600_init_defaults(c3600_t *router);
120    
121 dpavlin 1 /* Directly extract the configuration from the NVRAM device */
122 dpavlin 11 static ssize_t c3600_nvram_extract_config(vm_instance_t *vm,u_char **buffer)
123 dpavlin 4 {
124     u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;
125     m_uint32_t start,nvlen;
126     m_uint16_t magic1,magic2;
127 dpavlin 1 struct vdevice *nvram_dev;
128 dpavlin 4 off_t nvram_size;
129     int fd;
130 dpavlin 1
131 dpavlin 4 if ((nvram_dev = dev_get_by_name(vm,"nvram")))
132     dev_sync(nvram_dev);
133    
134     fd = vm_mmap_open_file(vm,"nvram",&base_ptr,&nvram_size);
135    
136     if (fd == -1)
137 dpavlin 1 return(-1);
138    
139 dpavlin 4 ios_ptr = base_ptr + vm->nvram_rom_space;
140     end_ptr = base_ptr + nvram_size;
141 dpavlin 1
142 dpavlin 4 if ((ios_ptr + 0x30) >= end_ptr) {
143     vm_error(vm,"NVRAM file too small\n");
144     return(-1);
145     }
146    
147     magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06));
148     magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08));
149    
150 dpavlin 1 if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) {
151     vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n",
152     magic1,magic2);
153     return(-1);
154     }
155    
156 dpavlin 4 start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1;
157     nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18));
158 dpavlin 1
159 dpavlin 4 if (!(*buffer = malloc(nvlen+1))) {
160     vm_error(vm,"unable to allocate config buffer (%u bytes)\n",nvlen);
161 dpavlin 1 return(-1);
162     }
163    
164 dpavlin 4 cfg_ptr = ios_ptr + start + 0x08;
165    
166     if ((cfg_ptr + nvlen) > end_ptr) {
167     vm_error(vm,"NVRAM file too small\n");
168 dpavlin 1 return(-1);
169     }
170    
171 dpavlin 4 memcpy(*buffer,cfg_ptr,nvlen-1);
172 dpavlin 3 (*buffer)[nvlen-1] = 0;
173     return(nvlen-1);
174 dpavlin 1 }
175    
176     /* Directly push the IOS configuration to the NVRAM device */
177 dpavlin 11 static int c3600_nvram_push_config(vm_instance_t *vm,u_char *buffer,size_t len)
178 dpavlin 1 {
179 dpavlin 4 u_char *base_ptr,*ios_ptr,*cfg_ptr;
180     m_uint32_t cfg_offset,cklen,tmp;
181 dpavlin 1 m_uint16_t cksum;
182 dpavlin 4 int fd;
183 dpavlin 1
184 dpavlin 4 fd = vm_mmap_create_file(vm,"nvram",vm->nvram_size*1024,&base_ptr);
185    
186     if (fd == -1)
187 dpavlin 1 return(-1);
188    
189     cfg_offset = 0x2c;
190 dpavlin 4 ios_ptr = base_ptr + vm->nvram_rom_space;
191     cfg_ptr = ios_ptr + cfg_offset;
192 dpavlin 1
193     /* Write IOS tag, uncompressed config... */
194 dpavlin 4 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5);
195     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD);
196     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001);
197     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000);
198     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0c04);
199 dpavlin 1
200     /* Store file contents to NVRAM */
201 dpavlin 4 memcpy(cfg_ptr,buffer,len);
202 dpavlin 1
203     /* Write config addresses + size */
204 dpavlin 4 tmp = cfg_offset - 0x08;
205 dpavlin 1
206 dpavlin 4 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(tmp);
207     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(tmp + len);
208     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len);
209 dpavlin 1
210     /* Compute the checksum */
211 dpavlin 4 cklen = (vm->nvram_size*1024) - (vm->nvram_rom_space + 0x08);
212     cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen);
213     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum);
214    
215     vm_mmap_close_file(fd,base_ptr,vm->nvram_size*1024);
216 dpavlin 1 return(0);
217     }
218    
219     /* Create a new router instance */
220 dpavlin 11 static int c3600_create_instance(vm_instance_t *vm)
221 dpavlin 1 {
222     c3600_t *router;
223    
224     if (!(router = malloc(sizeof(*router)))) {
225 dpavlin 11 fprintf(stderr,"C3600 '%s': Unable to create new instance!\n",vm->name);
226     return(-1);
227 dpavlin 1 }
228    
229     memset(router,0,sizeof(*router));
230 dpavlin 11 router->vm = vm;
231     vm->hw_data = router;
232 dpavlin 1
233     c3600_init_defaults(router);
234 dpavlin 11 return(0);
235 dpavlin 1 }
236    
237     /* Free resources used by a router instance */
238 dpavlin 11 static int c3600_delete_instance(vm_instance_t *vm)
239 dpavlin 1 {
240 dpavlin 11 c3600_t *router = VM_C3600(vm);
241 dpavlin 1 int i;
242    
243 dpavlin 11 /* Stop all CPUs */
244     if (vm->cpu_group != NULL) {
245     vm_stop(vm);
246 dpavlin 1
247 dpavlin 11 if (cpu_group_sync_state(vm->cpu_group) == -1) {
248     vm_error(vm,"unable to sync with system CPUs.\n");
249     return(FALSE);
250 dpavlin 1 }
251 dpavlin 11 }
252 dpavlin 1
253 dpavlin 11 /* Remove NIO bindings */
254     for(i=0;i<vm->nr_slots;i++)
255     vm_slot_remove_all_nio_bindings(vm,i);
256 dpavlin 1
257 dpavlin 11 /* Shutdown all Network Modules */
258     vm_slot_shutdown_all(vm);
259 dpavlin 1
260 dpavlin 11 /* Free mainboard EEPROM */
261     cisco_eeprom_free(&router->mb_eeprom);
262 dpavlin 3
263 dpavlin 11 /* Free all resources used by VM */
264     vm_free(vm);
265 dpavlin 1
266 dpavlin 11 /* Free the router structure */
267     free(router);
268     return(TRUE);
269 dpavlin 1 }
270    
271     /* Save configuration of a C3600 instance */
272 dpavlin 11 static void c3600_save_config(vm_instance_t *vm,FILE *fd)
273 dpavlin 1 {
274 dpavlin 11 c3600_t *router = VM_C3600(vm);
275 dpavlin 1
276 dpavlin 11 fprintf(fd,"c3600 set_chassis %s %s\n\n",
277 dpavlin 1 vm->name,router->chassis_driver->chassis_type);
278     }
279    
280 dpavlin 11 /* Set EEPROM for the specified slot */
281     int c3600_set_slot_eeprom(c3600_t *router,u_int slot,
282     struct cisco_eeprom *eeprom)
283 dpavlin 1 {
284 dpavlin 11 if (slot >= C3600_MAX_NM_BAYS)
285     return(-1);
286 dpavlin 1
287 dpavlin 11 router->c3660_nm_eeprom_group[slot].eeprom[0] = eeprom;
288     return(0);
289 dpavlin 1 }
290    
291 dpavlin 8 /* Get slot/port corresponding to specified network IRQ */
292     static inline void
293     c3600_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port)
294     {
295     irq -= C3600_NETIO_IRQ_BASE;
296     *port = irq & C3600_NETIO_IRQ_PORT_MASK;
297     *slot = irq >> C3600_NETIO_IRQ_PORT_BITS;
298     }
299    
300     /* Get network IRQ for specified slot/port */
301     u_int c3600_net_irq_for_slot_port(u_int slot,u_int port)
302     {
303     u_int irq;
304    
305     irq = (slot << C3600_NETIO_IRQ_PORT_BITS) + port;
306     irq += C3600_NETIO_IRQ_BASE;
307    
308     return(irq);
309     }
310    
311 dpavlin 1 /* Get a chassis driver */
312     struct c3600_chassis_driver *c3600_chassis_get_driver(char *chassis_type)
313     {
314     int i;
315    
316     for(i=0;chassis_drivers[i].chassis_type;i++)
317     if (!strcmp(chassis_drivers[i].chassis_type,chassis_type))
318     return(&chassis_drivers[i]);
319    
320     return NULL;
321     }
322    
323     /* Set the base MAC address of the chassis */
324 dpavlin 3 static int c3600_burn_mac_addr(c3600_t *router,n_eth_addr_t *addr)
325 dpavlin 1 {
326     m_uint8_t eeprom_ver;
327     size_t offset;
328    
329     /* Read EEPROM format version */
330 dpavlin 3 cisco_eeprom_get_byte(&router->mb_eeprom,0,&eeprom_ver);
331 dpavlin 1
332     switch(eeprom_ver) {
333     case 0:
334 dpavlin 3 cisco_eeprom_set_region(&router->mb_eeprom,2,addr->eth_addr_byte,6);
335 dpavlin 1 break;
336    
337     case 4:
338 dpavlin 3 if (!cisco_eeprom_v4_find_field(&router->mb_eeprom,0xC3,&offset)) {
339     cisco_eeprom_set_region(&router->mb_eeprom,offset,
340 dpavlin 1 addr->eth_addr_byte,6);
341     }
342     break;
343    
344     default:
345 dpavlin 3 vm_error(router->vm,"c3600_burn_mac_addr: unable to handle "
346     "EEPROM version %u\n",eeprom_ver);
347 dpavlin 1 return(-1);
348     }
349    
350     return(0);
351     }
352    
353     /* Set chassis MAC address */
354     int c3600_chassis_set_mac_addr(c3600_t *router,char *mac_addr)
355     {
356     if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) {
357     vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr);
358     return(-1);
359     }
360    
361     /* Set the chassis base MAC address */
362 dpavlin 3 c3600_burn_mac_addr(router,&router->mac_addr);
363 dpavlin 1 return(0);
364     }
365    
366     /* Set the chassis type */
367     int c3600_chassis_set_type(c3600_t *router,char *chassis_type)
368     {
369     struct c3600_chassis_driver *driver;
370    
371     if (router->vm->status == VM_STATUS_RUNNING) {
372     vm_error(router->vm,"unable to change chassis type when online.\n");
373     return(-1);
374     }
375    
376     if (!(driver = c3600_chassis_get_driver(chassis_type))) {
377     vm_error(router->vm,"unknown chassis type '%s'.\n",chassis_type);
378     return(-1);
379     }
380    
381     router->chassis_driver = driver;
382    
383     /* Copy the mainboard EEPROM */
384 dpavlin 3 if (cisco_eeprom_copy(&router->mb_eeprom,driver->eeprom) == -1) {
385     vm_error(router->vm,"unable to set chassis EEPROM '%s'.\n",chassis_type);
386     return(-1);
387     }
388 dpavlin 1
389     /* Set the chassis base MAC address */
390 dpavlin 3 c3600_burn_mac_addr(router,&router->mac_addr);
391 dpavlin 11
392     /* The motherboard has 2 integrated FastEthernet ports on a 3660 */
393     if (driver->chassis_id == 3660) {
394     vm_slot_remove_binding(router->vm,0,0);
395     vm_slot_add_binding(router->vm,"Leopard-2FE",0,0);
396     }
397    
398 dpavlin 1 return(0);
399     }
400    
401     /* Get the chassis ID */
402     int c3600_chassis_get_id(c3600_t *router)
403     {
404     if (router->chassis_driver)
405     return(router->chassis_driver->chassis_id);
406    
407     return(-1);
408     }
409    
410     /* Show the list of available chassis drivers */
411 dpavlin 11 static void c3600_chassis_show_drivers(void)
412 dpavlin 1 {
413     int i;
414    
415     printf("Available C3600 chassis drivers:\n");
416    
417     for(i=0;chassis_drivers[i].chassis_type;i++) {
418     printf(" * %s %s\n",
419     chassis_drivers[i].chassis_type,
420     !chassis_drivers[i].supported ? "(NOT WORKING)" : "");
421     }
422    
423     printf("\n");
424     }
425    
426     /* Create the main PCI bus for a GT64010 based system */
427     static int c3600_init_gt64010(c3600_t *router)
428     {
429     if (!(router->vm->pci_bus[0] = pci_bus_create("PCI bus",0))) {
430     vm_error(router->vm,"unable to create PCI data.\n");
431     return(-1);
432     }
433    
434     return(dev_gt64010_init(router->vm,"gt64010",C3600_GT64K_ADDR,0x1000,
435     C3600_GT64K_IRQ));
436     }
437    
438     /* Create the two main PCI busses for a GT64120 based system */
439     static int c3600_init_gt64120(c3600_t *router)
440     {
441     vm_instance_t *vm = router->vm;
442    
443     vm->pci_bus[0] = pci_bus_create("PCI bus #0",0);
444     vm->pci_bus[1] = pci_bus_create("PCI bus #1",0);
445    
446     if (!vm->pci_bus[0] || !vm->pci_bus[1]) {
447     vm_error(router->vm,"unable to create PCI data.\n");
448     return(-1);
449     }
450    
451     return(dev_gt64120_init(vm,"gt64120",C3600_GT64K_ADDR,0x1000,
452     C3600_GT64K_IRQ));
453     }
454    
455     /* Initialize a Cisco 3620 */
456     static int c3620_init(c3600_t *router)
457     {
458     vm_instance_t *vm = router->vm;
459     int i;
460    
461     /* Set the processor type: R4700 */
462 dpavlin 7 mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R4700);
463 dpavlin 1
464     /* Initialize the Galileo GT-64010 PCI controller */
465     if (c3600_init_gt64010(router) == -1)
466     return(-1);
467    
468     /* Initialize PCI map (no PCI bridge for this chassis) */
469     for(i=0;i<C3600_MAX_NM_BAYS;i++)
470 dpavlin 11 vm->slots_pci_bus[i] = vm->pci_bus[0];
471 dpavlin 1
472     vm->elf_machine_id = C3620_ELF_MACHINE_ID;
473     return(0);
474     }
475    
476     /* Initialize a Cisco 3640 */
477     static int c3640_init(c3600_t *router)
478     {
479     vm_instance_t *vm = router->vm;
480     struct nm_bay_info *bay;
481     int i;
482    
483     /* Set the processor type: R4700 */
484 dpavlin 7 mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R4700);
485 dpavlin 1
486     /* Initialize the Galileo GT-64010 PCI controller */
487     if (c3600_init_gt64010(router) == -1)
488     return(-1);
489    
490     /* Create the NM PCI busses */
491     vm->pci_bus_pool[0] = pci_bus_create("NM Slots 0,2",-1);
492     vm->pci_bus_pool[1] = pci_bus_create("NM Slots 1,3",-1);
493    
494     /* Initialize PCI map and PCI bridges */
495     for(i=0;i<=3;i++) {
496     bay = c3600_nm_get_bay_info(3640,i);
497    
498     /* Map the NM PCI bus */
499 dpavlin 11 vm->slots_pci_bus[i] = vm->pci_bus_pool[i & 1];
500 dpavlin 1
501     if (bay && (bay->pci_bridge_device != -1))
502     dev_dec21052_init(vm->pci_bus[0],bay->pci_bridge_device,
503 dpavlin 11 vm->slots_pci_bus[i]);
504 dpavlin 1 }
505    
506     vm->elf_machine_id = C3640_ELF_MACHINE_ID;
507     return(0);
508     }
509    
510     /* Initialize a Cisco 3660 */
511     static int c3660_init(c3600_t *router)
512     {
513     vm_instance_t *vm = router->vm;
514     struct nm_bay_info *bay;
515     char bus_name[128];
516     int i;
517    
518     /* Set the processor type: R5271 */
519 dpavlin 7 mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R527x);
520 dpavlin 1
521     /* Initialize the Galileo GT-64120 PCI controller */
522     if (c3600_init_gt64120(router) == -1)
523     return(-1);
524    
525     /* Create the NM PCI busses */
526     for(i=1;i<=6;i++) {
527     snprintf(bus_name,sizeof(bus_name),"NM Slot %d",i);
528     vm->pci_bus_pool[i] = pci_bus_create(bus_name,-1);
529     }
530    
531     /* Slot 0 is mapped to the first bus of GT64120 */
532 dpavlin 11 vm->slots_pci_bus[0] = vm->pci_bus[0];
533 dpavlin 1
534     /* Initialize PCI map and PCI bridges */
535     for(i=1;i<C3600_MAX_NM_BAYS;i++) {
536     bay = c3600_nm_get_bay_info(3660,i);
537    
538     /* Map the NM PCI bus */
539 dpavlin 11 vm->slots_pci_bus[i] = vm->pci_bus_pool[i];
540 dpavlin 1
541     /* Slots 1-6 are mapped to the second bus of GT64120 */
542     if (bay && (bay->pci_bridge_device != -1))
543     dev_dec21152_init(vm->pci_bus[1],bay->pci_bridge_device,
544 dpavlin 11 vm->slots_pci_bus[i]);
545 dpavlin 1 }
546    
547 dpavlin 11 vm->elf_machine_id = C3660_ELF_MACHINE_ID;
548 dpavlin 1 return(0);
549     }
550    
551     /* Show C3600 hardware info */
552     void c3600_show_hardware(c3600_t *router)
553     {
554     vm_instance_t *vm = router->vm;
555    
556     printf("C3600 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(" Chassis : %s\n",router->chassis_driver->chassis_type);
562     printf(" IOS image : %s\n\n",vm->ios_image);
563    
564     if (vm->debug_level > 0) {
565     dev_show_list(vm);
566     pci_dev_show_list(vm->pci_bus[0]);
567     pci_dev_show_list(vm->pci_bus[1]);
568     printf("\n");
569     }
570     }
571    
572     /* Initialize default parameters for a C3600 */
573 dpavlin 11 static void c3600_init_defaults(c3600_t *router)
574 dpavlin 1 {
575     vm_instance_t *vm = router->vm;
576     n_eth_addr_t *m;
577     m_uint16_t pid;
578    
579 dpavlin 11 /* Set platform slots characteristics */
580     vm->nr_slots = C3600_MAX_NM_BAYS;
581     vm->slots_type = CISCO_CARD_TYPE_NM;
582     vm->slots_drivers = nm_drivers;
583    
584 dpavlin 1 pid = (m_uint16_t)getpid();
585    
586     /* Generate a chassis MAC address based on the instance ID */
587     m = &router->mac_addr;
588 dpavlin 4 m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
589 dpavlin 1 m->eth_addr_byte[1] = vm->instance_id & 0xFF;
590     m->eth_addr_byte[2] = pid >> 8;
591     m->eth_addr_byte[3] = pid & 0xFF;
592     m->eth_addr_byte[4] = 0x00;
593     m->eth_addr_byte[5] = 0x00;
594    
595     c3600_init_eeprom_groups(router);
596     c3600_chassis_set_type(router,C3600_DEFAULT_CHASSIS);
597    
598     vm->ram_mmap = C3600_DEFAULT_RAM_MMAP;
599     vm->ram_size = C3600_DEFAULT_RAM_SIZE;
600     vm->rom_size = C3600_DEFAULT_ROM_SIZE;
601     vm->nvram_size = C3600_DEFAULT_NVRAM_SIZE;
602 dpavlin 4 vm->conf_reg_setup = C3600_DEFAULT_CONF_REG;
603 dpavlin 1 vm->clock_divisor = C3600_DEFAULT_CLOCK_DIV;
604     vm->nvram_rom_space = C3600_NVRAM_ROM_RES_SIZE;
605 dpavlin 11 vm->nm_iomem_size = C3600_DEFAULT_IOMEM_SIZE;
606 dpavlin 1
607     vm->pcmcia_disk_size[0] = C3600_DEFAULT_DISK0_SIZE;
608     vm->pcmcia_disk_size[1] = C3600_DEFAULT_DISK1_SIZE;
609     }
610    
611     /* Initialize the C3600 Platform */
612 dpavlin 11 static int c3600_init_platform(c3600_t *router)
613 dpavlin 1 {
614     vm_instance_t *vm = router->vm;
615     cpu_mips_t *cpu;
616 dpavlin 7 cpu_gen_t *gen;
617 dpavlin 8 vm_obj_t *obj;
618 dpavlin 1
619     /* Copy config register setup into "active" config register */
620     vm->conf_reg = vm->conf_reg_setup;
621    
622     /* Create Console and AUX ports */
623     vm_init_vtty(vm);
624    
625     /* Create a CPU group */
626     vm->cpu_group = cpu_group_create("System CPU");
627    
628     /* Initialize the virtual MIPS processor */
629 dpavlin 7 if (!(gen = cpu_create(vm,CPU_TYPE_MIPS64,0))) {
630 dpavlin 1 vm_error(vm,"unable to create CPU!\n");
631     return(-1);
632     }
633    
634 dpavlin 7 cpu = CPU_MIPS64(gen);
635    
636 dpavlin 1 /* Add this CPU to the system CPU group */
637 dpavlin 7 cpu_group_add(vm->cpu_group,gen);
638     vm->boot_cpu = gen;
639 dpavlin 1
640 dpavlin 7 /* Initialize the IRQ routing vectors */
641     vm->set_irq = mips64_vm_set_irq;
642     vm->clear_irq = mips64_vm_clear_irq;
643    
644 dpavlin 1 /* Mark the Network IO interrupt as high priority */
645     cpu->irq_idle_preempt[C3600_NETIO_IRQ] = TRUE;
646 dpavlin 4 cpu->irq_idle_preempt[C3600_GT64K_IRQ] = TRUE;
647 dpavlin 1 cpu->irq_idle_preempt[C3600_DUART_IRQ] = TRUE;
648    
649     /* Copy some parameters from VM to CPU (idle PC, ...) */
650     cpu->idle_pc = vm->idle_pc;
651    
652     if (vm->timer_irq_check_itv)
653     cpu->timer_irq_check_itv = vm->timer_irq_check_itv;
654    
655     /* Get chassis specific driver */
656     if (!router->chassis_driver) {
657     vm_error(vm,"no chassis defined.\n");
658     return(-1);
659     }
660    
661     /* Remote emulator control */
662     dev_remote_control_init(vm,0x16000000,0x1000);
663    
664 dpavlin 11 /* Bootflash (8 Mb) */
665     dev_bootflash_init(vm,"bootflash","c3600-bootflash-8mb",
666     C3600_BOOTFLASH_ADDR);
667 dpavlin 1
668     /* NVRAM and calendar */
669     dev_nvram_init(vm,"nvram",
670     C3600_NVRAM_ADDR,vm->nvram_size*1024,&vm->conf_reg);
671    
672     /* Bit-bucket zone */
673     dev_zero_init(vm,"zero",C3600_BITBUCKET_ADDR,0xc00000);
674    
675     /* IO FPGA */
676     if (dev_c3600_iofpga_init(router,C3600_IOFPGA_ADDR,0x40000) == -1)
677     return(-1);
678    
679 dpavlin 8 if (!(obj = vm_object_find(router->vm,"io_fpga")))
680     return(-1);
681    
682     router->iofpga_data = obj->data;
683    
684 dpavlin 1 /* PCI IO space */
685     if (!(vm->pci_io_space = pci_io_data_init(vm,C3600_PCI_IO_ADDR)))
686     return(-1);
687    
688     /* Initialize the chassis */
689     if (router->chassis_driver->chassis_init(router) == -1)
690     return(-1);
691    
692     /* Initialize RAM */
693 dpavlin 4 vm_ram_init(vm,0x00000000ULL);
694 dpavlin 1
695     /* Initialize ROM */
696     if (!vm->rom_filename) {
697     /* use embedded ROM */
698 dpavlin 7 dev_rom_init(vm,"rom",C3600_ROM_ADDR,vm->rom_size*1048576,
699     mips64_microcode,mips64_microcode_len);
700 dpavlin 1 } else {
701     /* use alternate ROM */
702 dpavlin 7 dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE,
703 dpavlin 4 C3600_ROM_ADDR,vm->rom_size*1048576);
704 dpavlin 1 }
705    
706     /* Initialize the NS16552 DUART */
707 dpavlin 2 dev_ns16552_init(vm,C3600_DUART_ADDR,0x1000,3,C3600_DUART_IRQ,
708 dpavlin 1 vm->vtty_con,vm->vtty_aux);
709    
710     /* Cirrus Logic PD6729 (PCI-to-PCMCIA host adapter) */
711     dev_clpd6729_init(vm,vm->pci_bus[0],20,vm->pci_io_space,0x4402,0x4403);
712    
713     /* Initialize Network Modules */
714 dpavlin 11 if (vm_slot_init_all(vm) == -1)
715     return(-1);
716 dpavlin 1
717     /* Show device list */
718     c3600_show_hardware(router);
719     return(0);
720     }
721    
722     /* Boot the IOS image */
723 dpavlin 11 static int c3600_boot_ios(c3600_t *router)
724 dpavlin 1 {
725     vm_instance_t *vm = router->vm;
726 dpavlin 7 cpu_mips_t *cpu;
727 dpavlin 1
728     if (!vm->boot_cpu)
729     return(-1);
730    
731     /* Suspend CPU activity since we will restart directly from ROM */
732     vm_suspend(vm);
733    
734     /* Check that CPU activity is really suspended */
735     if (cpu_group_sync_state(vm->cpu_group) == -1) {
736     vm_error(vm,"unable to sync with system CPUs.\n");
737     return(-1);
738     }
739    
740     /* Reset the boot CPU */
741 dpavlin 7 cpu = CPU_MIPS64(vm->boot_cpu);
742     mips64_reset(cpu);
743 dpavlin 1
744     /* Load IOS image */
745 dpavlin 7 if (mips64_load_elf_image(cpu,vm->ios_image,
746 dpavlin 4 (vm->ghost_status == VM_GHOST_RAM_USE),
747 dpavlin 1 &vm->ios_entry_point) < 0)
748     {
749     vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
750     return(-1);
751     }
752    
753     /* Launch the simulation */
754     printf("\nC3600 '%s': starting simulation (CPU0 PC=0x%llx), "
755     "JIT %sabled.\n",
756 dpavlin 7 vm->name,cpu->pc,vm->jit_use ? "en":"dis");
757 dpavlin 1
758     vm_log(vm,"C3600_BOOT",
759     "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
760 dpavlin 7 cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off");
761 dpavlin 2
762 dpavlin 1 /* Start main CPU */
763 dpavlin 4 if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
764     vm->status = VM_STATUS_RUNNING;
765     cpu_start(vm->boot_cpu);
766     } else {
767     vm->status = VM_STATUS_SHUTDOWN;
768     }
769 dpavlin 1 return(0);
770     }
771    
772 dpavlin 8 /* Set an IRQ */
773     static void c3600_set_irq(vm_instance_t *vm,u_int irq)
774     {
775     c3600_t *router = VM_C3600(vm);
776     cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
777     u_int slot,port;
778    
779     switch(irq) {
780     case 0 ... 7:
781     mips64_set_irq(cpu0,irq);
782    
783     if (cpu0->irq_idle_preempt[irq])
784     cpu_idle_break_wait(cpu0->gen);
785     break;
786    
787     case C3600_NETIO_IRQ_BASE ... C3600_NETIO_IRQ_END:
788     c3600_net_irq_get_slot_port(irq,&slot,&port);
789     dev_c3600_iofpga_net_set_irq(router->iofpga_data,slot,port);
790     break;
791     }
792     }
793    
794     /* Clear an IRQ */
795     static void c3600_clear_irq(vm_instance_t *vm,u_int irq)
796     {
797     c3600_t *router = VM_C3600(vm);
798     cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu);
799     u_int slot,port;
800    
801     switch(irq) {
802     case 0 ... 7:
803     mips64_clear_irq(cpu0,irq);
804     break;
805    
806     case C3600_NETIO_IRQ_BASE ... C3600_NETIO_IRQ_END:
807     c3600_net_irq_get_slot_port(irq,&slot,&port);
808     dev_c3600_iofpga_net_clear_irq(router->iofpga_data,slot,port);
809     break;
810     }
811     }
812    
813 dpavlin 1 /* Initialize a Cisco 3600 instance */
814 dpavlin 11 static int c3600_init_instance(vm_instance_t *vm)
815 dpavlin 1 {
816 dpavlin 11 c3600_t *router = VM_C3600(vm);
817 dpavlin 1 m_uint32_t rom_entry_point;
818     cpu_mips_t *cpu0;
819    
820     if (!vm->ios_image) {
821     vm_error(vm,"no Cisco IOS image defined.");
822     return(-1);
823     }
824    
825     /* Initialize the C3600 platform */
826     if (c3600_init_platform(router) == -1) {
827     vm_error(vm,"unable to initialize the platform hardware.\n");
828     return(-1);
829     }
830    
831 dpavlin 8 /* IRQ routing */
832     vm->set_irq = c3600_set_irq;
833     vm->clear_irq = c3600_clear_irq;
834    
835 dpavlin 1 /* Load IOS configuration file */
836     if (vm->ios_config != NULL) {
837     vm_nvram_push_config(vm,vm->ios_config);
838     vm->conf_reg &= ~0x40;
839     }
840    
841     /* Load ROM (ELF image or embedded) */
842 dpavlin 7 cpu0 = CPU_MIPS64(vm->boot_cpu);
843 dpavlin 1 rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
844    
845     if ((vm->rom_filename != NULL) &&
846 dpavlin 4 (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
847 dpavlin 1 {
848     vm_error(vm,"unable to load alternate ROM '%s', "
849     "fallback to embedded ROM.\n\n",vm->rom_filename);
850     vm->rom_filename = NULL;
851     }
852    
853     /* Load symbol file */
854     if (vm->sym_filename) {
855     mips64_sym_load_file(cpu0,vm->sym_filename);
856     cpu0->sym_trace = 1;
857     }
858    
859     return(c3600_boot_ios(router));
860     }
861    
862     /* Stop a Cisco 3600 instance */
863 dpavlin 11 static int c3600_stop_instance(vm_instance_t *vm)
864 dpavlin 1 {
865     printf("\nC3600 '%s': stopping simulation.\n",vm->name);
866     vm_log(vm,"C3600_STOP","stopping simulation.\n");
867    
868     /* Stop all CPUs */
869     if (vm->cpu_group != NULL) {
870     vm_stop(vm);
871    
872     if (cpu_group_sync_state(vm->cpu_group) == -1) {
873     vm_error(vm,"unable to sync with system CPUs.\n");
874     return(-1);
875     }
876     }
877    
878     /* Free resources that were used during execution to emulate hardware */
879 dpavlin 11 vm_slot_shutdown_all(vm);
880 dpavlin 1 vm_hardware_shutdown(vm);
881     return(0);
882     }
883 dpavlin 11
884     /* Get MAC address MSB */
885     static u_int c3600_get_mac_addr_msb(void)
886     {
887     return(0xCC);
888     }
889    
890     /* Parse specific options for the Cisco 3600 platform */
891     static int c3600_cli_parse_options(vm_instance_t *vm,int option)
892     {
893     c3600_t *router = VM_C3600(vm);
894    
895     switch(option) {
896     /* IO memory reserved for NMs (in percents!) */
897     case OPT_IOMEM_SIZE:
898     vm->nm_iomem_size = 0x8000 | atoi(optarg);
899     break;
900    
901     /* Chassis type */
902     case 't':
903     c3600_chassis_set_type(router,optarg);
904     break;
905    
906     /* Unknown option */
907     default:
908     return(-1);
909     }
910    
911     return(0);
912     }
913    
914     /* Show specific CLI options */
915     static void c3600_cli_show_options(vm_instance_t *vm)
916     {
917     printf(" -t <chassis_type> : Select Chassis type (default: \"%s\")\n"
918     " --iomem-size <val> : IO memory (in percents, default: %u)\n"
919     " -p <nm_desc> : Define a Network Module\n"
920     " -s <nm_nio> : Bind a Network IO interface to a "
921     "Network Module\n",
922     C3600_DEFAULT_CHASSIS,vm->nm_iomem_size);
923     }
924    
925     /* Platform definition */
926     static vm_platform_t c3600_platform = {
927     "c3600", "C3600", "3600",
928     c3600_create_instance,
929     c3600_delete_instance,
930     c3600_init_instance,
931     c3600_stop_instance,
932     c3600_nvram_extract_config,
933     c3600_nvram_push_config,
934     c3600_get_mac_addr_msb,
935     c3600_save_config,
936     c3600_cli_parse_options,
937     c3600_cli_show_options,
938     c3600_chassis_show_drivers,
939     };
940    
941     /* Register the c3600 platform */
942     int c3600_platform_register(void)
943     {
944     if (vm_platform_register(&c3600_platform) == -1)
945     return(-1);
946    
947     return(hypervisor_c3600_init(&c3600_platform));
948     }

  ViewVC Help
Powered by ViewVC 1.1.26