/[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 12 - (show annotations)
Sat Oct 6 16:45:40 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 63984 byte(s)
make working copy

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

  ViewVC Help
Powered by ViewVC 1.1.26