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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (show annotations)
Sat Oct 6 16:23:47 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 77042 byte(s)
dynamips-0.2.7-RC1

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

  ViewVC Help
Powered by ViewVC 1.1.26