/[dynamips]/upstream/dynamips-0.2.6-RC5/dev_c7200.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (show annotations)
Sat Oct 6 16:08:03 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.6-RC4/dev_c7200.c
File MIME type: text/plain
File size: 63905 byte(s)
dynamips-0.2.6-RC4

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

  ViewVC Help
Powered by ViewVC 1.1.26