/[dynamips]/upstream/dynamips-0.2.6-RC1/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

Contents of /upstream/dynamips-0.2.6-RC1/dev_c7200.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations)
Sat Oct 6 16:03:58 2007 UTC (12 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 63762 byte(s)
import dynamips-0.2.6-RC1

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

  ViewVC Help
Powered by ViewVC 1.1.26