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

Contents of /trunk/dev_c7200.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations)
Sat Oct 6 16:29:14 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7/dev_c7200.c
File MIME type: text/plain
File size: 79372 byte(s)
dynamips-0.2.7

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

  ViewVC Help
Powered by ViewVC 1.1.26