/[dynamips]/upstream/dynamips-0.2.6-RC5/dev_c7200.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 /upstream/dynamips-0.2.6-RC5/dev_c7200.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (hide annotations)
Sat Oct 6 16:09:07 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 63905 byte(s)
dynamips-0.2.6-RC5

1 dpavlin 1 /*
2     * Cisco 7200 (Predator) simulation platform.
3     * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4     *
5     * Generic Cisco 7200 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 "mips64.h"
16     #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     #include "dev_c7200.h"
23     #include "dev_vtty.h"
24     #include "registry.h"
25     #include "net.h"
26    
27     /* ======================================================================== */
28     /* CPU EEPROM definitions */
29     /* ======================================================================== */
30    
31     /* NPE-100 */
32     static m_uint16_t eeprom_cpu_npe100_data[16] = {
33     0x0135, 0x0203, 0xffff, 0xffff, 0x4906, 0x0004, 0x0000, 0x0000,
34     0x6000, 0x0000, 0x9901, 0x0600, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
35     };
36    
37     /* NPE-150 */
38     static m_uint16_t eeprom_cpu_npe150_data[16] = {
39     0x0115, 0x0203, 0xffff, 0xffff, 0x4906, 0x0004, 0x0000, 0x0000,
40     0x6000, 0x0000, 0x9901, 0x0600, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
41     };
42    
43     /* NPE-175 */
44     static m_uint16_t eeprom_cpu_npe175_data[16] = {
45     0x01C2, 0x0203, 0xffff, 0xffff, 0x4906, 0x0004, 0x0000, 0x0000,
46     0x6000, 0x0000, 0x9901, 0x0600, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
47     };
48    
49     /* NPE-200 */
50     static m_uint16_t eeprom_cpu_npe200_data[16] = {
51     0x0169, 0x0200, 0xffff, 0xffff, 0x4909, 0x8902, 0x0000, 0x0000,
52     0x6800, 0x0000, 0x9710, 0x2200, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
53     };
54    
55     /* NPE-225 (same as NPE-175) */
56     static m_uint16_t eeprom_cpu_npe225_data[16] = {
57     0x01C2, 0x0203, 0xffff, 0xffff, 0x4906, 0x0004, 0x0000, 0x0000,
58     0x6000, 0x0000, 0x9901, 0x0600, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
59     };
60    
61     /* NPE-300 */
62     static m_uint16_t eeprom_cpu_npe300_data[16] = {
63     0x01AE, 0x0402, 0xffff, 0xffff, 0x490D, 0x5108, 0x0000, 0x0000,
64     0x5000, 0x0000, 0x0012, 0x1000, 0x0000, 0xFFFF, 0xFFFF, 0xFF00,
65     };
66    
67     /* NPE-400 */
68     static m_uint16_t eeprom_cpu_npe400_data[64] = {
69     0x04FF, 0x4001, 0xF841, 0x0100, 0xC046, 0x0320, 0x001F, 0xC802,
70     0x8249, 0x14BC, 0x0242, 0x4230, 0xC18B, 0x3131, 0x3131, 0x3131,
71     0x3131, 0x0000, 0x0004, 0x0002, 0x0285, 0x1C0F, 0xF602, 0xCB87,
72     0x4E50, 0x452D, 0x3430, 0x3080, 0x0000, 0x0000, 0xFFFF, 0xFFFF,
73     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
74     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
75     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
76     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
77     };
78    
79     /* NPE-G1 */
80     static m_uint16_t eeprom_cpu_npeg1_data[64] = {
81     0x04FF, 0x4003, 0x5B41, 0x0200, 0xC046, 0x0320, 0x0049, 0xD00B,
82     0x8249, 0x1B4C, 0x0B42, 0x4130, 0xC18B, 0x3131, 0x3131, 0x3131,
83     0x3131, 0x0000, 0x0004, 0x0002, 0x0985, 0x1C13, 0xDA09, 0xCB86,
84     0x4E50, 0x452D, 0x4731, 0x8000, 0x0000, 0x00FF, 0xFFFF, 0xFFFF,
85     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
86     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
87     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
88     0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
89     };
90    
91     /*
92     * CPU EEPROM array.
93     */
94 dpavlin 3 static struct cisco_eeprom c7200_cpu_eeprom[] = {
95 dpavlin 1 { "npe-100", eeprom_cpu_npe100_data, sizeof(eeprom_cpu_npe100_data)/2 },
96     { "npe-150", eeprom_cpu_npe150_data, sizeof(eeprom_cpu_npe150_data)/2 },
97     { "npe-175", eeprom_cpu_npe175_data, sizeof(eeprom_cpu_npe175_data)/2 },
98     { "npe-200", eeprom_cpu_npe200_data, sizeof(eeprom_cpu_npe200_data)/2 },
99     { "npe-225", eeprom_cpu_npe225_data, sizeof(eeprom_cpu_npe225_data)/2 },
100     { "npe-300", eeprom_cpu_npe300_data, sizeof(eeprom_cpu_npe300_data)/2 },
101     { "npe-400", eeprom_cpu_npe400_data, sizeof(eeprom_cpu_npe400_data)/2 },
102     { "npe-g1" , eeprom_cpu_npeg1_data , sizeof(eeprom_cpu_npeg1_data)/2 },
103     { NULL, NULL, 0 },
104     };
105    
106     /* ======================================================================== */
107     /* Midplane EEPROM definitions */
108     /* ======================================================================== */
109    
110     /* Standard Midplane EEPROM contents */
111     static m_uint16_t eeprom_midplane_data[32] = {
112     0x0106, 0x0101, 0xffff, 0xffff, 0x4906, 0x0303, 0xFFFF, 0xFFFF,
113     0xFFFF, 0x0400, 0x0000, 0x0000, 0x4C09, 0x10B0, 0xFFFF, 0x00FF,
114     0x0000, 0x0000, 0x6335, 0x8B28, 0x631D, 0x0000, 0x608E, 0x6D1C,
115     0x62BB, 0x0000, 0x6335, 0x8B28, 0x0000, 0x0000, 0x6335, 0x8B28,
116     };
117    
118     /* VXR Midplane EEPROM contents */
119     static m_uint16_t eeprom_vxr_midplane_data[32] = {
120     0x0106, 0x0201, 0xffff, 0xffff, 0x4906, 0x0303, 0xFFFF, 0xFFFF,
121     0xFFFF, 0x0400, 0x0000, 0x0000, 0x4C09, 0x10B0, 0xFFFF, 0x00FF,
122     0x0000, 0x0000, 0x6335, 0x8B28, 0x631D, 0x0000, 0x608E, 0x6D1C,
123     0x62BB, 0x0000, 0x6335, 0x8B28, 0x0000, 0x0000, 0x6335, 0x8B28,
124     };
125    
126     /*
127     * Midplane EEPROM array.
128     */
129 dpavlin 3 static struct cisco_eeprom c7200_midplane_eeprom[] = {
130 dpavlin 1 { "std", eeprom_midplane_data, sizeof(eeprom_midplane_data)/2 },
131     { "vxr", eeprom_vxr_midplane_data, sizeof(eeprom_vxr_midplane_data)/2 },
132     { NULL, NULL, 0 },
133     };
134    
135     /* ======================================================================== */
136     /* PEM EEPROM definitions (for NPE-175 and NPE-225) */
137     /* ======================================================================== */
138    
139     /* NPE-175 */
140     static m_uint16_t eeprom_pem_npe175_data[16] = {
141     0x01C3, 0x0100, 0xFFFF, 0xFFFF, 0x490D, 0x8A04, 0x0000, 0x0000,
142     0x5000, 0x0000, 0x9906, 0x0400, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF,
143     };
144    
145     /* NPE-225 */
146     static m_uint16_t eeprom_pem_npe225_data[16] = {
147     0x01D5, 0x0100, 0xFFFF, 0xFFFF, 0x490D, 0x8A04, 0x0000, 0x0000,
148     0x5000, 0x0000, 0x9906, 0x0400, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF,
149     };
150    
151     /*
152     * PEM EEPROM array.
153     */
154 dpavlin 3 static struct cisco_eeprom c7200_pem_eeprom[] = {
155 dpavlin 1 { "npe-175", eeprom_pem_npe175_data, sizeof(eeprom_pem_npe175_data)/2 },
156     { "npe-225", eeprom_pem_npe225_data, sizeof(eeprom_pem_npe225_data)/2 },
157     { NULL, NULL, 0 },
158     };
159    
160     /* ======================================================================== */
161     /* Port Adapter Drivers */
162     /* ======================================================================== */
163     static struct c7200_pa_driver *pa_drivers[] = {
164     &dev_c7200_io_fe_driver,
165     &dev_c7200_pa_fe_tx_driver,
166     &dev_c7200_pa_4e_driver,
167     &dev_c7200_pa_8e_driver,
168     &dev_c7200_pa_4t_driver,
169     &dev_c7200_pa_8t_driver,
170     &dev_c7200_pa_a1_driver,
171     &dev_c7200_pa_pos_oc3_driver,
172 dpavlin 4 &dev_c7200_pa_4b_driver,
173     &dev_c7200_pa_mc8te1_driver,
174 dpavlin 1 NULL,
175     };
176    
177     /* ======================================================================== */
178     /* NPE Drivers */
179     /* ======================================================================== */
180     #define DECLARE_NPE(type) \
181     int (c7200_init_##type)(c7200_t *router)
182    
183     DECLARE_NPE(npe100);
184     DECLARE_NPE(npe150);
185     DECLARE_NPE(npe175);
186     DECLARE_NPE(npe200);
187     DECLARE_NPE(npe225);
188     DECLARE_NPE(npe300);
189     DECLARE_NPE(npe400);
190     DECLARE_NPE(npeg1);
191    
192     static struct c7200_npe_driver npe_drivers[] = {
193     { "npe-100" , c7200_init_npe100, 256, 1, C7200_NVRAM_ADDR, 0, 5, 0, 6 },
194     { "npe-150" , c7200_init_npe150, 256, 1, C7200_NVRAM_ADDR, 0, 5, 0, 6 },
195     { "npe-175" , c7200_init_npe175, 256, 1, C7200_NVRAM_ADDR, 2, 16, 1, 0 },
196     { "npe-200" , c7200_init_npe200, 256, 1, C7200_NVRAM_ADDR, 0, 5, 0, 6 },
197     { "npe-225" , c7200_init_npe225, 256, 1, C7200_NVRAM_ADDR, 2, 16, 1, 0 },
198     { "npe-300" , c7200_init_npe300, 256, 1, C7200_NVRAM_ADDR, 2, 16, 1, 0 },
199     { "npe-400" , c7200_init_npe400, 512, 1, C7200_NVRAM_ADDR, 2, 16, 1, 0 },
200     { "npe-g1" , c7200_init_npeg1, 1024, 0,
201     C7200_NPEG1_NVRAM_ADDR, 17, 16, 16, 0 },
202     { NULL , NULL },
203     };
204    
205     /* ======================================================================== */
206     /* Cisco 7200 router instances */
207     /* ======================================================================== */
208    
209     /* Directly extract the configuration from the NVRAM device */
210     ssize_t c7200_nvram_extract_config(vm_instance_t *vm,char **buffer)
211     {
212 dpavlin 4 u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr;
213     m_uint32_t start,end,nvlen,clen;
214     m_uint16_t magic1,magic2;
215 dpavlin 1 struct vdevice *nvram_dev;
216 dpavlin 4 m_uint64_t nvram_addr;
217     off_t nvram_size;
218     int fd;
219 dpavlin 1
220 dpavlin 4 if ((nvram_dev = dev_get_by_name(vm,"nvram")))
221     dev_sync(nvram_dev);
222    
223     fd = vm_mmap_open_file(vm,"nvram",&base_ptr,&nvram_size);
224    
225     if (fd == -1)
226 dpavlin 1 return(-1);
227    
228 dpavlin 4 nvram_addr = VM_C7200(vm)->npe_driver->nvram_addr;
229     ios_ptr = base_ptr + vm->nvram_rom_space;
230     end_ptr = base_ptr + nvram_size;
231 dpavlin 1
232 dpavlin 4 if ((ios_ptr + 0x30) >= end_ptr) {
233     vm_error(vm,"NVRAM file too small\n");
234     return(-1);
235     }
236    
237     magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06));
238     magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08));
239    
240 dpavlin 1 if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) {
241     vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n",
242     magic1,magic2);
243     return(-1);
244     }
245    
246 dpavlin 4 start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1;
247     end = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x14));
248     nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18));
249 dpavlin 1 clen = end - start;
250    
251     if ((clen + 1) != nvlen) {
252     vm_error(vm,"invalid configuration size (0x%x)\n",nvlen);
253     return(-1);
254     }
255    
256 dpavlin 4 if (!(*buffer = malloc(clen+1))) {
257     vm_error(vm,"unable to allocate config buffer (%u bytes)\n",clen);
258 dpavlin 1 return(-1);
259     }
260    
261 dpavlin 4 cfg_ptr = base_ptr + (start - nvram_addr);
262    
263     if ((start < nvram_addr) || ((cfg_ptr + clen) > end_ptr)) {
264     vm_error(vm,"NVRAM file too small\n");
265 dpavlin 1 return(-1);
266     }
267    
268 dpavlin 4 memcpy(*buffer,cfg_ptr,clen);
269 dpavlin 1 (*buffer)[clen] = 0;
270     return(clen);
271     }
272    
273     /* Directly push the IOS configuration to the NVRAM device */
274     int c7200_nvram_push_config(vm_instance_t *vm,char *buffer,size_t len)
275 dpavlin 4 {
276     u_char *base_ptr,*ios_ptr,*cfg_ptr;
277     m_uint32_t cfg_addr,cfg_offset;
278     m_uint32_t nvram_addr,cklen;
279 dpavlin 2 m_uint16_t cksum;
280 dpavlin 4 int fd;
281 dpavlin 1
282 dpavlin 4 fd = vm_mmap_create_file(vm,"nvram",vm->nvram_size*1024,&base_ptr);
283    
284     if (fd == -1)
285 dpavlin 1 return(-1);
286    
287 dpavlin 4 cfg_offset = 0x2c;
288     ios_ptr = base_ptr + vm->nvram_rom_space;
289     cfg_ptr = ios_ptr + cfg_offset;
290 dpavlin 1
291 dpavlin 4 nvram_addr = VM_C7200(vm)->npe_driver->nvram_addr;
292     cfg_addr = nvram_addr + vm->nvram_rom_space + cfg_offset;
293    
294 dpavlin 1 /* Write IOS tag, uncompressed config... */
295 dpavlin 4 *PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5);
296     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD);
297     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001);
298     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000);
299     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0000);
300 dpavlin 1
301     /* Store file contents to NVRAM */
302 dpavlin 4 memcpy(cfg_ptr,buffer,len);
303 dpavlin 1
304     /* Write config addresses + size */
305 dpavlin 4 *PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(cfg_addr);
306     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(cfg_addr + len);
307     *PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len);
308 dpavlin 2
309     /* Compute the checksum */
310 dpavlin 4 cklen = (vm->nvram_size*1024) - (vm->nvram_rom_space + 0x08);
311     cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen);
312     *PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum);
313    
314     vm_mmap_close_file(fd,base_ptr,vm->nvram_size*1024);
315 dpavlin 1 return(0);
316     }
317    
318     /* Get an EEPROM for a given NPE model */
319 dpavlin 3 static const struct cisco_eeprom *c7200_get_cpu_eeprom(char *npe_name)
320 dpavlin 1 {
321 dpavlin 3 return(cisco_eeprom_find(c7200_cpu_eeprom,npe_name));
322 dpavlin 1 }
323    
324     /* Get an EEPROM for a given midplane model */
325 dpavlin 3 static const struct cisco_eeprom *
326     c7200_get_midplane_eeprom(char *midplane_name)
327 dpavlin 1 {
328 dpavlin 3 return(cisco_eeprom_find(c7200_midplane_eeprom,midplane_name));
329 dpavlin 1 }
330    
331     /* Get a PEM EEPROM for a given NPE model */
332 dpavlin 3 static const struct cisco_eeprom *c7200_get_pem_eeprom(char *npe_name)
333 dpavlin 1 {
334 dpavlin 3 return(cisco_eeprom_find(c7200_pem_eeprom,npe_name));
335 dpavlin 1 }
336    
337     /* Set the base MAC address of the chassis */
338 dpavlin 3 static int c7200_burn_mac_addr(c7200_t *router,n_eth_addr_t *addr)
339 dpavlin 1 {
340     m_uint8_t eeprom_ver;
341    
342     /* Read EEPROM format version */
343 dpavlin 3 cisco_eeprom_get_byte(&router->mp_eeprom,0,&eeprom_ver);
344 dpavlin 1
345     if (eeprom_ver != 1) {
346 dpavlin 3 vm_error(router->vm,"c7200_burn_mac_addr: unable to handle "
347 dpavlin 1 "EEPROM version %u\n",eeprom_ver);
348     return(-1);
349     }
350    
351 dpavlin 3 cisco_eeprom_set_region(&router->mp_eeprom,12,addr->eth_addr_byte,6);
352 dpavlin 1 return(0);
353     }
354    
355     /* Free specific hardware resources used by C7200 */
356     static void c7200_free_hw_ressources(c7200_t *router)
357     {
358     /* Shutdown all Port Adapters */
359     c7200_pa_shutdown_all(router);
360    
361     /* Inactivate the PCMCIA bus */
362     router->pcmcia_bus = NULL;
363    
364     /* Remove the hidden I/O bridge */
365     if (router->io_pci_bridge != NULL) {
366     pci_bridge_remove(router->io_pci_bridge);
367     router->io_pci_bridge = NULL;
368     }
369     }
370    
371     /* Create a new router instance */
372     c7200_t *c7200_create_instance(char *name,int instance_id)
373     {
374     c7200_t *router;
375    
376     if (!(router = malloc(sizeof(*router)))) {
377     fprintf(stderr,"C7200 '%s': Unable to create new instance!\n",name);
378     return NULL;
379     }
380    
381     memset(router,0,sizeof(*router));
382    
383     if (!(router->vm = vm_create(name,instance_id,VM_TYPE_C7200))) {
384     fprintf(stderr,"C7200 '%s': unable to create VM instance!\n",name);
385     goto err_vm;
386     }
387    
388     c7200_init_defaults(router);
389     router->vm->hw_data = router;
390     router->vm->elf_machine_id = C7200_ELF_MACHINE_ID;
391     return router;
392    
393     err_vm:
394     free(router);
395     return NULL;
396     }
397    
398     /* Free resources used by a router instance */
399     static int c7200_free_instance(void *data,void *arg)
400     {
401     vm_instance_t *vm = data;
402     c7200_t *router;
403     int i;
404    
405     if (vm->type == VM_TYPE_C7200) {
406     router = VM_C7200(vm);
407    
408     /* Stop all CPUs */
409     if (vm->cpu_group != NULL) {
410     vm_stop(vm);
411    
412     if (cpu_group_sync_state(vm->cpu_group) == -1) {
413     vm_error(vm,"unable to sync with system CPUs.\n");
414     return(FALSE);
415     }
416     }
417    
418     /* Remove NIO bindings */
419     for(i=0;i<C7200_MAX_PA_BAYS;i++)
420     c7200_pa_remove_all_nio_bindings(router,i);
421    
422     /* Free specific HW resources */
423     c7200_free_hw_ressources(router);
424    
425 dpavlin 3 /* Free EEPROMs */
426     cisco_eeprom_free(&router->cpu_eeprom);
427     cisco_eeprom_free(&router->mp_eeprom);
428     cisco_eeprom_free(&router->pem_eeprom);
429    
430 dpavlin 1 /* Free all resources used by VM */
431     vm_free(vm);
432    
433     /* Free the router structure */
434     free(router);
435     return(TRUE);
436     }
437    
438     return(FALSE);
439     }
440    
441     /* Delete a router instance */
442     int c7200_delete_instance(char *name)
443     {
444     return(registry_delete_if_unused(name,OBJ_TYPE_VM,
445     c7200_free_instance,NULL));
446     }
447    
448     /* Delete all router instances */
449     int c7200_delete_all_instances(void)
450     {
451     return(registry_delete_type(OBJ_TYPE_VM,c7200_free_instance,NULL));
452     }
453    
454     /* Save configuration of a C7200 instance */
455     void c7200_save_config(c7200_t *router,FILE *fd)
456     {
457     vm_instance_t *vm = router->vm;
458     struct c7200_nio_binding *nb;
459     struct c7200_pa_bay *bay;
460     int i;
461    
462     /* General settings */
463     fprintf(fd,"c7200 create %s %u\n",vm->name,vm->instance_id);
464    
465     fprintf(fd,"c7200 set_npe %s %s\n",vm->name,router->npe_driver->npe_type);
466     fprintf(fd,"c7200 set_midplane %s %s\n",vm->name,router->midplane_type);
467    
468     /* VM configuration */
469     vm_save_config(vm,fd);
470    
471     /* Port Adapter settings */
472     for(i=0;i<C7200_MAX_PA_BAYS;i++) {
473     if (!(bay = c7200_pa_get_info(router,i)))
474     continue;
475    
476     if (bay->dev_type) {
477     fprintf(fd,"c7200 add_pa_binding %s %u %s\n",
478     vm->name,i,bay->dev_type);
479     }
480    
481     for(nb=bay->nio_list;nb;nb=nb->next) {
482     fprintf(fd,"c7200 add_nio_binding %s %u %u %s\n",
483     vm->name,i,nb->port_id,nb->nio->name);
484     }
485     }
486    
487     fprintf(fd,"\n");
488     }
489    
490     /* Save configurations of all C7200 instances */
491     static void c7200_reg_save_config(registry_entry_t *entry,void *opt,int *err)
492     {
493     vm_instance_t *vm = entry->data;
494     c7200_t *router = VM_C7200(vm);
495    
496     if (vm->type == VM_TYPE_C7200)
497     c7200_save_config(router,(FILE *)opt);
498     }
499    
500     void c7200_save_config_all(FILE *fd)
501     {
502     registry_foreach_type(OBJ_TYPE_VM,c7200_reg_save_config,fd,NULL);
503     }
504    
505     /* Set NPE eeprom definition */
506     static int c7200_npe_set_eeprom(c7200_t *router)
507     {
508 dpavlin 3 const struct cisco_eeprom *eeprom;
509 dpavlin 1
510     if (!(eeprom = c7200_get_cpu_eeprom(router->npe_driver->npe_type))) {
511     vm_error(router->vm,"unknown NPE \"%s\" (internal error)!\n",
512     router->npe_driver->npe_type);
513     return(-1);
514     }
515    
516 dpavlin 3 if (cisco_eeprom_copy(&router->cpu_eeprom,eeprom) == -1) {
517     vm_error(router->vm,"unable to set NPE EEPROM.\n");
518     return(-1);
519     }
520    
521 dpavlin 1 return(0);
522     }
523    
524     /* Set PEM eeprom definition */
525     static int c7200_pem_set_eeprom(c7200_t *router)
526     {
527 dpavlin 3 const struct cisco_eeprom *eeprom;
528 dpavlin 1
529     if (!(eeprom = c7200_get_pem_eeprom(router->npe_driver->npe_type))) {
530     vm_error(router->vm,"no PEM EEPROM found for NPE type \"%s\"!\n",
531     router->npe_driver->npe_type);
532     return(-1);
533     }
534    
535 dpavlin 3 if (cisco_eeprom_copy(&router->pem_eeprom,eeprom) == -1) {
536     vm_error(router->vm,"unable to set PEM EEPROM.\n");
537     return(-1);
538     }
539    
540 dpavlin 1 return(0);
541     }
542    
543     /* Set PA EEPROM definition */
544     int c7200_pa_set_eeprom(c7200_t *router,u_int pa_bay,
545 dpavlin 3 const struct cisco_eeprom *eeprom)
546 dpavlin 1 {
547     if (pa_bay >= C7200_MAX_PA_BAYS) {
548     vm_error(router->vm,"c7200_pa_set_eeprom: invalid PA Bay %u.\n",pa_bay);
549     return(-1);
550     }
551 dpavlin 3
552     if (cisco_eeprom_copy(&router->pa_bay[pa_bay].eeprom,eeprom) == -1) {
553     vm_error(router->vm,"c7200_pa_set_eeprom: no memory.\n");
554     return(-1);
555     }
556    
557 dpavlin 1 return(0);
558     }
559    
560     /* Unset PA EEPROM definition (empty bay) */
561     int c7200_pa_unset_eeprom(c7200_t *router,u_int pa_bay)
562     {
563     if (pa_bay >= C7200_MAX_PA_BAYS) {
564     vm_error(router->vm,"c7200_pa_set_eeprom: invalid PA Bay %u.\n",pa_bay);
565     return(-1);
566     }
567    
568 dpavlin 3 cisco_eeprom_free(&router->pa_bay[pa_bay].eeprom);
569 dpavlin 1 return(0);
570     }
571    
572     /* Check if a bay has a port adapter */
573     int c7200_pa_check_eeprom(c7200_t *router,u_int pa_bay)
574     {
575     if (!pa_bay || (pa_bay >= C7200_MAX_PA_BAYS))
576 dpavlin 3 return(FALSE);
577 dpavlin 1
578 dpavlin 3 return(cisco_eeprom_valid(&router->pa_bay[pa_bay].eeprom));
579 dpavlin 1 }
580    
581     /* Get bay info */
582     struct c7200_pa_bay *c7200_pa_get_info(c7200_t *router,u_int pa_bay)
583     {
584     if (pa_bay >= C7200_MAX_PA_BAYS)
585     return NULL;
586    
587     return(&router->pa_bay[pa_bay]);
588     }
589    
590     /* Get PA type */
591     char *c7200_pa_get_type(c7200_t *router,u_int pa_bay)
592     {
593     struct c7200_pa_bay *bay;
594    
595     bay = c7200_pa_get_info(router,pa_bay);
596     return((bay != NULL) ? bay->dev_type : NULL);
597     }
598    
599     /* Get driver info about the specified slot */
600     void *c7200_pa_get_drvinfo(c7200_t *router,u_int pa_bay)
601     {
602     struct c7200_pa_bay *bay;
603    
604     bay = c7200_pa_get_info(router,pa_bay);
605     return((bay != NULL) ? bay->drv_info : NULL);
606     }
607    
608     /* Set driver info for the specified slot */
609     int c7200_pa_set_drvinfo(c7200_t *router,u_int pa_bay,void *drv_info)
610     {
611     struct c7200_pa_bay *bay;
612    
613     if (!(bay = c7200_pa_get_info(router,pa_bay)))
614     return(-1);
615    
616     bay->drv_info = drv_info;
617     return(0);
618     }
619    
620     /* Get a PA driver */
621     static struct c7200_pa_driver *c7200_pa_get_driver(char *dev_type)
622     {
623     int i;
624    
625     for(i=0;pa_drivers[i];i++)
626     if (!strcmp(pa_drivers[i]->dev_type,dev_type))
627     return pa_drivers[i];
628    
629     return NULL;
630     }
631    
632     /* Add a PA binding */
633     int c7200_pa_add_binding(c7200_t *router,char *dev_type,u_int pa_bay)
634     {
635     struct c7200_pa_driver *pa_driver;
636     struct c7200_pa_bay *bay;
637    
638     if (!(bay = c7200_pa_get_info(router,pa_bay)))
639     return(-1);
640    
641     /* check that this bay is empty */
642     if (bay->dev_type != NULL) {
643     vm_error(router->vm,"a PA already exists in slot %u.\n",pa_bay);
644     return(-1);
645     }
646    
647     /* find the PA driver */
648     if (!(pa_driver = c7200_pa_get_driver(dev_type))) {
649     vm_error(router->vm,"unknown PA type '%s'.\n",dev_type);
650     return(-1);
651     }
652    
653     bay->dev_type = pa_driver->dev_type;
654     bay->pa_driver = pa_driver;
655     return(0);
656     }
657    
658     /* Remove a PA binding */
659     int c7200_pa_remove_binding(c7200_t *router,u_int pa_bay)
660     {
661     struct c7200_pa_bay *bay;
662    
663     if (!(bay = c7200_pa_get_info(router,pa_bay)))
664     return(-1);
665    
666     /* stop if this bay is still active */
667     if (bay->drv_info != NULL) {
668     vm_error(router->vm,"slot %u still active.\n",pa_bay);
669     return(-1);
670     }
671    
672     /* check that this bay is not empty */
673     if (bay->dev_type == NULL) {
674     vm_error(router->vm,"slot %u is empty.\n",pa_bay);
675     return(-1);
676     }
677    
678     /* remove all NIOs bindings */
679     c7200_pa_remove_all_nio_bindings(router,pa_bay);
680    
681     bay->dev_type = NULL;
682     bay->pa_driver = NULL;
683     return(0);
684     }
685    
686     /* Find a NIO binding */
687     struct c7200_nio_binding *
688     c7200_pa_find_nio_binding(c7200_t *router,u_int pa_bay,u_int port_id)
689     {
690     struct c7200_nio_binding *nb;
691     struct c7200_pa_bay *bay;
692    
693     if (!(bay = c7200_pa_get_info(router,pa_bay)))
694     return NULL;
695    
696     for(nb=bay->nio_list;nb;nb=nb->next)
697     if (nb->port_id == port_id)
698     return nb;
699    
700     return NULL;
701     }
702    
703     /* Add a network IO binding */
704     int c7200_pa_add_nio_binding(c7200_t *router,u_int pa_bay,u_int port_id,
705     char *nio_name)
706     {
707     struct c7200_nio_binding *nb;
708     struct c7200_pa_bay *bay;
709     netio_desc_t *nio;
710    
711     if (!(bay = c7200_pa_get_info(router,pa_bay)))
712     return(-1);
713    
714     /* check that a NIO is not already bound to this port */
715     if (c7200_pa_find_nio_binding(router,pa_bay,port_id) != NULL) {
716     vm_error(router->vm,"a NIO already exists for interface %u/%u\n",
717     pa_bay,port_id);
718     return(-1);
719     }
720    
721     /* acquire a reference on the NIO object */
722     if (!(nio = netio_acquire(nio_name))) {
723     vm_error(router->vm,"unable to find NIO '%s'.\n",nio_name);
724     return(-1);
725     }
726    
727     /* create a new binding */
728     if (!(nb = malloc(sizeof(*nb)))) {
729     vm_error(router->vm,"unable to create NIO binding "
730     "for interface %u/%u.\n",pa_bay,port_id);
731     netio_release(nio_name);
732     return(-1);
733     }
734    
735     memset(nb,0,sizeof(*nb));
736     nb->nio = nio;
737     nb->port_id = port_id;
738     nb->next = bay->nio_list;
739     if (nb->next) nb->next->prev = nb;
740     bay->nio_list = nb;
741     return(0);
742     }
743    
744     /* Remove a NIO binding */
745     int c7200_pa_remove_nio_binding(c7200_t *router,u_int pa_bay,u_int port_id)
746     {
747     struct c7200_nio_binding *nb;
748     struct c7200_pa_bay *bay;
749    
750     if (!(bay = c7200_pa_get_info(router,pa_bay)))
751     return(-1);
752    
753     if (!(nb = c7200_pa_find_nio_binding(router,pa_bay,port_id)))
754     return(-1); /* no nio binding for this slot/port */
755    
756     /* tell the PA driver to stop using this NIO */
757     if (bay->pa_driver)
758     bay->pa_driver->pa_unset_nio(router,pa_bay,port_id);
759    
760     /* remove this entry from the double linked list */
761     if (nb->next)
762     nb->next->prev = nb->prev;
763    
764     if (nb->prev) {
765     nb->prev->next = nb->next;
766     } else {
767     bay->nio_list = nb->next;
768     }
769    
770     /* unreference NIO object */
771     netio_release(nb->nio->name);
772     free(nb);
773     return(0);
774     }
775    
776     /* Remove all NIO bindings for the specified PA */
777     int c7200_pa_remove_all_nio_bindings(c7200_t *router,u_int pa_bay)
778     {
779     struct c7200_nio_binding *nb,*next;
780     struct c7200_pa_bay *bay;
781    
782     if (!(bay = c7200_pa_get_info(router,pa_bay)))
783     return(-1);
784    
785     for(nb=bay->nio_list;nb;nb=next) {
786     next = nb->next;
787    
788     /* tell the PA driver to stop using this NIO */
789     if (bay->pa_driver)
790     bay->pa_driver->pa_unset_nio(router,pa_bay,nb->port_id);
791    
792     /* unreference NIO object */
793     netio_release(nb->nio->name);
794     free(nb);
795     }
796    
797     bay->nio_list = NULL;
798     return(0);
799     }
800    
801     /* Enable a Network IO descriptor for a Port Adapter */
802     int c7200_pa_enable_nio(c7200_t *router,u_int pa_bay,u_int port_id)
803     {
804     struct c7200_nio_binding *nb;
805     struct c7200_pa_bay *bay;
806    
807     if (!(bay = c7200_pa_get_info(router,pa_bay)))
808     return(-1);
809    
810     /* check that we have an NIO binding for this interface */
811     if (!(nb = c7200_pa_find_nio_binding(router,pa_bay,port_id)))
812     return(-1);
813    
814     /* check that the driver is defined and successfully initialized */
815     if (!bay->pa_driver || !bay->drv_info)
816     return(-1);
817    
818     return(bay->pa_driver->pa_set_nio(router,pa_bay,port_id,nb->nio));
819     }
820    
821     /* Disable Network IO descriptor of a Port Adapter */
822     int c7200_pa_disable_nio(c7200_t *router,u_int pa_bay,u_int port_id)
823     {
824     struct c7200_pa_bay *bay;
825    
826     if (!(bay = c7200_pa_get_info(router,pa_bay)))
827     return(-1);
828    
829     /* check that the driver is defined and successfully initialized */
830     if (!bay->pa_driver || !bay->drv_info)
831     return(-1);
832    
833     return(bay->pa_driver->pa_unset_nio(router,pa_bay,port_id));
834     }
835    
836     /* Enable all NIO of the specified PA */
837     int c7200_pa_enable_all_nio(c7200_t *router,u_int pa_bay)
838     {
839     struct c7200_nio_binding *nb;
840     struct c7200_pa_bay *bay;
841    
842     if (!(bay = c7200_pa_get_info(router,pa_bay)))
843     return(-1);
844    
845     /* check that the driver is defined and successfully initialized */
846     if (!bay->pa_driver || !bay->drv_info)
847     return(-1);
848    
849     for(nb=bay->nio_list;nb;nb=nb->next)
850     bay->pa_driver->pa_set_nio(router,pa_bay,nb->port_id,nb->nio);
851    
852     return(0);
853     }
854    
855     /* Disable all NIO of the specified PA */
856     int c7200_pa_disable_all_nio(c7200_t *router,u_int pa_bay)
857     {
858     struct c7200_nio_binding *nb;
859     struct c7200_pa_bay *bay;
860    
861     if (!(bay = c7200_pa_get_info(router,pa_bay)))
862     return(-1);
863    
864     /* check that the driver is defined and successfully initialized */
865     if (!bay->pa_driver || !bay->drv_info)
866     return(-1);
867    
868     for(nb=bay->nio_list;nb;nb=nb->next)
869     bay->pa_driver->pa_unset_nio(router,pa_bay,nb->port_id);
870    
871     return(0);
872     }
873    
874     /* Initialize a Port Adapter */
875     int c7200_pa_init(c7200_t *router,u_int pa_bay)
876     {
877     struct c7200_pa_bay *bay;
878     size_t len;
879    
880     if (!(bay = c7200_pa_get_info(router,pa_bay)))
881     return(-1);
882    
883     /* Check that a device type is defined for this bay */
884     if (!bay->dev_type || !bay->pa_driver) {
885     vm_error(router->vm,"trying to init empty slot %u.\n",pa_bay);
886     return(-1);
887     }
888    
889     /* Allocate device name */
890     len = strlen(bay->dev_type) + 10;
891     if (!(bay->dev_name = malloc(len))) {
892     vm_error(router->vm,"unable to allocate device name.\n");
893     return(-1);
894     }
895    
896     snprintf(bay->dev_name,len,"%s(%u)",bay->dev_type,pa_bay);
897    
898     /* Initialize PA driver */
899     if (bay->pa_driver->pa_init(router,bay->dev_name,pa_bay) == 1) {
900     vm_error(router->vm,"unable to initialize PA %u.\n",pa_bay);
901     return(-1);
902     }
903    
904     /* Enable all NIO */
905     c7200_pa_enable_all_nio(router,pa_bay);
906     return(0);
907     }
908    
909     /* Shutdown a Port Adapter */
910     int c7200_pa_shutdown(c7200_t *router,u_int pa_bay)
911     {
912     struct c7200_pa_bay *bay;
913    
914     if (!(bay = c7200_pa_get_info(router,pa_bay)))
915     return(-1);
916    
917     /* Check that a device type is defined for this bay */
918     if (!bay->dev_type || !bay->pa_driver) {
919     vm_error(router->vm,"trying to shut down an empty bay %u.\n",pa_bay);
920     return(-1);
921     }
922    
923     /* Disable all NIO */
924     c7200_pa_disable_all_nio(router,pa_bay);
925    
926     /* Shutdown the PA driver */
927     if (bay->drv_info && (bay->pa_driver->pa_shutdown(router,pa_bay) == -1)) {
928     vm_error(router->vm,"unable to shutdown PA %u.\n",pa_bay);
929     return(-1);
930     }
931    
932     free(bay->dev_name);
933     bay->dev_name = NULL;
934     bay->drv_info = NULL;
935     return(0);
936     }
937    
938     /* Shutdown all PA of a router */
939     int c7200_pa_shutdown_all(c7200_t *router)
940     {
941     int i;
942    
943     for(i=0;i<C7200_MAX_PA_BAYS;i++) {
944     if (!router->pa_bay[i].dev_type)
945     continue;
946    
947     c7200_pa_shutdown(router,i);
948     }
949    
950     return(0);
951     }
952    
953 dpavlin 2 /* Show info about all NMs */
954     int c7200_pa_show_all_info(c7200_t *router)
955     {
956     struct c7200_pa_bay *bay;
957     int i;
958    
959     for(i=0;i<C7200_MAX_PA_BAYS;i++) {
960     if (!(bay = c7200_pa_get_info(router,i)) || !bay->pa_driver)
961     continue;
962    
963     if (bay->pa_driver->pa_show_info != NULL)
964     bay->pa_driver->pa_show_info(router,i);
965     }
966    
967     return(0);
968     }
969    
970 dpavlin 1 /* Maximum number of tokens in a PA description */
971     #define PA_DESC_MAX_TOKENS 8
972    
973     /* Create a Port Adapter (command line) */
974     int c7200_cmd_pa_create(c7200_t *router,char *str)
975     {
976     char *tokens[PA_DESC_MAX_TOKENS];
977     int i,count,res;
978     u_int pa_bay;
979    
980     /* A port adapter description is like "1:PA-FE-TX" */
981     if ((count = m_strsplit(str,':',tokens,PA_DESC_MAX_TOKENS)) != 2) {
982     vm_error(router->vm,"unable to parse PA description '%s'.\n",str);
983     return(-1);
984     }
985    
986     /* Parse the PA bay id */
987     pa_bay = atoi(tokens[0]);
988    
989     /* Add this new PA to the current PA list */
990     res = c7200_pa_add_binding(router,tokens[1],pa_bay);
991    
992     /* The complete array was cleaned by strsplit */
993     for(i=0;i<PA_DESC_MAX_TOKENS;i++)
994     free(tokens[i]);
995    
996     return(res);
997     }
998    
999     /* Add a Network IO descriptor binding (command line) */
1000     int c7200_cmd_add_nio(c7200_t *router,char *str)
1001     {
1002     char *tokens[PA_DESC_MAX_TOKENS];
1003     int i,count,nio_type,res=-1;
1004     u_int pa_bay,port_id;
1005     netio_desc_t *nio;
1006     char nio_name[128];
1007    
1008     /* A port adapter description is like "1:3:tap:tap0" */
1009     if ((count = m_strsplit(str,':',tokens,PA_DESC_MAX_TOKENS)) < 3) {
1010     vm_error(router->vm,"unable to parse NIO description '%s'.\n",str);
1011     return(-1);
1012     }
1013    
1014     /* Parse the PA bay */
1015     pa_bay = atoi(tokens[0]);
1016    
1017     /* Parse the PA port id */
1018     port_id = atoi(tokens[1]);
1019    
1020     /* Autogenerate a NIO name */
1021     snprintf(nio_name,sizeof(nio_name),"c7200-i%u/%u/%u",
1022     router->vm->instance_id,pa_bay,port_id);
1023    
1024     /* Create the Network IO descriptor */
1025     nio = NULL;
1026     nio_type = netio_get_type(tokens[2]);
1027    
1028     switch(nio_type) {
1029     case NETIO_TYPE_UNIX:
1030     if (count != 5) {
1031     vm_error(router->vm,
1032     "invalid number of arguments for UNIX NIO '%s'\n",str);
1033     goto done;
1034     }
1035    
1036     nio = netio_desc_create_unix(nio_name,tokens[3],tokens[4]);
1037     break;
1038    
1039     case NETIO_TYPE_VDE:
1040     if (count != 5) {
1041     vm_error(router->vm,
1042     "invalid number of arguments for VDE NIO '%s'\n",str);
1043     goto done;
1044     }
1045    
1046     nio = netio_desc_create_vde(nio_name,tokens[3],tokens[4]);
1047     break;
1048    
1049     case NETIO_TYPE_TAP:
1050     if (count != 4) {
1051     vm_error(router->vm,
1052     "invalid number of arguments for TAP NIO '%s'\n",str);
1053     goto done;
1054     }
1055    
1056     nio = netio_desc_create_tap(nio_name,tokens[3]);
1057     break;
1058    
1059     case NETIO_TYPE_UDP:
1060     if (count != 6) {
1061     vm_error(router->vm,
1062     "invalid number of arguments for UDP NIO '%s'\n",str);
1063     goto done;
1064     }
1065    
1066     nio = netio_desc_create_udp(nio_name,atoi(tokens[3]),
1067     tokens[4],atoi(tokens[5]));
1068     break;
1069    
1070     case NETIO_TYPE_TCP_CLI:
1071     if (count != 5) {
1072     vm_error(router->vm,
1073     "invalid number of arguments for TCP CLI NIO '%s'\n",str);
1074     goto done;
1075     }
1076    
1077     nio = netio_desc_create_tcp_cli(nio_name,tokens[3],tokens[4]);
1078     break;
1079    
1080     case NETIO_TYPE_TCP_SER:
1081     if (count != 4) {
1082     vm_error(router->vm,
1083     "invalid number of arguments for TCP SER NIO '%s'\n",str);
1084     goto done;
1085     }
1086    
1087     nio = netio_desc_create_tcp_ser(nio_name,tokens[3]);
1088     break;
1089    
1090     case NETIO_TYPE_NULL:
1091     nio = netio_desc_create_null(nio_name);
1092     break;
1093    
1094     #ifdef LINUX_ETH
1095     case NETIO_TYPE_LINUX_ETH:
1096     if (count != 4) {
1097     vm_error(router->vm,
1098     "invalid number of arguments for Linux Eth NIO '%s'\n",
1099     str);
1100     goto done;
1101     }
1102    
1103     nio = netio_desc_create_lnxeth(nio_name,tokens[3]);
1104     break;
1105     #endif
1106    
1107     #ifdef GEN_ETH
1108     case NETIO_TYPE_GEN_ETH:
1109     if (count != 4) {
1110     vm_error(router->vm,"invalid number of "
1111     "arguments for Generic Eth NIO '%s'\n",str);
1112     goto done;
1113     }
1114    
1115     nio = netio_desc_create_geneth(nio_name,tokens[3]);
1116     break;
1117     #endif
1118    
1119     default:
1120     vm_error(router->vm,"unknown NETIO type '%s'\n",tokens[2]);
1121     goto done;
1122     }
1123    
1124     if (!nio) {
1125     fprintf(stderr,"c7200_cmd_add_nio: unable to create NETIO "
1126     "descriptor for PA bay %u\n",pa_bay);
1127     goto done;
1128     }
1129    
1130     if (c7200_pa_add_nio_binding(router,pa_bay,port_id,nio_name) == -1) {
1131     vm_error(router->vm,"unable to add NETIO binding for slot %u\n",pa_bay);
1132     netio_release(nio_name);
1133     netio_delete(nio_name);
1134     goto done;
1135     }
1136    
1137     netio_release(nio_name);
1138     res = 0;
1139    
1140     done:
1141     /* The complete array was cleaned by strsplit */
1142     for(i=0;i<PA_DESC_MAX_TOKENS;i++)
1143     free(tokens[i]);
1144    
1145     return(res);
1146     }
1147    
1148     /* Show the list of available PA drivers */
1149     void c7200_pa_show_drivers(void)
1150     {
1151     int i;
1152    
1153     printf("Available C7200 Port Adapter drivers:\n");
1154    
1155     for(i=0;pa_drivers[i];i++) {
1156     printf(" * %s %s\n",
1157     pa_drivers[i]->dev_type,
1158     !pa_drivers[i]->supported ? "(NOT WORKING)" : "");
1159     }
1160    
1161     printf("\n");
1162     }
1163    
1164     /* Get an NPE driver */
1165     struct c7200_npe_driver *c7200_npe_get_driver(char *npe_type)
1166     {
1167     int i;
1168    
1169     for(i=0;npe_drivers[i].npe_type;i++)
1170     if (!strcmp(npe_drivers[i].npe_type,npe_type))
1171     return(&npe_drivers[i]);
1172    
1173     return NULL;
1174     }
1175    
1176     /* Set the NPE type */
1177     int c7200_npe_set_type(c7200_t *router,char *npe_type)
1178     {
1179     struct c7200_npe_driver *driver;
1180    
1181     if (router->vm->status == VM_STATUS_RUNNING) {
1182     vm_error(router->vm,"unable to change NPE type when online.\n");
1183     return(-1);
1184     }
1185    
1186     if (!(driver = c7200_npe_get_driver(npe_type))) {
1187     vm_error(router->vm,"unknown NPE type '%s'.\n",npe_type);
1188     return(-1);
1189     }
1190    
1191     router->npe_driver = driver;
1192    
1193     if (c7200_npe_set_eeprom(router) == -1) {
1194     vm_error(router->vm,"unable to find NPE '%s' EEPROM!\n",
1195     router->npe_driver->npe_type);
1196     return(-1);
1197     }
1198    
1199     return(0);
1200     }
1201    
1202     /* Show the list of available NPE drivers */
1203     void c7200_npe_show_drivers(void)
1204     {
1205     int i;
1206    
1207     printf("Available C7200 NPE drivers:\n");
1208    
1209     for(i=0;npe_drivers[i].npe_type;i++) {
1210     printf(" * %s %s\n",
1211     npe_drivers[i].npe_type,
1212     !npe_drivers[i].supported ? "(NOT WORKING)" : "");
1213     }
1214    
1215     printf("\n");
1216     }
1217    
1218     /* Set Midplane type */
1219     int c7200_midplane_set_type(c7200_t *router,char *midplane_type)
1220     {
1221 dpavlin 3 const struct cisco_eeprom *eeprom;
1222 dpavlin 1 m_uint8_t version;
1223    
1224     if (router->vm->status == VM_STATUS_RUNNING) {
1225     vm_error(router->vm,"unable to change Midplane type when online.\n");
1226     return(-1);
1227     }
1228    
1229     /* Set EEPROM */
1230     if (!(eeprom = c7200_get_midplane_eeprom(midplane_type))) {
1231     vm_error(router->vm,"unknown Midplane \"%s\"!\n",midplane_type);
1232     return(-1);
1233     }
1234    
1235 dpavlin 3 /* Copy the midplane EEPROM */
1236     if (cisco_eeprom_copy(&router->mp_eeprom,eeprom) == -1) {
1237     vm_error(router->vm,"unable to set midplane EEPROM.\n");
1238     return(-1);
1239     }
1240 dpavlin 1
1241     /* Set the chassis base MAC address */
1242 dpavlin 3 c7200_burn_mac_addr(router,&router->mac_addr);
1243 dpavlin 1
1244 dpavlin 3 /* Get the midplane version */
1245     cisco_eeprom_get_byte(&router->mp_eeprom,2,&version);
1246     router->midplane_version = version;
1247 dpavlin 1 router->midplane_type = eeprom->name;
1248     return(0);
1249     }
1250    
1251     /* Set chassis MAC address */
1252     int c7200_midplane_set_mac_addr(c7200_t *router,char *mac_addr)
1253     {
1254     if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) {
1255     vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr);
1256     return(-1);
1257     }
1258    
1259     /* Set the chassis base MAC address */
1260 dpavlin 3 c7200_burn_mac_addr(router,&router->mac_addr);
1261 dpavlin 1 return(0);
1262     }
1263    
1264     /* Create the main PCI bus for a GT64010 based system */
1265     static int c7200_init_gt64010(c7200_t *router)
1266     {
1267     vm_instance_t *vm = router->vm;
1268    
1269     if (!(vm->pci_bus[0] = pci_bus_create("MB0/MB1/MB2",0))) {
1270     vm_error(vm,"unable to create PCI data.\n");
1271     return(-1);
1272     }
1273    
1274     return(dev_gt64010_init(vm,"gt64010",C7200_GT64K_ADDR,0x1000,
1275     C7200_GT64K_IRQ));
1276     }
1277    
1278     /* Create the two main PCI busses for a GT64120 based system */
1279     static int c7200_init_gt64120(c7200_t *router)
1280     {
1281     vm_instance_t *vm = router->vm;
1282    
1283     vm->pci_bus[0] = pci_bus_create("MB0/MB1",0);
1284     vm->pci_bus[1] = pci_bus_create("MB2",0);
1285    
1286     if (!vm->pci_bus[0] || !vm->pci_bus[1]) {
1287     vm_error(vm,"unable to create PCI data.\n");
1288     return(-1);
1289     }
1290    
1291     return(dev_gt64120_init(vm,"gt64120",C7200_GT64K_ADDR,0x1000,
1292     C7200_GT64K_IRQ));
1293     }
1294    
1295     /* Create the two main PCI busses for a dual GT64120 system */
1296     static int c7200_init_dual_gt64120(c7200_t *router)
1297     {
1298     vm_instance_t *vm = router->vm;
1299    
1300     vm->pci_bus[0] = pci_bus_create("MB0/MB1",0);
1301     vm->pci_bus[1] = pci_bus_create("MB2",0);
1302    
1303     if (!vm->pci_bus[0] || !vm->pci_bus[1]) {
1304     vm_error(vm,"unable to create PCI data.\n",vm->name);
1305     return(-1);
1306     }
1307    
1308     /* Initialize the first GT64120 at 0x14000000 */
1309     if (dev_gt64120_init(vm,"gt64120(1)",C7200_GT64K_ADDR,0x1000,
1310     C7200_GT64K_IRQ) == -1)
1311     return(-1);
1312    
1313     /* Initialize the second GT64120 at 0x15000000 */
1314     if (dev_gt64120_init(vm,"gt64120(2)",C7200_GT64K_SEC_ADDR,0x1000,
1315     C7200_GT64K_IRQ) == -1)
1316     return(-1);
1317    
1318     return(0);
1319     }
1320    
1321     /* Create the PA PCI busses */
1322     static int c7200_pa_create_pci_busses(c7200_t *router)
1323     {
1324     vm_instance_t *vm = router->vm;
1325     char bus_name[128];
1326     int i;
1327    
1328     for(i=1;i<C7200_MAX_PA_BAYS;i++) {
1329     snprintf(bus_name,sizeof(bus_name),"PA Slot %d",i);
1330     vm->pci_bus_pool[i] = pci_bus_create(bus_name,-1);
1331    
1332     if (!vm->pci_bus_pool[i])
1333     return(-1);
1334     }
1335    
1336     return(0);
1337     }
1338    
1339     /* Create a PA bridge, depending on the midplane */
1340     static int c7200_pa_init_pci_bridge(c7200_t *router,u_int pa_bay,
1341     struct pci_bus *pci_bus,int pci_device)
1342     {
1343     switch(router->midplane_version) {
1344     case 0:
1345     case 1:
1346     dev_dec21050_init(pci_bus,pci_device,router->pa_bay[pa_bay].pci_map);
1347     break;
1348     default:
1349     dev_dec21150_init(pci_bus,pci_device,router->pa_bay[pa_bay].pci_map);
1350     }
1351     return(0);
1352     }
1353    
1354     /*
1355     * Hidden "I/O" PCI bridge hack for PCMCIA controller.
1356     *
1357     * On NPE-175, NPE-225, NPE-300 and NPE-400, PCMCIA controller is
1358     * identified on PCI as Bus=2,Device=16. On NPE-G1, this is Bus=17,Device=16.
1359     *
1360     * However, I don't understand how the bridging between PCI bus 1 and 2
1361     * is done (16 and 17 on NPE-G1).
1362     *
1363     * Maybe I'm missing something about PCI-to-PCI bridge mechanism, or there
1364     * is a special hidden device that does the job silently (it should be
1365     * visible on the PCI bus...)
1366     *
1367     * BTW, it works.
1368     */
1369     static int
1370     c7200_create_io_pci_bridge(c7200_t *router,struct pci_bus *parent_bus)
1371     {
1372     vm_instance_t *vm = router->vm;
1373    
1374     /* Create the PCI bus where the PCMCIA controller will seat */
1375     if (!(vm->pci_bus_pool[16] = pci_bus_create("I/O secondary bus",-1)))
1376     return(-1);
1377    
1378     /* Create the hidden bridge with "special" handling... */
1379     if (!(router->io_pci_bridge = pci_bridge_add(parent_bus)))
1380     return(-1);
1381    
1382     router->io_pci_bridge->skip_bus_check = TRUE;
1383     pci_bridge_map_bus(router->io_pci_bridge,vm->pci_bus_pool[16]);
1384    
1385     router->pcmcia_bus = vm->pci_bus_pool[16];
1386     return(0);
1387     }
1388    
1389     /* Initialize an NPE-100 board */
1390     int c7200_init_npe100(c7200_t *router)
1391     {
1392     vm_instance_t *vm = router->vm;
1393     int i;
1394    
1395     /* Set the processor type: R4600 */
1396     mips64_set_prid(vm->boot_cpu,MIPS_PRID_R4600);
1397    
1398     /* Initialize the Galileo GT-64010 system controller */
1399     if (c7200_init_gt64010(router) == -1)
1400     return(-1);
1401    
1402     /* PCMCIA controller is on bus 0 */
1403     router->pcmcia_bus = vm->pci_bus[0];
1404    
1405     /* Initialize the PA PCI busses */
1406     if (c7200_pa_create_pci_busses(router) == -1)
1407     return(-1);
1408    
1409     /* Create PCI busses for PA Bays 1,3,5 and PA Bays 2,4,6 */
1410     vm->pci_bus_pool[24] = pci_bus_create("PA Slots 1,3,5",-1);
1411     vm->pci_bus_pool[25] = pci_bus_create("PA Slots 2,4,6",-1);
1412    
1413     /* PCI bridges (MB0/MB1, MB0/MB2) */
1414     dev_dec21050_init(vm->pci_bus[0],1,NULL);
1415     dev_dec21050_init(vm->pci_bus[0],2,vm->pci_bus_pool[24]);
1416     dev_dec21050_init(vm->pci_bus[0],3,NULL);
1417     dev_dec21050_init(vm->pci_bus[0],4,vm->pci_bus_pool[25]);
1418    
1419     /* Map the PA PCI busses */
1420     router->pa_bay[0].pci_map = vm->pci_bus[0];
1421    
1422     for(i=1;i<C7200_MAX_PA_BAYS;i++)
1423     router->pa_bay[i].pci_map = vm->pci_bus_pool[i];
1424    
1425     /* PCI bridges for PA Bays 1 to 6 */
1426     c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1);
1427     c7200_pa_init_pci_bridge(router,3,vm->pci_bus_pool[24],2);
1428     c7200_pa_init_pci_bridge(router,5,vm->pci_bus_pool[24],3);
1429    
1430     c7200_pa_init_pci_bridge(router,2,vm->pci_bus_pool[25],1);
1431     c7200_pa_init_pci_bridge(router,4,vm->pci_bus_pool[25],2);
1432     c7200_pa_init_pci_bridge(router,6,vm->pci_bus_pool[25],3);
1433     return(0);
1434     }
1435    
1436     /* Initialize an NPE-150 board */
1437     int c7200_init_npe150(c7200_t *router)
1438     {
1439     vm_instance_t *vm = router->vm;
1440     m_uint32_t bank_size;
1441     int i;
1442    
1443     /* Set the processor type: R4700 */
1444     mips64_set_prid(vm->boot_cpu,MIPS_PRID_R4700);
1445    
1446     /* Initialize the Galileo GT-64010 system controller */
1447     if (c7200_init_gt64010(router) == -1)
1448     return(-1);
1449    
1450     /* PCMCIA controller is on bus 0 */
1451     router->pcmcia_bus = vm->pci_bus[0];
1452    
1453     /* Initialize the PA PCI busses */
1454     if (c7200_pa_create_pci_busses(router) == -1)
1455     return(-1);
1456    
1457     /* Create PCI busses for PA Bays 1,3,5 and PA Bays 2,4,6 */
1458     vm->pci_bus_pool[24] = pci_bus_create("PA Slots 1,3,5",-1);
1459     vm->pci_bus_pool[25] = pci_bus_create("PA Slots 2,4,6",-1);
1460    
1461     /* PCI bridges (MB0/MB1, MB0/MB2) */
1462     dev_dec21050_init(vm->pci_bus[0],1,NULL);
1463     dev_dec21050_init(vm->pci_bus[0],2,vm->pci_bus_pool[24]);
1464     dev_dec21050_init(vm->pci_bus[0],3,NULL);
1465     dev_dec21050_init(vm->pci_bus[0],4,vm->pci_bus_pool[25]);
1466    
1467     /* Map the PA PCI busses */
1468     router->pa_bay[0].pci_map = vm->pci_bus[0];
1469    
1470     for(i=1;i<C7200_MAX_PA_BAYS;i++)
1471     router->pa_bay[i].pci_map = vm->pci_bus_pool[i];
1472    
1473     /* PCI bridges for PA Bays 1 to 6 */
1474     c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1);
1475     c7200_pa_init_pci_bridge(router,3,vm->pci_bus_pool[24],2);
1476     c7200_pa_init_pci_bridge(router,5,vm->pci_bus_pool[24],3);
1477    
1478     c7200_pa_init_pci_bridge(router,2,vm->pci_bus_pool[25],1);
1479     c7200_pa_init_pci_bridge(router,4,vm->pci_bus_pool[25],2);
1480     c7200_pa_init_pci_bridge(router,6,vm->pci_bus_pool[25],3);
1481    
1482     /* Packet SRAM: 1 Mb */
1483     bank_size = 0x80000;
1484    
1485     dev_c7200_sram_init(vm,"sram0",C7200_SRAM_ADDR,bank_size,
1486     vm->pci_bus_pool[24],0);
1487    
1488     dev_c7200_sram_init(vm,"sram1",C7200_SRAM_ADDR+bank_size,bank_size,
1489     vm->pci_bus_pool[25],0);
1490     return(0);
1491     }
1492    
1493     /* Initialize an NPE-175 board */
1494     int c7200_init_npe175(c7200_t *router)
1495     {
1496     vm_instance_t *vm = router->vm;
1497     int i;
1498    
1499     /* Set the processor type: R5271 */
1500     mips64_set_prid(vm->boot_cpu,MIPS_PRID_R527x);
1501    
1502     /* Initialize the Galileo GT-64120 PCI controller */
1503     if (c7200_init_gt64120(router) == -1)
1504     return(-1);
1505    
1506     /* Initialize the PA PCI busses */
1507     if (c7200_pa_create_pci_busses(router) == -1)
1508     return(-1);
1509    
1510     /* Create PCI bus for PA Bay 0 (I/O Card, PCMCIA, Interfaces) */
1511     vm->pci_bus_pool[0] = pci_bus_create("PA Slot 0",-1);
1512    
1513     /* PCI bridge for I/O card device on MB0 */
1514     dev_dec21150_init(vm->pci_bus[0],1,vm->pci_bus_pool[0]);
1515    
1516     /* Create the hidden "I/O" PCI bridge for PCMCIA controller */
1517     c7200_create_io_pci_bridge(router,vm->pci_bus_pool[0]);
1518    
1519     /* Map the PA PCI busses */
1520     for(i=0;i<C7200_MAX_PA_BAYS;i++)
1521     router->pa_bay[i].pci_map = vm->pci_bus_pool[i];
1522    
1523     /* PCI bridges for PA Bays 1 to 6 */
1524     c7200_pa_init_pci_bridge(router,1,vm->pci_bus[0],7);
1525     c7200_pa_init_pci_bridge(router,3,vm->pci_bus[0],8);
1526     c7200_pa_init_pci_bridge(router,5,vm->pci_bus[0],9);
1527    
1528     c7200_pa_init_pci_bridge(router,2,vm->pci_bus[1],7);
1529     c7200_pa_init_pci_bridge(router,4,vm->pci_bus[1],8);
1530     c7200_pa_init_pci_bridge(router,6,vm->pci_bus[1],9);
1531    
1532     /* Enable PEM EEPROM */
1533     c7200_pem_set_eeprom(router);
1534     return(0);
1535     }
1536    
1537     /* Initialize an NPE-200 board */
1538     int c7200_init_npe200(c7200_t *router)
1539     {
1540     vm_instance_t *vm = router->vm;
1541     m_uint32_t bank_size;
1542     int i;
1543    
1544     /* Set the processor type: R5000 */
1545     mips64_set_prid(vm->boot_cpu,MIPS_PRID_R5000);
1546    
1547     /* Initialize the Galileo GT-64010 PCI controller */
1548     if (c7200_init_gt64010(router) == -1)
1549     return(-1);
1550    
1551     /* PCMCIA controller is on bus 0 */
1552     router->pcmcia_bus = vm->pci_bus[0];
1553    
1554     /* Initialize the PA PCI busses */
1555     if (c7200_pa_create_pci_busses(router) == -1)
1556     return(-1);
1557    
1558     /* Create PCI busses for PA Bays 1,3,5 and PA Bays 2,4,6 */
1559     vm->pci_bus_pool[24] = pci_bus_create("PA Slots 1,3,5",-1);
1560     vm->pci_bus_pool[25] = pci_bus_create("PA Slots 2,4,6",-1);
1561    
1562     /* PCI bridges (MB0/MB1, MB0/MB2) */
1563     dev_dec21050_init(vm->pci_bus[0],1,NULL);
1564     dev_dec21050_init(vm->pci_bus[0],2,vm->pci_bus_pool[24]);
1565     dev_dec21050_init(vm->pci_bus[0],3,NULL);
1566     dev_dec21050_init(vm->pci_bus[0],4,vm->pci_bus_pool[25]);
1567    
1568     /* Map the PA PCI busses */
1569     router->pa_bay[0].pci_map = vm->pci_bus[0];
1570    
1571     for(i=1;i<C7200_MAX_PA_BAYS;i++)
1572     router->pa_bay[i].pci_map = vm->pci_bus_pool[i];
1573    
1574     /* PCI bridges for PA Bays 1 to 6 */
1575     c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1);
1576     c7200_pa_init_pci_bridge(router,3,vm->pci_bus_pool[24],2);
1577     c7200_pa_init_pci_bridge(router,5,vm->pci_bus_pool[24],3);
1578    
1579     c7200_pa_init_pci_bridge(router,2,vm->pci_bus_pool[25],1);
1580     c7200_pa_init_pci_bridge(router,4,vm->pci_bus_pool[25],2);
1581     c7200_pa_init_pci_bridge(router,6,vm->pci_bus_pool[25],3);
1582    
1583     /* Packet SRAM: 4 Mb */
1584     bank_size = 0x200000;
1585    
1586     dev_c7200_sram_init(vm,"sram0",C7200_SRAM_ADDR,bank_size,
1587     vm->pci_bus_pool[24],0);
1588    
1589     dev_c7200_sram_init(vm,"sram1",C7200_SRAM_ADDR+bank_size,bank_size,
1590     vm->pci_bus_pool[25],0);
1591     return(0);
1592     }
1593    
1594     /* Initialize an NPE-225 board */
1595     int c7200_init_npe225(c7200_t *router)
1596     {
1597     vm_instance_t *vm = router->vm;
1598     int i;
1599    
1600     /* Set the processor type: R5271 */
1601     mips64_set_prid(vm->boot_cpu,MIPS_PRID_R527x);
1602    
1603     /* Initialize the Galileo GT-64120 PCI controller */
1604     if (c7200_init_gt64120(router) == -1)
1605     return(-1);
1606    
1607     /* Initialize the PA PCI busses */
1608     if (c7200_pa_create_pci_busses(router) == -1)
1609     return(-1);
1610    
1611     /* Create PCI bus for PA Bay 0 (I/O Card, PCMCIA, Interfaces) */
1612     vm->pci_bus_pool[0] = pci_bus_create("PA Slot 0",-1);
1613    
1614     /* PCI bridge for I/O card device on MB0 */
1615     dev_dec21150_init(vm->pci_bus[0],1,vm->pci_bus_pool[0]);
1616    
1617     /* Create the hidden "I/O" PCI bridge for PCMCIA controller */
1618     c7200_create_io_pci_bridge(router,vm->pci_bus_pool[0]);
1619    
1620     /* Map the PA PCI busses */
1621     for(i=0;i<C7200_MAX_PA_BAYS;i++)
1622     router->pa_bay[i].pci_map = vm->pci_bus_pool[i];
1623    
1624     /* PCI bridges for PA Bays 1 to 6 */
1625     c7200_pa_init_pci_bridge(router,1,vm->pci_bus[0],7);
1626     c7200_pa_init_pci_bridge(router,3,vm->pci_bus[0],8);
1627     c7200_pa_init_pci_bridge(router,5,vm->pci_bus[0],9);
1628    
1629     c7200_pa_init_pci_bridge(router,2,vm->pci_bus[1],7);
1630     c7200_pa_init_pci_bridge(router,4,vm->pci_bus[1],8);
1631     c7200_pa_init_pci_bridge(router,6,vm->pci_bus[1],9);
1632    
1633     /* Enable PEM EEPROM */
1634     c7200_pem_set_eeprom(router);
1635     return(0);
1636     }
1637    
1638     /* Initialize an NPE-300 board */
1639     int c7200_init_npe300(c7200_t *router)
1640     {
1641     vm_instance_t *vm = router->vm;
1642     int i;
1643    
1644     /* Set the processor type: R7000 */
1645     mips64_set_prid(vm->boot_cpu,MIPS_PRID_R7000);
1646    
1647     /* 32 Mb of I/O memory */
1648     vm->iomem_size = 32;
1649 dpavlin 4 dev_ram_init(vm,"iomem",vm->ram_mmap,TRUE,NULL,C7200_IOMEM_ADDR,32*1048576);
1650 dpavlin 1
1651     /* Initialize the two Galileo GT-64120 system controllers */
1652     if (c7200_init_dual_gt64120(router) == -1)
1653     return(-1);
1654    
1655     /* Initialize the PA PCI busses */
1656     if (c7200_pa_create_pci_busses(router) == -1)
1657     return(-1);
1658    
1659     /* Create PCI bus for PA Bay 0 (I/O Card, PCMCIA, Interfaces) */
1660     vm->pci_bus_pool[0] = pci_bus_create("PA Slot 0",-1);
1661    
1662     /* Create PCI busses for PA Bays 1,3,5 and PA Bays 2,4,6 */
1663     vm->pci_bus_pool[24] = pci_bus_create("PA Slots 1,3,5",-1);
1664     vm->pci_bus_pool[25] = pci_bus_create("PA Slots 2,4,6",-1);
1665    
1666     /* PCI bridge for I/O card device on MB0 */
1667     dev_dec21150_init(vm->pci_bus[0],1,vm->pci_bus_pool[0]);
1668    
1669     /* Create the hidden "I/O" PCI bridge for PCMCIA controller */
1670     c7200_create_io_pci_bridge(router,vm->pci_bus_pool[0]);
1671    
1672     /* PCI bridges for PA PCI "Head" Busses */
1673     dev_dec21150_init(vm->pci_bus[0],2,vm->pci_bus_pool[24]);
1674     dev_dec21150_init(vm->pci_bus[1],1,vm->pci_bus_pool[25]);
1675    
1676     /* Map the PA PCI busses */
1677     for(i=0;i<C7200_MAX_PA_BAYS;i++)
1678     router->pa_bay[i].pci_map = vm->pci_bus_pool[i];
1679    
1680     /* PCI bridges for PA Bays 1 to 6 */
1681     c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1);
1682     c7200_pa_init_pci_bridge(router,3,vm->pci_bus_pool[24],2);
1683     c7200_pa_init_pci_bridge(router,5,vm->pci_bus_pool[24],3);
1684    
1685     c7200_pa_init_pci_bridge(router,2,vm->pci_bus_pool[25],1);
1686     c7200_pa_init_pci_bridge(router,4,vm->pci_bus_pool[25],2);
1687     c7200_pa_init_pci_bridge(router,6,vm->pci_bus_pool[25],3);
1688     return(0);
1689     }
1690    
1691     /* Initialize an NPE-400 board */
1692     int c7200_init_npe400(c7200_t *router)
1693     {
1694     vm_instance_t *vm = router->vm;
1695     int i;
1696    
1697     /* Set the processor type: R7000 */
1698     mips64_set_prid(vm->boot_cpu,MIPS_PRID_R7000);
1699    
1700     /*
1701     * Add supplemental memory (as "iomem") if we have more than 256 Mb.
1702     */
1703     if (vm->ram_size > C7200_BASE_RAM_LIMIT) {
1704     vm->iomem_size = vm->ram_size - C7200_BASE_RAM_LIMIT;
1705     vm->ram_size = C7200_BASE_RAM_LIMIT;
1706 dpavlin 4 dev_ram_init(vm,"ram1",vm->ram_mmap,TRUE,NULL,
1707 dpavlin 1 C7200_IOMEM_ADDR,vm->iomem_size*1048576);
1708     }
1709    
1710     /* Initialize the Galileo GT-64120 system controller */
1711     if (c7200_init_gt64120(router) == -1)
1712     return(-1);
1713    
1714     /* Initialize the PA PCI busses */
1715     if (c7200_pa_create_pci_busses(router) == -1)
1716     return(-1);
1717    
1718     /* Create PCI bus for PA Bay 0 (I/O Card, PCMCIA, Interfaces) */
1719     vm->pci_bus_pool[0] = pci_bus_create("PA Slot 0",-1);
1720    
1721     /* PCI bridge for I/O card device on MB0 */
1722     dev_dec21050_init(vm->pci_bus[0],1,vm->pci_bus_pool[0]);
1723    
1724     /* Create the hidden "I/O" PCI bridge for PCMCIA controller */
1725     c7200_create_io_pci_bridge(router,vm->pci_bus_pool[0]);
1726    
1727     /* Map the PA PCI busses */
1728     for(i=0;i<C7200_MAX_PA_BAYS;i++)
1729     router->pa_bay[i].pci_map = vm->pci_bus_pool[i];
1730    
1731     /* PCI bridges for PA Bays 1 to 6 */
1732     c7200_pa_init_pci_bridge(router,1,vm->pci_bus[0],7);
1733     c7200_pa_init_pci_bridge(router,3,vm->pci_bus[0],8);
1734     c7200_pa_init_pci_bridge(router,5,vm->pci_bus[0],9);
1735    
1736     c7200_pa_init_pci_bridge(router,2,vm->pci_bus[1],7);
1737     c7200_pa_init_pci_bridge(router,4,vm->pci_bus[1],8);
1738     c7200_pa_init_pci_bridge(router,6,vm->pci_bus[1],9);
1739     return(0);
1740     }
1741    
1742     /* Initialize an NPE-G1 board (XXX not working) */
1743     int c7200_init_npeg1(c7200_t *router)
1744     {
1745     vm_instance_t *vm = router->vm;
1746     int i;
1747    
1748     /* Just some tests */
1749     mips64_set_prid(vm->boot_cpu,MIPS_PRID_BCM1250);
1750     vm->pci_bus[0] = pci_bus_create("HT/PCI bus",0);
1751    
1752     /* SB-1 System control devices */
1753     dev_sb1_init(vm);
1754    
1755     /* SB-1 I/O devices */
1756     dev_sb1_io_init(vm,C7200_DUART_IRQ);
1757    
1758     /* SB-1 PCI bus configuration zone */
1759     dev_sb1_pci_init(vm,"pci_cfg",0xFE000000ULL);
1760    
1761     /* Initialize the PA PCI busses */
1762     if (c7200_pa_create_pci_busses(router) == -1)
1763     return(-1);
1764    
1765     /* Create PCI bus for PA Bay 0 (I/O Card, PCMCIA, Interfaces) */
1766     vm->pci_bus_pool[0] = pci_bus_create("PA Slot 0",-1);
1767    
1768     /* Create PCI busses for PA Bays 1,3,5 and PA Bays 2,4,6 */
1769     vm->pci_bus_pool[24] = pci_bus_create("PA Slots 1,3,5",-1);
1770     vm->pci_bus_pool[25] = pci_bus_create("PA Slots 2,4,6",-1);
1771    
1772     /* HyperTransport/PCI bridges */
1773     dev_ap1011_init(vm->pci_bus_pool[28],0,NULL);
1774     dev_ap1011_init(vm->pci_bus_pool[28],1,vm->pci_bus_pool[24]);
1775     dev_ap1011_init(vm->pci_bus_pool[28],2,vm->pci_bus_pool[25]);
1776    
1777     /* PCI bridge for I/O card device on MB0 */
1778     dev_dec21150_init(vm->pci_bus[0],3,vm->pci_bus_pool[0]);
1779    
1780     /* Create the hidden "I/O" PCI bridge for PCMCIA controller */
1781     c7200_create_io_pci_bridge(router,vm->pci_bus_pool[0]);
1782    
1783     /* Map the PA PCI busses */
1784     router->pa_bay[0].pci_map = vm->pci_bus[0];
1785    
1786     for(i=1;i<C7200_MAX_PA_BAYS;i++)
1787     router->pa_bay[i].pci_map = vm->pci_bus_pool[i];
1788    
1789     /* PCI bridges for PA Bays 1 to 6 */
1790     c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1);
1791     c7200_pa_init_pci_bridge(router,3,vm->pci_bus_pool[24],2);
1792     c7200_pa_init_pci_bridge(router,5,vm->pci_bus_pool[24],3);
1793    
1794     c7200_pa_init_pci_bridge(router,2,vm->pci_bus_pool[25],1);
1795     c7200_pa_init_pci_bridge(router,4,vm->pci_bus_pool[25],2);
1796     c7200_pa_init_pci_bridge(router,6,vm->pci_bus_pool[25],3);
1797     return(0);
1798     }
1799    
1800     /* Show C7200 hardware info */
1801     void c7200_show_hardware(c7200_t *router)
1802     {
1803     vm_instance_t *vm = router->vm;
1804    
1805     printf("C7200 instance '%s' (id %d):\n",vm->name,vm->instance_id);
1806    
1807     printf(" VM Status : %d\n",vm->status);
1808     printf(" RAM size : %u Mb\n",vm->ram_size);
1809     printf(" IOMEM size : %u Mb\n",vm->iomem_size);
1810     printf(" NVRAM size : %u Kb\n",vm->nvram_size);
1811     printf(" NPE model : %s\n",router->npe_driver->npe_type);
1812     printf(" Midplane : %s\n",router->midplane_type);
1813     printf(" IOS image : %s\n\n",vm->ios_image);
1814    
1815     if (vm->debug_level > 0) {
1816     dev_show_list(vm);
1817     pci_dev_show_list(vm->pci_bus[0]);
1818     pci_dev_show_list(vm->pci_bus[1]);
1819     printf("\n");
1820     }
1821     }
1822    
1823     /* Initialize default parameters for a C7200 */
1824     void c7200_init_defaults(c7200_t *router)
1825     {
1826     vm_instance_t *vm = router->vm;
1827     n_eth_addr_t *m;
1828     m_uint16_t pid;
1829    
1830     pid = (m_uint16_t)getpid();
1831    
1832     /* Generate a chassis MAC address based on the instance ID */
1833     m = &router->mac_addr;
1834 dpavlin 4 m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm);
1835 dpavlin 1 m->eth_addr_byte[1] = vm->instance_id & 0xFF;
1836     m->eth_addr_byte[2] = pid >> 8;
1837     m->eth_addr_byte[3] = pid & 0xFF;
1838     m->eth_addr_byte[4] = 0x00;
1839     m->eth_addr_byte[5] = 0x00;
1840    
1841     c7200_init_eeprom_groups(router);
1842     c7200_npe_set_type(router,C7200_DEFAULT_NPE_TYPE);
1843     c7200_midplane_set_type(router,C7200_DEFAULT_MIDPLANE);
1844    
1845     vm->ram_mmap = C7200_DEFAULT_RAM_MMAP;
1846     vm->ram_size = C7200_DEFAULT_RAM_SIZE;
1847     vm->rom_size = C7200_DEFAULT_ROM_SIZE;
1848     vm->nvram_size = C7200_DEFAULT_NVRAM_SIZE;
1849     vm->iomem_size = 0;
1850     vm->conf_reg_setup = C7200_DEFAULT_CONF_REG;
1851     vm->clock_divisor = C7200_DEFAULT_CLOCK_DIV;
1852     vm->nvram_rom_space = C7200_NVRAM_ROM_RES_SIZE;
1853    
1854     vm->pcmcia_disk_size[0] = C7200_DEFAULT_DISK0_SIZE;
1855     vm->pcmcia_disk_size[1] = C7200_DEFAULT_DISK1_SIZE;
1856 dpavlin 4
1857     /* Enable NVRAM operations to load/store configs */
1858     vm->nvram_extract_config = c7200_nvram_extract_config;
1859     vm->nvram_push_config = c7200_nvram_push_config;
1860 dpavlin 1 }
1861    
1862     /* Run the checklist */
1863     int c7200_checklist(c7200_t *router)
1864     {
1865     struct vm_instance *vm = router->vm;
1866     int res = 0;
1867    
1868     res += vm_object_check(vm,"ram");
1869     res += vm_object_check(vm,"rom");
1870     res += vm_object_check(vm,"nvram");
1871     res += vm_object_check(vm,"zero");
1872    
1873     if (res < 0)
1874     vm_error(vm,"incomplete initialization (no memory?)\n");
1875    
1876     return(res);
1877     }
1878    
1879     /* Initialize the C7200 Platform */
1880     int c7200_init_platform(c7200_t *router)
1881     {
1882     struct vm_instance *vm = router->vm;
1883     struct c7200_pa_bay *pa_bay;
1884     cpu_mips_t *cpu0;
1885     int i;
1886    
1887     /* Copy config register setup into "active" config register */
1888     vm->conf_reg = vm->conf_reg_setup;
1889    
1890     /* Create Console and AUX ports */
1891     vm_init_vtty(vm);
1892    
1893     /* Check that the amount of RAM is valid */
1894     if (vm->ram_size > router->npe_driver->max_ram_size) {
1895     vm_error(vm,"%u is not a valid RAM size for this NPE. "
1896     "Fallback to %u Mb.\n\n",
1897     vm->ram_size,router->npe_driver->max_ram_size);
1898    
1899     vm->ram_size = router->npe_driver->max_ram_size;
1900     }
1901    
1902     /* Create a CPU group */
1903     vm->cpu_group = cpu_group_create("System CPU");
1904    
1905     /* Initialize the virtual MIPS processor */
1906     if (!(cpu0 = cpu_create(vm,0))) {
1907     vm_error(vm,"unable to create CPU0!\n");
1908     return(-1);
1909     }
1910    
1911     /* Add this CPU to the system CPU group */
1912     cpu_group_add(vm->cpu_group,cpu0);
1913     vm->boot_cpu = cpu0;
1914    
1915     /* Mark the Network IO interrupt as high priority */
1916     cpu0->irq_idle_preempt[C7200_NETIO_IRQ] = TRUE;
1917 dpavlin 4 cpu0->irq_idle_preempt[C7200_GT64K_IRQ] = TRUE;
1918 dpavlin 1
1919     /* Copy some parameters from VM to CPU0 (idle PC, ...) */
1920     cpu0->idle_pc = vm->idle_pc;
1921    
1922     if (vm->timer_irq_check_itv)
1923     cpu0->timer_irq_check_itv = vm->timer_irq_check_itv;
1924    
1925     /*
1926     * On the C7200, bit 33 of physical addresses is used to bypass L2 cache.
1927     * We clear it systematically.
1928     */
1929     cpu0->addr_bus_mask = C7200_ADDR_BUS_MASK;
1930    
1931     /* Remote emulator control */
1932     dev_remote_control_init(vm,0x16000000,0x1000);
1933    
1934     /* Bootflash */
1935     dev_bootflash_init(vm,"bootflash",C7200_BOOTFLASH_ADDR,(8 * 1048576));
1936    
1937     /* NVRAM and calendar */
1938     dev_nvram_init(vm,"nvram",router->npe_driver->nvram_addr,
1939     vm->nvram_size*1024,&vm->conf_reg);
1940    
1941     /* Bit-bucket zone */
1942     dev_zero_init(vm,"zero",C7200_BITBUCKET_ADDR,0xc00000);
1943    
1944     /* Midplane FPGA */
1945     dev_c7200_mpfpga_init(router,C7200_MPFPGA_ADDR,0x1000);
1946    
1947     /* IO FPGA */
1948     if (dev_c7200_iofpga_init(router,C7200_IOFPGA_ADDR,0x1000) == -1)
1949     return(-1);
1950    
1951     /* Initialize the NPE board */
1952     if (router->npe_driver->npe_init(router) == -1)
1953     return(-1);
1954    
1955     /* Initialize RAM */
1956 dpavlin 4 vm_ram_init(vm,0x00000000ULL);
1957 dpavlin 1
1958     /* Initialize ROM */
1959     if (!vm->rom_filename) {
1960     /* use embedded ROM */
1961     dev_rom_init(vm,"rom",C7200_ROM_ADDR,vm->rom_size*1048576);
1962     } else {
1963     /* use alternate ROM */
1964 dpavlin 4 dev_ram_init(vm,"rom",TRUE,TRUE,NULL,
1965     C7200_ROM_ADDR,vm->rom_size*1048576);
1966 dpavlin 1 }
1967    
1968     /* PCI IO space */
1969     if (!(vm->pci_io_space = pci_io_data_init(vm,C7200_PCI_IO_ADDR)))
1970     return(-1);
1971    
1972     /* Cirrus Logic PD6729 (PCI-to-PCMCIA host adapter) */
1973     dev_clpd6729_init(vm,router->pcmcia_bus,
1974     router->npe_driver->clpd6729_pci_dev,
1975     vm->pci_io_space,0x402,0x403);
1976    
1977     /* Initialize Port Adapters */
1978     for(i=0;i<C7200_MAX_PA_BAYS;i++) {
1979     pa_bay = &router->pa_bay[i];
1980    
1981     if (!pa_bay->dev_type)
1982     continue;
1983    
1984     if (c7200_pa_init(router,i) == -1) {
1985     vm_error(vm,"unable to create Port Adapter \"%s\"\n",
1986     pa_bay->dev_type);
1987     return(-1);
1988     }
1989     }
1990    
1991     /* By default, initialize a C7200-IO-FE in slot 0 if nothing found */
1992     if (!router->pa_bay[0].drv_info) {
1993     c7200_pa_add_binding(router,"C7200-IO-FE",0);
1994     c7200_pa_init(router,0);
1995     }
1996    
1997     /* Verify the check list */
1998     if (c7200_checklist(router) == -1)
1999     return(-1);
2000    
2001     /* Show device list */
2002     c7200_show_hardware(router);
2003     return(0);
2004     }
2005    
2006     /* Boot the IOS image */
2007     int c7200_boot_ios(c7200_t *router)
2008     {
2009     vm_instance_t *vm = router->vm;
2010    
2011     if (!vm->boot_cpu)
2012     return(-1);
2013    
2014     /* Suspend CPU activity since we will restart directly from ROM */
2015     vm_suspend(vm);
2016    
2017     /* Check that CPU activity is really suspended */
2018     if (cpu_group_sync_state(vm->cpu_group) == -1) {
2019     vm_error(vm,"unable to sync with system CPUs.\n");
2020     return(-1);
2021     }
2022    
2023     /* Reset the boot CPU */
2024     mips64_reset(vm->boot_cpu);
2025    
2026     /* Load IOS image */
2027     if (mips64_load_elf_image(vm->boot_cpu,vm->ios_image,
2028 dpavlin 4 (vm->ghost_status == VM_GHOST_RAM_USE),
2029     &vm->ios_entry_point) < 0)
2030 dpavlin 1 {
2031     vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image);
2032     return(-1);
2033     }
2034    
2035     /* Launch the simulation */
2036     printf("\nC7200 '%s': starting simulation (CPU0 PC=0x%llx), "
2037     "JIT %sabled.\n",
2038     vm->name,vm->boot_cpu->pc,vm->jit_use ? "en":"dis");
2039    
2040     vm_log(vm,"C7200_BOOT",
2041     "starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n",
2042     vm->boot_cpu->pc,vm->boot_cpu->idle_pc,vm->jit_use ? "on":"off");
2043    
2044     /* Start main CPU */
2045 dpavlin 4 if (vm->ghost_status != VM_GHOST_RAM_GENERATE) {
2046     vm->status = VM_STATUS_RUNNING;
2047     cpu_start(vm->boot_cpu);
2048     } else {
2049     vm->status = VM_STATUS_SHUTDOWN;
2050     }
2051 dpavlin 1 return(0);
2052     }
2053    
2054     /* Initialize a Cisco 7200 instance */
2055     int c7200_init_instance(c7200_t *router)
2056     {
2057     vm_instance_t *vm = router->vm;
2058     m_uint32_t rom_entry_point;
2059     cpu_mips_t *cpu0;
2060    
2061     /* Initialize the C7200 platform */
2062     if (c7200_init_platform(router) == -1) {
2063     vm_error(vm,"unable to initialize the platform hardware.\n");
2064     return(-1);
2065     }
2066    
2067     /* Load IOS configuration file */
2068     if (vm->ios_config != NULL) {
2069     vm_nvram_push_config(vm,vm->ios_config);
2070     vm->conf_reg &= ~0x40;
2071     }
2072    
2073     /* Load ROM (ELF image or embedded) */
2074     cpu0 = vm->boot_cpu;
2075     rom_entry_point = (m_uint32_t)MIPS_ROM_PC;
2076    
2077     if ((vm->rom_filename != NULL) &&
2078 dpavlin 4 (mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0))
2079 dpavlin 1 {
2080     vm_error(vm,"unable to load alternate ROM '%s', "
2081     "fallback to embedded ROM.\n\n",vm->rom_filename);
2082     vm->rom_filename = NULL;
2083     }
2084    
2085     /* Load symbol file */
2086     if (vm->sym_filename) {
2087     mips64_sym_load_file(cpu0,vm->sym_filename);
2088     cpu0->sym_trace = 1;
2089     }
2090    
2091     return(c7200_boot_ios(router));
2092     }
2093    
2094     /* Stop a Cisco 7200 instance */
2095     int c7200_stop_instance(c7200_t *router)
2096     {
2097     vm_instance_t *vm = router->vm;
2098    
2099     printf("\nC7200 '%s': stopping simulation.\n",vm->name);
2100     vm_log(vm,"C7200_STOP","stopping simulation.\n");
2101    
2102     /* Stop all CPUs */
2103     if (vm->cpu_group != NULL) {
2104     vm_stop(vm);
2105    
2106     if (cpu_group_sync_state(vm->cpu_group) == -1) {
2107     vm_error(vm,"unable to sync with system CPUs.\n");
2108     return(-1);
2109     }
2110     }
2111    
2112     /* Free resources that were used during execution to emulate hardware */
2113     c7200_free_hw_ressources(router);
2114     vm_hardware_shutdown(vm);
2115     return(0);
2116     }
2117    
2118     /* Trigger an OIR event */
2119     int c7200_trigger_oir_event(c7200_t *router,u_int slot_mask)
2120     {
2121     /* An OIR IRQ without reason could lead to stop the system */
2122     if (!slot_mask) return(-1);
2123    
2124     router->oir_status = slot_mask;
2125     vm_set_irq(router->vm,C7200_OIR_IRQ);
2126     return(0);
2127     }
2128    
2129     /* Initialize a new PA while the virtual router is online (OIR) */
2130     int c7200_pa_init_online(c7200_t *router,u_int pa_bay)
2131     {
2132     vm_instance_t *vm = router->vm;
2133    
2134     if (!pa_bay) {
2135     vm_error(vm,"OIR not supported on slot 0.\n");
2136     return(-1);
2137     }
2138    
2139     /*
2140     * Suspend CPU activity while adding new hardware (since we change the
2141     * memory maps).
2142     */
2143     vm_suspend(vm);
2144    
2145     /* Check that CPU activity is really suspended */
2146     if (cpu_group_sync_state(vm->cpu_group) == -1) {
2147     vm_error(vm,"unable to sync with system CPUs.\n");
2148     return(-1);
2149     }
2150    
2151     /* Add the new hardware elements */
2152     if (c7200_pa_init(router,pa_bay) == -1)
2153     return(-1);
2154    
2155     /* Resume normal operations */
2156     vm_resume(vm);
2157    
2158     /* Now, we can safely trigger the OIR event */
2159     c7200_trigger_oir_event(router,1 << pa_bay);
2160     return(0);
2161     }
2162    
2163     /* Stop a PA while the virtual router is online (OIR) */
2164     int c7200_pa_stop_online(c7200_t *router,u_int pa_bay)
2165     {
2166     vm_instance_t *vm = router->vm;
2167     struct c7200_pa_bay *bay;
2168    
2169     if (!pa_bay) {
2170     vm_error(vm,"OIR not supported on slot 0.\n");
2171     return(-1);
2172     }
2173    
2174     if (!(bay = c7200_pa_get_info(router,pa_bay)))
2175     return(-1);
2176    
2177     /* The PA driver must be initialized */
2178     if (!bay->dev_type || !bay->pa_driver) {
2179     vm_error(vm,"trying to shut down empty slot %u.\n",pa_bay);
2180     return(-1);
2181     }
2182    
2183     /* Disable all NIOs to stop traffic forwarding */
2184     c7200_pa_disable_all_nio(router,pa_bay);
2185    
2186     /* We can safely trigger the OIR event */
2187     c7200_trigger_oir_event(router,1 << pa_bay);
2188    
2189     /*
2190     * Suspend CPU activity while removing the hardware (since we change the
2191     * memory maps).
2192     */
2193     vm_suspend(vm);
2194    
2195     /* Device removal */
2196     c7200_pa_shutdown(router,pa_bay);
2197    
2198     /* Resume normal operations */
2199     vm_resume(vm);
2200     return(0);
2201     }

  ViewVC Help
Powered by ViewVC 1.1.26