/[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 7 - (hide annotations)
Sat Oct 6 16:23:47 2007 UTC (16 years, 6 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7-RC1/dev_c7200.c
File MIME type: text/plain
File size: 77042 byte(s)
dynamips-0.2.7-RC1

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

  ViewVC Help
Powered by ViewVC 1.1.26