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

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

  ViewVC Help
Powered by ViewVC 1.1.26