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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Sat Oct 6 16:01:44 2007 UTC (12 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 63228 byte(s)
import 0.2.5 from upstream

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

  ViewVC Help
Powered by ViewVC 1.1.26