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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (hide annotations)
Sat Oct 6 16:05:34 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.6-RC2/dev_c7200.c
File MIME type: text/plain
File size: 62940 byte(s)
dynamips-0.2.6-RC2

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

  ViewVC Help
Powered by ViewVC 1.1.26