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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations)
Sat Oct 6 16:05:34 2007 UTC (13 years, 2 months ago) by dpavlin
File MIME type: text/plain
File size: 62940 byte(s)
dynamips-0.2.6-RC2

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 cisco_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 cisco_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 cisco_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 /* 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 m_uint64_t addr,cfg_addr;
261 m_uint32_t cklen;
262 m_uint16_t cksum;
263
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 cfg_addr = addr + 0x2c;
269
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 physmem_copy_u16_to_vm(vm,addr+0x0e,0x0000); /* IOS version */
276
277 /* Store file contents to NVRAM */
278 physmem_copy_to_vm(vm,buffer,cfg_addr,len);
279
280 /* Write config addresses + size */
281 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 return(0);
290 }
291
292 /* Get an EEPROM for a given NPE model */
293 static const struct cisco_eeprom *c7200_get_cpu_eeprom(char *npe_name)
294 {
295 return(cisco_eeprom_find(c7200_cpu_eeprom,npe_name));
296 }
297
298 /* Get an EEPROM for a given midplane model */
299 static const struct cisco_eeprom *
300 c7200_get_midplane_eeprom(char *midplane_name)
301 {
302 return(cisco_eeprom_find(c7200_midplane_eeprom,midplane_name));
303 }
304
305 /* Get a PEM EEPROM for a given NPE model */
306 static const struct cisco_eeprom *c7200_get_pem_eeprom(char *npe_name)
307 {
308 return(cisco_eeprom_find(c7200_pem_eeprom,npe_name));
309 }
310
311 /* Set the base MAC address of the chassis */
312 static int c7200_burn_mac_addr(c7200_t *router,n_eth_addr_t *addr)
313 {
314 m_uint8_t eeprom_ver;
315
316 /* Read EEPROM format version */
317 cisco_eeprom_get_byte(&router->mp_eeprom,0,&eeprom_ver);
318
319 if (eeprom_ver != 1) {
320 vm_error(router->vm,"c7200_burn_mac_addr: unable to handle "
321 "EEPROM version %u\n",eeprom_ver);
322 return(-1);
323 }
324
325 cisco_eeprom_set_region(&router->mp_eeprom,12,addr->eth_addr_byte,6);
326 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 /* 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 /* 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 const struct cisco_eeprom *eeprom;
483
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 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 return(0);
496 }
497
498 /* Set PEM eeprom definition */
499 static int c7200_pem_set_eeprom(c7200_t *router)
500 {
501 const struct cisco_eeprom *eeprom;
502
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 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 return(0);
515 }
516
517 /* Set PA EEPROM definition */
518 int c7200_pa_set_eeprom(c7200_t *router,u_int pa_bay,
519 const struct cisco_eeprom *eeprom)
520 {
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
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 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 cisco_eeprom_free(&router->pa_bay[pa_bay].eeprom);
543 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 return(FALSE);
551
552 return(cisco_eeprom_valid(&router->pa_bay[pa_bay].eeprom));
553 }
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 /* 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 /* 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 const struct cisco_eeprom *eeprom;
1196 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 /* 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
1215 /* Set the chassis base MAC address */
1216 c7200_burn_mac_addr(router,&router->mac_addr);
1217
1218 /* Get the midplane version */
1219 cisco_eeprom_get_byte(&router->mp_eeprom,2,&version);
1220 router->midplane_version = version;
1221 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 c7200_burn_mac_addr(router,&router->mac_addr);
1235 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