/[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

Annotation of /trunk/dev_c7200.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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

  ViewVC Help
Powered by ViewVC 1.1.26