1 |
/* |
/* |
2 |
* Cisco 7200 (Predator) simulation platform. |
* Cisco router simulation platform. |
3 |
* Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) |
* Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) |
4 |
* |
* |
5 |
* Generic Cisco 7200 routines and definitions (EEPROM,...). |
* Generic Cisco 7200 routines and definitions (EEPROM,...). |
12 |
#include <sys/types.h> |
#include <sys/types.h> |
13 |
#include <assert.h> |
#include <assert.h> |
14 |
|
|
15 |
#include "mips64.h" |
#include "cpu.h" |
16 |
|
#include "vm.h" |
17 |
#include "dynamips.h" |
#include "dynamips.h" |
18 |
#include "memory.h" |
#include "memory.h" |
19 |
|
#include "ppc32_mem.h" |
20 |
#include "device.h" |
#include "device.h" |
21 |
#include "pci_io.h" |
#include "pci_io.h" |
22 |
|
#include "dev_gt.h" |
23 |
|
#include "dev_mv64460.h" |
24 |
#include "cisco_eeprom.h" |
#include "cisco_eeprom.h" |
25 |
|
#include "dev_rom.h" |
26 |
#include "dev_c7200.h" |
#include "dev_c7200.h" |
27 |
|
#include "dev_c7200_mpfpga.h" |
28 |
#include "dev_vtty.h" |
#include "dev_vtty.h" |
29 |
#include "registry.h" |
#include "registry.h" |
30 |
#include "net.h" |
#include "net.h" |
93 |
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
94 |
}; |
}; |
95 |
|
|
96 |
|
/* NPE-G2 */ |
97 |
|
static m_uint16_t eeprom_cpu_npeg2_data[64] = { |
98 |
|
0x04FF, 0x4004, 0xCA41, 0x0201, 0x8744, 0x19BC, 0x0182, 0x4928, |
99 |
|
0x5901, 0x42FF, 0xFFC1, 0x8B43, 0x534A, 0x3039, 0x3435, 0x3239, |
100 |
|
0x3237, 0x0400, 0x0201, 0x851C, 0x1DA2, 0x01CB, 0x864E, 0x5045, |
101 |
|
0x2D47, 0x3280, 0x0000, 0x0000, 0x8956, 0x3031, 0x2DFF, 0xFFFF, |
102 |
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
103 |
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
104 |
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
105 |
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x15FF, |
106 |
|
}; |
107 |
|
|
108 |
/* |
/* |
109 |
* CPU EEPROM array. |
* CPU EEPROM array. |
110 |
*/ |
*/ |
111 |
static struct c7200_eeprom c7200_cpu_eeprom[] = { |
static struct cisco_eeprom c7200_cpu_eeprom[] = { |
112 |
{ "npe-100", eeprom_cpu_npe100_data, sizeof(eeprom_cpu_npe100_data)/2 }, |
{ "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 }, |
{ "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 }, |
{ "npe-175", eeprom_cpu_npe175_data, sizeof(eeprom_cpu_npe175_data)/2 }, |
117 |
{ "npe-300", eeprom_cpu_npe300_data, sizeof(eeprom_cpu_npe300_data)/2 }, |
{ "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 }, |
{ "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 }, |
{ "npe-g1" , eeprom_cpu_npeg1_data , sizeof(eeprom_cpu_npeg1_data)/2 }, |
120 |
|
{ "npe-g2" , eeprom_cpu_npeg2_data , sizeof(eeprom_cpu_npeg2_data)/2 }, |
121 |
{ NULL, NULL, 0 }, |
{ NULL, NULL, 0 }, |
122 |
}; |
}; |
123 |
|
|
144 |
/* |
/* |
145 |
* Midplane EEPROM array. |
* Midplane EEPROM array. |
146 |
*/ |
*/ |
147 |
static struct c7200_eeprom c7200_midplane_eeprom[] = { |
static struct cisco_eeprom c7200_midplane_eeprom[] = { |
148 |
{ "std", eeprom_midplane_data, sizeof(eeprom_midplane_data)/2 }, |
{ "std", eeprom_midplane_data, sizeof(eeprom_midplane_data)/2 }, |
149 |
{ "vxr", eeprom_vxr_midplane_data, sizeof(eeprom_vxr_midplane_data)/2 }, |
{ "vxr", eeprom_vxr_midplane_data, sizeof(eeprom_vxr_midplane_data)/2 }, |
150 |
{ NULL, NULL, 0 }, |
{ NULL, NULL, 0 }, |
169 |
/* |
/* |
170 |
* PEM EEPROM array. |
* PEM EEPROM array. |
171 |
*/ |
*/ |
172 |
static struct c7200_eeprom c7200_pem_eeprom[] = { |
static struct cisco_eeprom c7200_pem_eeprom[] = { |
173 |
{ "npe-175", eeprom_pem_npe175_data, sizeof(eeprom_pem_npe175_data)/2 }, |
{ "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 }, |
{ "npe-225", eeprom_pem_npe225_data, sizeof(eeprom_pem_npe225_data)/2 }, |
175 |
{ NULL, NULL, 0 }, |
{ NULL, NULL, 0 }, |
178 |
/* ======================================================================== */ |
/* ======================================================================== */ |
179 |
/* Port Adapter Drivers */ |
/* Port Adapter Drivers */ |
180 |
/* ======================================================================== */ |
/* ======================================================================== */ |
181 |
static struct c7200_pa_driver *pa_drivers[] = { |
static struct cisco_card_driver *pa_drivers[] = { |
182 |
&dev_c7200_io_fe_driver, |
&dev_c7200_iocard_fe_driver, |
183 |
|
&dev_c7200_iocard_2fe_driver, |
184 |
|
&dev_c7200_iocard_ge_e_driver, |
185 |
&dev_c7200_pa_fe_tx_driver, |
&dev_c7200_pa_fe_tx_driver, |
186 |
|
&dev_c7200_pa_2fe_tx_driver, |
187 |
|
&dev_c7200_pa_ge_driver, |
188 |
&dev_c7200_pa_4e_driver, |
&dev_c7200_pa_4e_driver, |
189 |
&dev_c7200_pa_8e_driver, |
&dev_c7200_pa_8e_driver, |
190 |
&dev_c7200_pa_4t_driver, |
&dev_c7200_pa_4t_driver, |
191 |
&dev_c7200_pa_8t_driver, |
&dev_c7200_pa_8t_driver, |
192 |
&dev_c7200_pa_a1_driver, |
&dev_c7200_pa_a1_driver, |
193 |
&dev_c7200_pa_pos_oc3_driver, |
&dev_c7200_pa_pos_oc3_driver, |
194 |
&dev_c7200_pa_4b_driver, |
&dev_c7200_pa_4b_driver, |
195 |
|
&dev_c7200_pa_mc8te1_driver, |
196 |
NULL, |
NULL, |
197 |
}; |
}; |
198 |
|
|
210 |
DECLARE_NPE(npe300); |
DECLARE_NPE(npe300); |
211 |
DECLARE_NPE(npe400); |
DECLARE_NPE(npe400); |
212 |
DECLARE_NPE(npeg1); |
DECLARE_NPE(npeg1); |
213 |
|
DECLARE_NPE(npeg2); |
214 |
|
|
215 |
static struct c7200_npe_driver npe_drivers[] = { |
static struct c7200_npe_driver npe_drivers[] = { |
216 |
{ "npe-100" , c7200_init_npe100, 256, 1, C7200_NVRAM_ADDR, 0, 5, 0, 6 }, |
{ "npe-100" , C7200_NPE_FAMILY_MIPS, c7200_init_npe100, 256, 1, |
217 |
{ "npe-150" , c7200_init_npe150, 256, 1, C7200_NVRAM_ADDR, 0, 5, 0, 6 }, |
C7200_NVRAM_ADDR, TRUE, 0, 5, 0, 6 }, |
218 |
{ "npe-175" , c7200_init_npe175, 256, 1, C7200_NVRAM_ADDR, 2, 16, 1, 0 }, |
{ "npe-150" , C7200_NPE_FAMILY_MIPS, c7200_init_npe150, 256, 1, |
219 |
{ "npe-200" , c7200_init_npe200, 256, 1, C7200_NVRAM_ADDR, 0, 5, 0, 6 }, |
C7200_NVRAM_ADDR, TRUE, 0, 5, 0, 6 }, |
220 |
{ "npe-225" , c7200_init_npe225, 256, 1, C7200_NVRAM_ADDR, 2, 16, 1, 0 }, |
{ "npe-175" , C7200_NPE_FAMILY_MIPS, c7200_init_npe175, 256, 1, |
221 |
{ "npe-300" , c7200_init_npe300, 256, 1, C7200_NVRAM_ADDR, 2, 16, 1, 0 }, |
C7200_NVRAM_ADDR, TRUE, 2, 16, 1, 0 }, |
222 |
{ "npe-400" , c7200_init_npe400, 512, 1, C7200_NVRAM_ADDR, 2, 16, 1, 0 }, |
{ "npe-200" , C7200_NPE_FAMILY_MIPS, c7200_init_npe200, 256, 1, |
223 |
{ "npe-g1" , c7200_init_npeg1, 1024, 0, |
C7200_NVRAM_ADDR, TRUE, 0, 5, 0, 6 }, |
224 |
C7200_NPEG1_NVRAM_ADDR, 17, 16, 16, 0 }, |
{ "npe-225" , C7200_NPE_FAMILY_MIPS, c7200_init_npe225, 256, 1, |
225 |
{ NULL , NULL }, |
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 |
/* Empty EEPROM for PAs */ |
C7200_NVRAM_ADDR, TRUE, 2, 16, 1, 0 }, |
230 |
/* ======================================================================== */ |
{ "npe-g1" , C7200_NPE_FAMILY_MIPS, c7200_init_npeg1, 1024, 0, |
231 |
static const m_uint16_t eeprom_pa_empty[64] = { |
C7200_G1_NVRAM_ADDR, FALSE, 17, 16, 16, 0 }, |
232 |
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
{ "npe-g2" , C7200_NPE_FAMILY_PPC , c7200_init_npeg2, 1024, 0, |
233 |
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
C7200_G2_NVRAM_ADDR, FALSE, 17, 16, 16, 0 }, |
234 |
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
{ NULL, -1, NULL, -1, -1, 0, -1, -1, -1, -1 }, |
|
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, |
|
235 |
}; |
}; |
236 |
|
|
237 |
/* ======================================================================== */ |
/* ======================================================================== */ |
238 |
/* Cisco 7200 router instances */ |
/* Cisco 7200 router instances */ |
239 |
/* ======================================================================== */ |
/* ======================================================================== */ |
240 |
|
|
241 |
|
/* Initialize default parameters for a C7200 */ |
242 |
|
static void c7200_init_defaults(c7200_t *router); |
243 |
|
|
244 |
/* Directly extract the configuration from the NVRAM device */ |
/* Directly extract the configuration from the NVRAM device */ |
245 |
ssize_t c7200_nvram_extract_config(vm_instance_t *vm,char **buffer) |
static ssize_t c7200_nvram_extract_config(vm_instance_t *vm,u_char **buffer) |
246 |
{ |
{ |
247 |
|
u_char *base_ptr,*ios_ptr,*cfg_ptr,*end_ptr; |
248 |
|
m_uint32_t start,end,nvlen,clen; |
249 |
|
m_uint16_t magic1,magic2; |
250 |
struct vdevice *nvram_dev; |
struct vdevice *nvram_dev; |
251 |
m_uint32_t start,end,clen,nvlen; |
m_uint64_t nvram_addr; |
252 |
m_uint16_t magic1,magic2; |
off_t nvram_size; |
253 |
m_uint64_t addr; |
int fd; |
254 |
|
|
255 |
|
if ((nvram_dev = dev_get_by_name(vm,"nvram"))) |
256 |
|
dev_sync(nvram_dev); |
257 |
|
|
258 |
if (!(nvram_dev = dev_get_by_name(vm,"nvram"))) |
fd = vm_mmap_open_file(vm,"nvram",&base_ptr,&nvram_size); |
259 |
|
|
260 |
|
if (fd == -1) |
261 |
return(-1); |
return(-1); |
262 |
|
|
263 |
addr = nvram_dev->phys_addr + vm->nvram_rom_space; |
nvram_addr = VM_C7200(vm)->npe_driver->nvram_addr; |
264 |
magic1 = physmem_copy_u16_from_vm(vm,addr+0x06); |
ios_ptr = base_ptr + vm->nvram_rom_space; |
265 |
magic2 = physmem_copy_u16_from_vm(vm,addr+0x08); |
end_ptr = base_ptr + nvram_size; |
266 |
|
|
267 |
|
if ((ios_ptr + 0x30) >= end_ptr) { |
268 |
|
vm_error(vm,"NVRAM file too small\n"); |
269 |
|
return(-1); |
270 |
|
} |
271 |
|
|
272 |
|
magic1 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06)); |
273 |
|
magic2 = ntohs(*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08)); |
274 |
|
|
275 |
if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) { |
if ((magic1 != 0xF0A5) || (magic2 != 0xABCD)) { |
276 |
vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n", |
vm_error(vm,"unable to find IOS magic numbers (0x%x,0x%x)!\n", |
278 |
return(-1); |
return(-1); |
279 |
} |
} |
280 |
|
|
281 |
start = physmem_copy_u32_from_vm(vm,addr+0x10) + 1; |
start = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10)) + 1; |
282 |
end = physmem_copy_u32_from_vm(vm,addr+0x14); |
end = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x14)); |
283 |
nvlen = physmem_copy_u32_from_vm(vm,addr+0x18); |
nvlen = ntohl(*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18)); |
284 |
clen = end - start; |
clen = end - start; |
285 |
|
|
286 |
if ((clen + 1) != nvlen) { |
if ((clen + 1) != nvlen) { |
288 |
return(-1); |
return(-1); |
289 |
} |
} |
290 |
|
|
291 |
if ((start <= nvram_dev->phys_addr) || (end <= nvram_dev->phys_addr) || |
if (!(*buffer = malloc(clen+1))) { |
292 |
(end <= start)) |
vm_error(vm,"unable to allocate config buffer (%u bytes)\n",clen); |
|
{ |
|
|
vm_error(vm,"invalid configuration markers (start=0x%x,end=0x%x)\n", |
|
|
start,end); |
|
293 |
return(-1); |
return(-1); |
294 |
} |
} |
295 |
|
|
296 |
if (!(*buffer = malloc(clen+1))) { |
cfg_ptr = base_ptr + (start - nvram_addr); |
297 |
vm_error(vm,"unable to allocate config buffer (%u bytes)\n",clen); |
|
298 |
|
if ((start < nvram_addr) || ((cfg_ptr + clen) > end_ptr)) { |
299 |
|
vm_error(vm,"NVRAM file too small\n"); |
300 |
return(-1); |
return(-1); |
301 |
} |
} |
302 |
|
|
303 |
physmem_copy_from_vm(vm,*buffer,start,clen); |
memcpy(*buffer,cfg_ptr,clen); |
304 |
(*buffer)[clen] = 0; |
(*buffer)[clen] = 0; |
305 |
return(clen); |
return(clen); |
306 |
} |
} |
307 |
|
|
308 |
/* Directly push the IOS configuration to the NVRAM device */ |
/* Directly push the IOS configuration to the NVRAM device */ |
309 |
int c7200_nvram_push_config(vm_instance_t *vm,char *buffer,size_t len) |
static int c7200_nvram_push_config(vm_instance_t *vm,u_char *buffer,size_t len) |
310 |
{ |
{ |
311 |
struct vdevice *nvram_dev; |
u_char *base_ptr,*ios_ptr,*cfg_ptr; |
312 |
m_uint64_t addr,cfg_addr,cfg_start_addr; |
m_uint32_t cfg_addr,cfg_offset; |
313 |
|
m_uint32_t nvram_addr,cklen; |
314 |
|
m_uint16_t cksum; |
315 |
|
int fd; |
316 |
|
|
317 |
if (!(nvram_dev = dev_get_by_name(vm,"nvram"))) |
fd = vm_mmap_create_file(vm,"nvram",vm->nvram_size*1024,&base_ptr); |
318 |
|
|
319 |
|
if (fd == -1) |
320 |
return(-1); |
return(-1); |
321 |
|
|
322 |
addr = nvram_dev->phys_addr + vm->nvram_rom_space; |
cfg_offset = 0x2c; |
323 |
cfg_start_addr = cfg_addr = addr + 0x40; |
ios_ptr = base_ptr + vm->nvram_rom_space; |
324 |
|
cfg_ptr = ios_ptr + cfg_offset; |
325 |
|
|
326 |
|
nvram_addr = VM_C7200(vm)->npe_driver->nvram_addr; |
327 |
|
cfg_addr = nvram_addr + vm->nvram_rom_space + cfg_offset; |
328 |
|
|
329 |
/* Write IOS tag, uncompressed config... */ |
/* Write IOS tag, uncompressed config... */ |
330 |
physmem_copy_u16_to_vm(vm,addr+0x06,0xF0A5); |
*PTR_ADJUST(m_uint16_t *,ios_ptr,0x06) = htons(0xF0A5); |
331 |
physmem_copy_u16_to_vm(vm,addr+0x08,0xABCD); /* Magic number */ |
*PTR_ADJUST(m_uint16_t *,ios_ptr,0x08) = htons(0xABCD); |
332 |
physmem_copy_u16_to_vm(vm,addr+0x0a,0x0001); /* ??? */ |
*PTR_ADJUST(m_uint16_t *,ios_ptr,0x0a) = htons(0x0001); |
333 |
physmem_copy_u16_to_vm(vm,addr+0x0c,0x0000); /* zero */ |
*PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(0x0000); |
334 |
physmem_copy_u16_to_vm(vm,addr+0x0e,0x0c04); /* IOS version */ |
*PTR_ADJUST(m_uint16_t *,ios_ptr,0x0e) = htons(0x0000); |
335 |
|
|
336 |
/* Store file contents to NVRAM */ |
/* Store file contents to NVRAM */ |
337 |
physmem_copy_to_vm(vm,buffer,cfg_addr,len); |
memcpy(cfg_ptr,buffer,len); |
338 |
|
|
339 |
/* Write config addresses + size */ |
/* Write config addresses + size */ |
340 |
physmem_copy_u32_to_vm(vm,addr+0x10,cfg_start_addr); |
*PTR_ADJUST(m_uint32_t *,ios_ptr,0x10) = htonl(cfg_addr); |
341 |
physmem_copy_u32_to_vm(vm,addr+0x14,cfg_addr); |
*PTR_ADJUST(m_uint32_t *,ios_ptr,0x14) = htonl(cfg_addr + len); |
342 |
physmem_copy_u32_to_vm(vm,addr+0x18,cfg_addr - cfg_start_addr); |
*PTR_ADJUST(m_uint32_t *,ios_ptr,0x18) = htonl(len); |
343 |
return(0); |
|
344 |
} |
/* Compute the checksum */ |
345 |
|
cklen = (vm->nvram_size*1024) - (vm->nvram_rom_space + 0x08); |
346 |
/* Find an EEPROM in the specified array */ |
cksum = nvram_cksum((m_uint16_t *)(ios_ptr+0x08),cklen); |
347 |
struct c7200_eeprom *c7200_get_eeprom(struct c7200_eeprom *eeproms,char *name) |
*PTR_ADJUST(m_uint16_t *,ios_ptr,0x0c) = htons(cksum); |
|
{ |
|
|
int i; |
|
348 |
|
|
349 |
for(i=0;eeproms[i].name;i++) |
vm_mmap_close_file(fd,base_ptr,vm->nvram_size*1024); |
350 |
if (!strcmp(eeproms[i].name,name)) |
return(0); |
|
return(&eeproms[i]); |
|
|
|
|
|
return NULL; |
|
351 |
} |
} |
352 |
|
|
353 |
/* Get an EEPROM for a given NPE model */ |
/* Get an EEPROM for a given NPE model */ |
354 |
struct c7200_eeprom *c7200_get_cpu_eeprom(char *npe_name) |
static const struct cisco_eeprom *c7200_get_cpu_eeprom(char *npe_name) |
355 |
{ |
{ |
356 |
return(c7200_get_eeprom(c7200_cpu_eeprom,npe_name)); |
return(cisco_eeprom_find(c7200_cpu_eeprom,npe_name)); |
357 |
} |
} |
358 |
|
|
359 |
/* Get an EEPROM for a given midplane model */ |
/* Get an EEPROM for a given midplane model */ |
360 |
struct c7200_eeprom *c7200_get_midplane_eeprom(char *midplane_name) |
static const struct cisco_eeprom * |
361 |
|
c7200_get_midplane_eeprom(char *midplane_name) |
362 |
{ |
{ |
363 |
return(c7200_get_eeprom(c7200_midplane_eeprom,midplane_name)); |
return(cisco_eeprom_find(c7200_midplane_eeprom,midplane_name)); |
364 |
} |
} |
365 |
|
|
366 |
/* Get a PEM EEPROM for a given NPE model */ |
/* Get a PEM EEPROM for a given NPE model */ |
367 |
struct c7200_eeprom *c7200_get_pem_eeprom(char *npe_name) |
static const struct cisco_eeprom *c7200_get_pem_eeprom(char *npe_name) |
368 |
{ |
{ |
369 |
return(c7200_get_eeprom(c7200_pem_eeprom,npe_name)); |
return(cisco_eeprom_find(c7200_pem_eeprom,npe_name)); |
370 |
} |
} |
371 |
|
|
372 |
/* Set the base MAC address of the chassis */ |
/* Set the base MAC address of the chassis */ |
373 |
static int c7200_burn_mac_addr(m_uint16_t *data,size_t data_len, |
static int c7200_burn_mac_addr(c7200_t *router,n_eth_addr_t *addr) |
|
n_eth_addr_t *addr) |
|
374 |
{ |
{ |
375 |
m_uint8_t eeprom_ver; |
m_uint8_t eeprom_ver; |
376 |
|
|
377 |
/* Read EEPROM format version */ |
/* Read EEPROM format version */ |
378 |
cisco_eeprom_get_byte(data,data_len,0,&eeprom_ver); |
cisco_eeprom_get_byte(&router->mp_eeprom,0,&eeprom_ver); |
379 |
|
|
380 |
if (eeprom_ver != 1) { |
if (eeprom_ver != 1) { |
381 |
fprintf(stderr,"c7200_burn_mac_addr: unable to handle " |
vm_error(router->vm,"c7200_burn_mac_addr: unable to handle " |
382 |
"EEPROM version %u\n",eeprom_ver); |
"EEPROM version %u\n",eeprom_ver); |
383 |
return(-1); |
return(-1); |
384 |
} |
} |
385 |
|
|
386 |
cisco_eeprom_set_region(data,data_len,12,addr->eth_addr_byte,6); |
cisco_eeprom_set_region(&router->mp_eeprom,12,addr->eth_addr_byte,6); |
387 |
return(0); |
return(0); |
388 |
} |
} |
389 |
|
|
391 |
static void c7200_free_hw_ressources(c7200_t *router) |
static void c7200_free_hw_ressources(c7200_t *router) |
392 |
{ |
{ |
393 |
/* Shutdown all Port Adapters */ |
/* Shutdown all Port Adapters */ |
394 |
c7200_pa_shutdown_all(router); |
vm_slot_shutdown_all(router->vm); |
395 |
|
|
396 |
/* Inactivate the PCMCIA bus */ |
/* Inactivate the PCMCIA bus */ |
397 |
router->pcmcia_bus = NULL; |
router->pcmcia_bus = NULL; |
404 |
} |
} |
405 |
|
|
406 |
/* Create a new router instance */ |
/* Create a new router instance */ |
407 |
c7200_t *c7200_create_instance(char *name,int instance_id) |
static int c7200_create_instance(vm_instance_t *vm) |
408 |
{ |
{ |
409 |
c7200_t *router; |
c7200_t *router; |
410 |
|
|
411 |
if (!(router = malloc(sizeof(*router)))) { |
if (!(router = malloc(sizeof(*router)))) { |
412 |
fprintf(stderr,"C7200 '%s': Unable to create new instance!\n",name); |
fprintf(stderr,"C7200 '%s': Unable to create new instance!\n",vm->name); |
413 |
return NULL; |
return(-1); |
414 |
} |
} |
|
|
|
|
memset(router,0,sizeof(*router)); |
|
415 |
|
|
416 |
if (!(router->vm = vm_create(name,instance_id,VM_TYPE_C7200))) { |
memset(router,0,sizeof(*router)); |
417 |
fprintf(stderr,"C7200 '%s': unable to create VM instance!\n",name); |
router->vm = vm; |
418 |
goto err_vm; |
vm->hw_data = router; |
419 |
} |
vm->elf_machine_id = C7200_ELF_MACHINE_ID; |
420 |
|
|
421 |
c7200_init_defaults(router); |
c7200_init_defaults(router); |
422 |
router->vm->hw_data = router; |
return(0); |
|
router->vm->elf_machine_id = C7200_ELF_MACHINE_ID; |
|
|
return router; |
|
|
|
|
|
err_vm: |
|
|
free(router); |
|
|
return NULL; |
|
423 |
} |
} |
424 |
|
|
425 |
/* Free resources used by a router instance */ |
/* Free resources used by a router instance */ |
426 |
static int c7200_free_instance(void *data,void *arg) |
static int c7200_delete_instance(vm_instance_t *vm) |
427 |
{ |
{ |
428 |
vm_instance_t *vm = data; |
c7200_t *router = VM_C7200(vm); |
|
c7200_t *router; |
|
429 |
int i; |
int i; |
430 |
|
|
431 |
if (vm->type == VM_TYPE_C7200) { |
/* Stop all CPUs */ |
432 |
router = VM_C7200(vm); |
if (vm->cpu_group != NULL) { |
433 |
|
vm_stop(vm); |
434 |
|
|
435 |
/* Stop all CPUs */ |
if (cpu_group_sync_state(vm->cpu_group) == -1) { |
436 |
if (vm->cpu_group != NULL) { |
vm_error(vm,"unable to sync with system CPUs.\n"); |
437 |
vm_stop(vm); |
return(FALSE); |
|
|
|
|
if (cpu_group_sync_state(vm->cpu_group) == -1) { |
|
|
vm_error(vm,"unable to sync with system CPUs.\n"); |
|
|
return(FALSE); |
|
|
} |
|
438 |
} |
} |
439 |
|
} |
440 |
|
|
441 |
/* Remove NIO bindings */ |
/* Remove NIO bindings */ |
442 |
for(i=0;i<C7200_MAX_PA_BAYS;i++) |
for(i=0;i<vm->nr_slots;i++) |
443 |
c7200_pa_remove_all_nio_bindings(router,i); |
vm_slot_remove_all_nio_bindings(vm,i); |
|
|
|
|
/* Free specific HW resources */ |
|
|
c7200_free_hw_ressources(router); |
|
|
|
|
|
/* Free all resources used by VM */ |
|
|
vm_free(vm); |
|
444 |
|
|
445 |
/* Free the router structure */ |
/* Free specific HW resources */ |
446 |
free(router); |
c7200_free_hw_ressources(router); |
|
return(TRUE); |
|
|
} |
|
447 |
|
|
448 |
return(FALSE); |
/* Free EEPROMs */ |
449 |
} |
cisco_eeprom_free(&router->cpu_eeprom); |
450 |
|
cisco_eeprom_free(&router->mp_eeprom); |
451 |
|
cisco_eeprom_free(&router->pem_eeprom); |
452 |
|
|
453 |
/* Delete a router instance */ |
/* Free all resources used by VM */ |
454 |
int c7200_delete_instance(char *name) |
vm_free(vm); |
|
{ |
|
|
return(registry_delete_if_unused(name,OBJ_TYPE_VM, |
|
|
c7200_free_instance,NULL)); |
|
|
} |
|
455 |
|
|
456 |
/* Delete all router instances */ |
/* Free the router structure */ |
457 |
int c7200_delete_all_instances(void) |
free(router); |
458 |
{ |
return(TRUE); |
|
return(registry_delete_type(OBJ_TYPE_VM,c7200_free_instance,NULL)); |
|
459 |
} |
} |
460 |
|
|
461 |
/* Save configuration of a C7200 instance */ |
/* Save configuration of a C7200 instance */ |
462 |
void c7200_save_config(c7200_t *router,FILE *fd) |
static void c7200_save_config(vm_instance_t *vm,FILE *fd) |
463 |
{ |
{ |
464 |
vm_instance_t *vm = router->vm; |
c7200_t *router = VM_C7200(vm); |
|
struct c7200_nio_binding *nb; |
|
|
struct c7200_pa_bay *bay; |
|
|
int i; |
|
|
|
|
|
/* General settings */ |
|
|
fprintf(fd,"c7200 create %s %u\n",vm->name,vm->instance_id); |
|
465 |
|
|
466 |
fprintf(fd,"c7200 set_npe %s %s\n",vm->name,router->npe_driver->npe_type); |
fprintf(fd,"c7200 set_npe %s %s\n",vm->name,router->npe_driver->npe_type); |
467 |
fprintf(fd,"c7200 set_midplane %s %s\n",vm->name,router->midplane_type); |
fprintf(fd,"c7200 set_midplane %s %s\n\n",vm->name,router->midplane_type); |
468 |
|
} |
469 |
|
|
470 |
/* VM configuration */ |
/* Set EEPROM for the specified slot */ |
471 |
vm_save_config(vm,fd); |
int c7200_set_slot_eeprom(c7200_t *router,u_int slot, |
472 |
|
struct cisco_eeprom *eeprom) |
473 |
|
{ |
474 |
|
if (slot >= C7200_MAX_PA_BAYS) |
475 |
|
return(-1); |
476 |
|
|
477 |
/* Port Adapter settings */ |
switch(slot) { |
478 |
for(i=0;i<C7200_MAX_PA_BAYS;i++) { |
/* Group 1: bays 0, 1, 3, 4 */ |
479 |
if (!(bay = c7200_pa_get_info(router,i))) |
case 0: |
480 |
continue; |
router->pa_eeprom_g1.eeprom[0] = eeprom; |
481 |
|
break; |
482 |
if (bay->dev_type) { |
case 1: |
483 |
fprintf(fd,"c7200 add_pa_binding %s %u %s\n", |
router->pa_eeprom_g1.eeprom[1] = eeprom; |
484 |
vm->name,i,bay->dev_type); |
break; |
485 |
} |
case 3: |
486 |
|
router->pa_eeprom_g1.eeprom[2] = eeprom; |
487 |
|
break; |
488 |
|
case 4: |
489 |
|
router->pa_eeprom_g1.eeprom[3] = eeprom; |
490 |
|
break; |
491 |
|
|
492 |
for(nb=bay->nio_list;nb;nb=nb->next) { |
/* Group 2: bays 2, 5, 6 */ |
493 |
fprintf(fd,"c7200 add_nio_binding %s %u %u %s\n", |
case 2: |
494 |
vm->name,i,nb->port_id,nb->nio->name); |
router->pa_eeprom_g2.eeprom[0] = eeprom; |
495 |
} |
break; |
496 |
|
case 5: |
497 |
|
router->pa_eeprom_g2.eeprom[1] = eeprom; |
498 |
|
break; |
499 |
|
case 6: |
500 |
|
router->pa_eeprom_g2.eeprom[2] = eeprom; |
501 |
|
break; |
502 |
} |
} |
503 |
|
|
504 |
fprintf(fd,"\n"); |
return(0); |
505 |
} |
} |
506 |
|
|
507 |
/* Save configurations of all C7200 instances */ |
/* Get slot/port corresponding to specified network IRQ */ |
508 |
static void c7200_reg_save_config(registry_entry_t *entry,void *opt,int *err) |
static inline void |
509 |
|
c7200_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port) |
510 |
{ |
{ |
511 |
vm_instance_t *vm = entry->data; |
irq -= C7200_NETIO_IRQ_BASE; |
512 |
c7200_t *router = VM_C7200(vm); |
*port = irq & C7200_NETIO_IRQ_PORT_MASK; |
513 |
|
*slot = irq >> C7200_NETIO_IRQ_PORT_BITS; |
|
if (vm->type == VM_TYPE_C7200) |
|
|
c7200_save_config(router,(FILE *)opt); |
|
514 |
} |
} |
515 |
|
|
516 |
void c7200_save_config_all(FILE *fd) |
/* Get network IRQ for specified slot/port */ |
517 |
|
u_int c7200_net_irq_for_slot_port(u_int slot,u_int port) |
518 |
{ |
{ |
519 |
registry_foreach_type(OBJ_TYPE_VM,c7200_reg_save_config,fd,NULL); |
u_int irq; |
520 |
|
|
521 |
|
irq = (slot << C7200_NETIO_IRQ_PORT_BITS) + port; |
522 |
|
irq += C7200_NETIO_IRQ_BASE; |
523 |
|
|
524 |
|
return(irq); |
525 |
} |
} |
526 |
|
|
527 |
/* Set NPE eeprom definition */ |
/* Set NPE eeprom definition */ |
528 |
static int c7200_npe_set_eeprom(c7200_t *router) |
static int c7200_npe_set_eeprom(c7200_t *router) |
529 |
{ |
{ |
530 |
struct c7200_eeprom *eeprom; |
const struct cisco_eeprom *eeprom; |
531 |
|
|
532 |
if (!(eeprom = c7200_get_cpu_eeprom(router->npe_driver->npe_type))) { |
if (!(eeprom = c7200_get_cpu_eeprom(router->npe_driver->npe_type))) { |
533 |
vm_error(router->vm,"unknown NPE \"%s\" (internal error)!\n", |
vm_error(router->vm,"unknown NPE \"%s\" (internal error)!\n", |
535 |
return(-1); |
return(-1); |
536 |
} |
} |
537 |
|
|
538 |
router->cpu_eeprom.data = eeprom->data; |
if (cisco_eeprom_copy(&router->cpu_eeprom,eeprom) == -1) { |
539 |
router->cpu_eeprom.data_len = eeprom->len; |
vm_error(router->vm,"unable to set NPE EEPROM.\n"); |
540 |
|
return(-1); |
541 |
|
} |
542 |
|
|
543 |
return(0); |
return(0); |
544 |
} |
} |
545 |
|
|
546 |
/* Set PEM eeprom definition */ |
/* Set PEM eeprom definition */ |
547 |
static int c7200_pem_set_eeprom(c7200_t *router) |
static int c7200_pem_set_eeprom(c7200_t *router) |
548 |
{ |
{ |
549 |
struct c7200_eeprom *eeprom; |
const struct cisco_eeprom *eeprom; |
550 |
|
|
551 |
if (!(eeprom = c7200_get_pem_eeprom(router->npe_driver->npe_type))) { |
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", |
vm_error(router->vm,"no PEM EEPROM found for NPE type \"%s\"!\n", |
554 |
return(-1); |
return(-1); |
555 |
} |
} |
556 |
|
|
557 |
router->pem_eeprom.data = eeprom->data; |
if (cisco_eeprom_copy(&router->pem_eeprom,eeprom) == -1) { |
558 |
router->pem_eeprom.data_len = eeprom->len; |
vm_error(router->vm,"unable to set PEM EEPROM.\n"); |
|
return(0); |
|
|
} |
|
|
|
|
|
/* Set PA EEPROM definition */ |
|
|
int c7200_pa_set_eeprom(c7200_t *router,u_int pa_bay, |
|
|
const struct c7200_eeprom *eeprom) |
|
|
{ |
|
|
if (pa_bay >= C7200_MAX_PA_BAYS) { |
|
|
vm_error(router->vm,"c7200_pa_set_eeprom: invalid PA Bay %u.\n",pa_bay); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
router->pa_bay[pa_bay].eeprom.data = eeprom->data; |
|
|
router->pa_bay[pa_bay].eeprom.data_len = eeprom->len; |
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Unset PA EEPROM definition (empty bay) */ |
|
|
int c7200_pa_unset_eeprom(c7200_t *router,u_int pa_bay) |
|
|
{ |
|
|
if (pa_bay >= C7200_MAX_PA_BAYS) { |
|
|
vm_error(router->vm,"c7200_pa_set_eeprom: invalid PA Bay %u.\n",pa_bay); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
router->pa_bay[pa_bay].eeprom.data = (m_uint16_t *)eeprom_pa_empty; |
|
|
router->pa_bay[pa_bay].eeprom.data_len = sizeof(eeprom_pa_empty)/2; |
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Check if a bay has a port adapter */ |
|
|
int c7200_pa_check_eeprom(c7200_t *router,u_int pa_bay) |
|
|
{ |
|
|
struct nmc93c46_eeprom_def *def; |
|
|
|
|
|
if (!pa_bay || (pa_bay >= C7200_MAX_PA_BAYS)) |
|
|
return(0); |
|
|
|
|
|
def = &router->pa_bay[pa_bay].eeprom; |
|
|
|
|
|
if (def->data == eeprom_pa_empty) |
|
|
return(0); |
|
|
|
|
|
return(1); |
|
|
} |
|
|
|
|
|
/* Get bay info */ |
|
|
struct c7200_pa_bay *c7200_pa_get_info(c7200_t *router,u_int pa_bay) |
|
|
{ |
|
|
if (pa_bay >= C7200_MAX_PA_BAYS) |
|
|
return NULL; |
|
|
|
|
|
return(&router->pa_bay[pa_bay]); |
|
|
} |
|
|
|
|
|
/* Get PA type */ |
|
|
char *c7200_pa_get_type(c7200_t *router,u_int pa_bay) |
|
|
{ |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
bay = c7200_pa_get_info(router,pa_bay); |
|
|
return((bay != NULL) ? bay->dev_type : NULL); |
|
|
} |
|
|
|
|
|
/* Get driver info about the specified slot */ |
|
|
void *c7200_pa_get_drvinfo(c7200_t *router,u_int pa_bay) |
|
|
{ |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
bay = c7200_pa_get_info(router,pa_bay); |
|
|
return((bay != NULL) ? bay->drv_info : NULL); |
|
|
} |
|
|
|
|
|
/* Set driver info for the specified slot */ |
|
|
int c7200_pa_set_drvinfo(c7200_t *router,u_int pa_bay,void *drv_info) |
|
|
{ |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
bay->drv_info = drv_info; |
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Get a PA driver */ |
|
|
static struct c7200_pa_driver *c7200_pa_get_driver(char *dev_type) |
|
|
{ |
|
|
int i; |
|
|
|
|
|
for(i=0;pa_drivers[i];i++) |
|
|
if (!strcmp(pa_drivers[i]->dev_type,dev_type)) |
|
|
return pa_drivers[i]; |
|
|
|
|
|
return NULL; |
|
|
} |
|
|
|
|
|
/* Add a PA binding */ |
|
|
int c7200_pa_add_binding(c7200_t *router,char *dev_type,u_int pa_bay) |
|
|
{ |
|
|
struct c7200_pa_driver *pa_driver; |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
/* check that this bay is empty */ |
|
|
if (bay->dev_type != NULL) { |
|
|
vm_error(router->vm,"a PA already exists in slot %u.\n",pa_bay); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
/* find the PA driver */ |
|
|
if (!(pa_driver = c7200_pa_get_driver(dev_type))) { |
|
|
vm_error(router->vm,"unknown PA type '%s'.\n",dev_type); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
bay->dev_type = pa_driver->dev_type; |
|
|
bay->pa_driver = pa_driver; |
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Remove a PA binding */ |
|
|
int c7200_pa_remove_binding(c7200_t *router,u_int pa_bay) |
|
|
{ |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
/* stop if this bay is still active */ |
|
|
if (bay->drv_info != NULL) { |
|
|
vm_error(router->vm,"slot %u still active.\n",pa_bay); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
/* check that this bay is not empty */ |
|
|
if (bay->dev_type == NULL) { |
|
|
vm_error(router->vm,"slot %u is empty.\n",pa_bay); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
/* remove all NIOs bindings */ |
|
|
c7200_pa_remove_all_nio_bindings(router,pa_bay); |
|
|
|
|
|
bay->dev_type = NULL; |
|
|
bay->pa_driver = NULL; |
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Find a NIO binding */ |
|
|
struct c7200_nio_binding * |
|
|
c7200_pa_find_nio_binding(c7200_t *router,u_int pa_bay,u_int port_id) |
|
|
{ |
|
|
struct c7200_nio_binding *nb; |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return NULL; |
|
|
|
|
|
for(nb=bay->nio_list;nb;nb=nb->next) |
|
|
if (nb->port_id == port_id) |
|
|
return nb; |
|
|
|
|
|
return NULL; |
|
|
} |
|
|
|
|
|
/* Add a network IO binding */ |
|
|
int c7200_pa_add_nio_binding(c7200_t *router,u_int pa_bay,u_int port_id, |
|
|
char *nio_name) |
|
|
{ |
|
|
struct c7200_nio_binding *nb; |
|
|
struct c7200_pa_bay *bay; |
|
|
netio_desc_t *nio; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
/* check that a NIO is not already bound to this port */ |
|
|
if (c7200_pa_find_nio_binding(router,pa_bay,port_id) != NULL) { |
|
|
vm_error(router->vm,"a NIO already exists for interface %u/%u\n", |
|
|
pa_bay,port_id); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
/* acquire a reference on the NIO object */ |
|
|
if (!(nio = netio_acquire(nio_name))) { |
|
|
vm_error(router->vm,"unable to find NIO '%s'.\n",nio_name); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
/* create a new binding */ |
|
|
if (!(nb = malloc(sizeof(*nb)))) { |
|
|
vm_error(router->vm,"unable to create NIO binding " |
|
|
"for interface %u/%u.\n",pa_bay,port_id); |
|
|
netio_release(nio_name); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
memset(nb,0,sizeof(*nb)); |
|
|
nb->nio = nio; |
|
|
nb->port_id = port_id; |
|
|
nb->next = bay->nio_list; |
|
|
if (nb->next) nb->next->prev = nb; |
|
|
bay->nio_list = nb; |
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Remove a NIO binding */ |
|
|
int c7200_pa_remove_nio_binding(c7200_t *router,u_int pa_bay,u_int port_id) |
|
|
{ |
|
|
struct c7200_nio_binding *nb; |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
if (!(nb = c7200_pa_find_nio_binding(router,pa_bay,port_id))) |
|
|
return(-1); /* no nio binding for this slot/port */ |
|
|
|
|
|
/* tell the PA driver to stop using this NIO */ |
|
|
if (bay->pa_driver) |
|
|
bay->pa_driver->pa_unset_nio(router,pa_bay,port_id); |
|
|
|
|
|
/* remove this entry from the double linked list */ |
|
|
if (nb->next) |
|
|
nb->next->prev = nb->prev; |
|
|
|
|
|
if (nb->prev) { |
|
|
nb->prev->next = nb->next; |
|
|
} else { |
|
|
bay->nio_list = nb->next; |
|
|
} |
|
|
|
|
|
/* unreference NIO object */ |
|
|
netio_release(nb->nio->name); |
|
|
free(nb); |
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Remove all NIO bindings for the specified PA */ |
|
|
int c7200_pa_remove_all_nio_bindings(c7200_t *router,u_int pa_bay) |
|
|
{ |
|
|
struct c7200_nio_binding *nb,*next; |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
for(nb=bay->nio_list;nb;nb=next) { |
|
|
next = nb->next; |
|
|
|
|
|
/* tell the PA driver to stop using this NIO */ |
|
|
if (bay->pa_driver) |
|
|
bay->pa_driver->pa_unset_nio(router,pa_bay,nb->port_id); |
|
|
|
|
|
/* unreference NIO object */ |
|
|
netio_release(nb->nio->name); |
|
|
free(nb); |
|
|
} |
|
|
|
|
|
bay->nio_list = NULL; |
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Enable a Network IO descriptor for a Port Adapter */ |
|
|
int c7200_pa_enable_nio(c7200_t *router,u_int pa_bay,u_int port_id) |
|
|
{ |
|
|
struct c7200_nio_binding *nb; |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
/* check that we have an NIO binding for this interface */ |
|
|
if (!(nb = c7200_pa_find_nio_binding(router,pa_bay,port_id))) |
|
|
return(-1); |
|
|
|
|
|
/* check that the driver is defined and successfully initialized */ |
|
|
if (!bay->pa_driver || !bay->drv_info) |
|
|
return(-1); |
|
|
|
|
|
return(bay->pa_driver->pa_set_nio(router,pa_bay,port_id,nb->nio)); |
|
|
} |
|
|
|
|
|
/* Disable Network IO descriptor of a Port Adapter */ |
|
|
int c7200_pa_disable_nio(c7200_t *router,u_int pa_bay,u_int port_id) |
|
|
{ |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
/* check that the driver is defined and successfully initialized */ |
|
|
if (!bay->pa_driver || !bay->drv_info) |
|
|
return(-1); |
|
|
|
|
|
return(bay->pa_driver->pa_unset_nio(router,pa_bay,port_id)); |
|
|
} |
|
|
|
|
|
/* Enable all NIO of the specified PA */ |
|
|
int c7200_pa_enable_all_nio(c7200_t *router,u_int pa_bay) |
|
|
{ |
|
|
struct c7200_nio_binding *nb; |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
/* check that the driver is defined and successfully initialized */ |
|
|
if (!bay->pa_driver || !bay->drv_info) |
|
|
return(-1); |
|
|
|
|
|
for(nb=bay->nio_list;nb;nb=nb->next) |
|
|
bay->pa_driver->pa_set_nio(router,pa_bay,nb->port_id,nb->nio); |
|
|
|
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Disable all NIO of the specified PA */ |
|
|
int c7200_pa_disable_all_nio(c7200_t *router,u_int pa_bay) |
|
|
{ |
|
|
struct c7200_nio_binding *nb; |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
/* check that the driver is defined and successfully initialized */ |
|
|
if (!bay->pa_driver || !bay->drv_info) |
|
|
return(-1); |
|
|
|
|
|
for(nb=bay->nio_list;nb;nb=nb->next) |
|
|
bay->pa_driver->pa_unset_nio(router,pa_bay,nb->port_id); |
|
|
|
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Initialize a Port Adapter */ |
|
|
int c7200_pa_init(c7200_t *router,u_int pa_bay) |
|
|
{ |
|
|
struct c7200_pa_bay *bay; |
|
|
size_t len; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
/* Check that a device type is defined for this bay */ |
|
|
if (!bay->dev_type || !bay->pa_driver) { |
|
|
vm_error(router->vm,"trying to init empty slot %u.\n",pa_bay); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
/* Allocate device name */ |
|
|
len = strlen(bay->dev_type) + 10; |
|
|
if (!(bay->dev_name = malloc(len))) { |
|
|
vm_error(router->vm,"unable to allocate device name.\n"); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
snprintf(bay->dev_name,len,"%s(%u)",bay->dev_type,pa_bay); |
|
|
|
|
|
/* Initialize PA driver */ |
|
|
if (bay->pa_driver->pa_init(router,bay->dev_name,pa_bay) == 1) { |
|
|
vm_error(router->vm,"unable to initialize PA %u.\n",pa_bay); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
/* Enable all NIO */ |
|
|
c7200_pa_enable_all_nio(router,pa_bay); |
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Shutdown a Port Adapter */ |
|
|
int c7200_pa_shutdown(c7200_t *router,u_int pa_bay) |
|
|
{ |
|
|
struct c7200_pa_bay *bay; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
/* Check that a device type is defined for this bay */ |
|
|
if (!bay->dev_type || !bay->pa_driver) { |
|
|
vm_error(router->vm,"trying to shut down an empty bay %u.\n",pa_bay); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
/* Disable all NIO */ |
|
|
c7200_pa_disable_all_nio(router,pa_bay); |
|
|
|
|
|
/* Shutdown the PA driver */ |
|
|
if (bay->drv_info && (bay->pa_driver->pa_shutdown(router,pa_bay) == -1)) { |
|
|
vm_error(router->vm,"unable to shutdown PA %u.\n",pa_bay); |
|
559 |
return(-1); |
return(-1); |
560 |
} |
} |
561 |
|
|
|
free(bay->dev_name); |
|
|
bay->dev_name = NULL; |
|
|
bay->drv_info = NULL; |
|
562 |
return(0); |
return(0); |
563 |
} |
} |
564 |
|
|
|
/* Shutdown all PA of a router */ |
|
|
int c7200_pa_shutdown_all(c7200_t *router) |
|
|
{ |
|
|
int i; |
|
|
|
|
|
for(i=0;i<C7200_MAX_PA_BAYS;i++) { |
|
|
if (!router->pa_bay[i].dev_type) |
|
|
continue; |
|
|
|
|
|
c7200_pa_shutdown(router,i); |
|
|
} |
|
|
|
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* Maximum number of tokens in a PA description */ |
|
|
#define PA_DESC_MAX_TOKENS 8 |
|
|
|
|
|
/* Create a Port Adapter (command line) */ |
|
|
int c7200_cmd_pa_create(c7200_t *router,char *str) |
|
|
{ |
|
|
char *tokens[PA_DESC_MAX_TOKENS]; |
|
|
int i,count,res; |
|
|
u_int pa_bay; |
|
|
|
|
|
/* A port adapter description is like "1:PA-FE-TX" */ |
|
|
if ((count = m_strsplit(str,':',tokens,PA_DESC_MAX_TOKENS)) != 2) { |
|
|
vm_error(router->vm,"unable to parse PA description '%s'.\n",str); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
/* Parse the PA bay id */ |
|
|
pa_bay = atoi(tokens[0]); |
|
|
|
|
|
/* Add this new PA to the current PA list */ |
|
|
res = c7200_pa_add_binding(router,tokens[1],pa_bay); |
|
|
|
|
|
/* The complete array was cleaned by strsplit */ |
|
|
for(i=0;i<PA_DESC_MAX_TOKENS;i++) |
|
|
free(tokens[i]); |
|
|
|
|
|
return(res); |
|
|
} |
|
|
|
|
|
/* Add a Network IO descriptor binding (command line) */ |
|
|
int c7200_cmd_add_nio(c7200_t *router,char *str) |
|
|
{ |
|
|
char *tokens[PA_DESC_MAX_TOKENS]; |
|
|
int i,count,nio_type,res=-1; |
|
|
u_int pa_bay,port_id; |
|
|
netio_desc_t *nio; |
|
|
char nio_name[128]; |
|
|
|
|
|
/* A port adapter description is like "1:3:tap:tap0" */ |
|
|
if ((count = m_strsplit(str,':',tokens,PA_DESC_MAX_TOKENS)) < 3) { |
|
|
vm_error(router->vm,"unable to parse NIO description '%s'.\n",str); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
/* Parse the PA bay */ |
|
|
pa_bay = atoi(tokens[0]); |
|
|
|
|
|
/* Parse the PA port id */ |
|
|
port_id = atoi(tokens[1]); |
|
|
|
|
|
/* Autogenerate a NIO name */ |
|
|
snprintf(nio_name,sizeof(nio_name),"c7200-i%u/%u/%u", |
|
|
router->vm->instance_id,pa_bay,port_id); |
|
|
|
|
|
/* Create the Network IO descriptor */ |
|
|
nio = NULL; |
|
|
nio_type = netio_get_type(tokens[2]); |
|
|
|
|
|
switch(nio_type) { |
|
|
case NETIO_TYPE_UNIX: |
|
|
if (count != 5) { |
|
|
vm_error(router->vm, |
|
|
"invalid number of arguments for UNIX NIO '%s'\n",str); |
|
|
goto done; |
|
|
} |
|
|
|
|
|
nio = netio_desc_create_unix(nio_name,tokens[3],tokens[4]); |
|
|
break; |
|
|
|
|
|
case NETIO_TYPE_VDE: |
|
|
if (count != 5) { |
|
|
vm_error(router->vm, |
|
|
"invalid number of arguments for VDE NIO '%s'\n",str); |
|
|
goto done; |
|
|
} |
|
|
|
|
|
nio = netio_desc_create_vde(nio_name,tokens[3],tokens[4]); |
|
|
break; |
|
|
|
|
|
case NETIO_TYPE_TAP: |
|
|
if (count != 4) { |
|
|
vm_error(router->vm, |
|
|
"invalid number of arguments for TAP NIO '%s'\n",str); |
|
|
goto done; |
|
|
} |
|
|
|
|
|
nio = netio_desc_create_tap(nio_name,tokens[3]); |
|
|
break; |
|
|
|
|
|
case NETIO_TYPE_UDP: |
|
|
if (count != 6) { |
|
|
vm_error(router->vm, |
|
|
"invalid number of arguments for UDP NIO '%s'\n",str); |
|
|
goto done; |
|
|
} |
|
|
|
|
|
nio = netio_desc_create_udp(nio_name,atoi(tokens[3]), |
|
|
tokens[4],atoi(tokens[5])); |
|
|
break; |
|
|
|
|
|
case NETIO_TYPE_TCP_CLI: |
|
|
if (count != 5) { |
|
|
vm_error(router->vm, |
|
|
"invalid number of arguments for TCP CLI NIO '%s'\n",str); |
|
|
goto done; |
|
|
} |
|
|
|
|
|
nio = netio_desc_create_tcp_cli(nio_name,tokens[3],tokens[4]); |
|
|
break; |
|
|
|
|
|
case NETIO_TYPE_TCP_SER: |
|
|
if (count != 4) { |
|
|
vm_error(router->vm, |
|
|
"invalid number of arguments for TCP SER NIO '%s'\n",str); |
|
|
goto done; |
|
|
} |
|
|
|
|
|
nio = netio_desc_create_tcp_ser(nio_name,tokens[3]); |
|
|
break; |
|
|
|
|
|
case NETIO_TYPE_NULL: |
|
|
nio = netio_desc_create_null(nio_name); |
|
|
break; |
|
|
|
|
|
#ifdef LINUX_ETH |
|
|
case NETIO_TYPE_LINUX_ETH: |
|
|
if (count != 4) { |
|
|
vm_error(router->vm, |
|
|
"invalid number of arguments for Linux Eth NIO '%s'\n", |
|
|
str); |
|
|
goto done; |
|
|
} |
|
|
|
|
|
nio = netio_desc_create_lnxeth(nio_name,tokens[3]); |
|
|
break; |
|
|
#endif |
|
|
|
|
|
#ifdef GEN_ETH |
|
|
case NETIO_TYPE_GEN_ETH: |
|
|
if (count != 4) { |
|
|
vm_error(router->vm,"invalid number of " |
|
|
"arguments for Generic Eth NIO '%s'\n",str); |
|
|
goto done; |
|
|
} |
|
|
|
|
|
nio = netio_desc_create_geneth(nio_name,tokens[3]); |
|
|
break; |
|
|
#endif |
|
|
|
|
|
default: |
|
|
vm_error(router->vm,"unknown NETIO type '%s'\n",tokens[2]); |
|
|
goto done; |
|
|
} |
|
|
|
|
|
if (!nio) { |
|
|
fprintf(stderr,"c7200_cmd_add_nio: unable to create NETIO " |
|
|
"descriptor for PA bay %u\n",pa_bay); |
|
|
goto done; |
|
|
} |
|
|
|
|
|
if (c7200_pa_add_nio_binding(router,pa_bay,port_id,nio_name) == -1) { |
|
|
vm_error(router->vm,"unable to add NETIO binding for slot %u\n",pa_bay); |
|
|
netio_release(nio_name); |
|
|
netio_delete(nio_name); |
|
|
goto done; |
|
|
} |
|
|
|
|
|
netio_release(nio_name); |
|
|
res = 0; |
|
|
|
|
|
done: |
|
|
/* The complete array was cleaned by strsplit */ |
|
|
for(i=0;i<PA_DESC_MAX_TOKENS;i++) |
|
|
free(tokens[i]); |
|
|
|
|
|
return(res); |
|
|
} |
|
|
|
|
|
/* Show the list of available PA drivers */ |
|
|
void c7200_pa_show_drivers(void) |
|
|
{ |
|
|
int i; |
|
|
|
|
|
printf("Available C7200 Port Adapter drivers:\n"); |
|
|
|
|
|
for(i=0;pa_drivers[i];i++) { |
|
|
printf(" * %s %s\n", |
|
|
pa_drivers[i]->dev_type, |
|
|
!pa_drivers[i]->supported ? "(NOT WORKING)" : ""); |
|
|
} |
|
|
|
|
|
printf("\n"); |
|
|
} |
|
|
|
|
565 |
/* Get an NPE driver */ |
/* Get an NPE driver */ |
566 |
struct c7200_npe_driver *c7200_npe_get_driver(char *npe_type) |
struct c7200_npe_driver *c7200_npe_get_driver(char *npe_type) |
567 |
{ |
{ |
597 |
return(-1); |
return(-1); |
598 |
} |
} |
599 |
|
|
600 |
|
/* Use a C7200-IO-FE by default in slot 0 if an I/O card is required */ |
601 |
|
if (driver->iocard_required) { |
602 |
|
vm_slot_add_binding(router->vm,"C7200-IO-FE",0,0); |
603 |
|
vm_slot_set_flag(router->vm,0,0,CISCO_CARD_FLAG_OVERRIDE); |
604 |
|
} |
605 |
return(0); |
return(0); |
606 |
} |
} |
607 |
|
|
608 |
/* Show the list of available NPE drivers */ |
/* Show the list of available NPE drivers */ |
609 |
void c7200_npe_show_drivers(void) |
static void c7200_npe_show_drivers(void) |
610 |
{ |
{ |
611 |
int i; |
int i; |
612 |
|
|
624 |
/* Set Midplane type */ |
/* Set Midplane type */ |
625 |
int c7200_midplane_set_type(c7200_t *router,char *midplane_type) |
int c7200_midplane_set_type(c7200_t *router,char *midplane_type) |
626 |
{ |
{ |
627 |
struct c7200_eeprom *eeprom; |
const struct cisco_eeprom *eeprom; |
628 |
m_uint8_t version; |
m_uint8_t version; |
629 |
|
|
630 |
if (router->vm->status == VM_STATUS_RUNNING) { |
if (router->vm->status == VM_STATUS_RUNNING) { |
638 |
return(-1); |
return(-1); |
639 |
} |
} |
640 |
|
|
641 |
memcpy(router->mp_eeprom_data,eeprom->data,eeprom->len << 1); |
/* Copy the midplane EEPROM */ |
642 |
|
if (cisco_eeprom_copy(&router->mp_eeprom,eeprom) == -1) { |
643 |
|
vm_error(router->vm,"unable to set midplane EEPROM.\n"); |
644 |
|
return(-1); |
645 |
|
} |
646 |
|
|
647 |
/* Set the chassis base MAC address */ |
/* Set the chassis base MAC address */ |
648 |
c7200_burn_mac_addr(router->mp_eeprom_data,sizeof(router->mp_eeprom_data), |
c7200_burn_mac_addr(router,&router->mac_addr); |
|
&router->mac_addr); |
|
|
|
|
|
router->mp_eeprom.data = router->mp_eeprom_data; |
|
|
router->mp_eeprom.data_len = eeprom->len; |
|
|
router->midplane_type = eeprom->name; |
|
649 |
|
|
650 |
/* Get the midplane version */ |
/* Get the midplane version */ |
651 |
cisco_eeprom_get_byte(router->mp_eeprom.data,router->mp_eeprom.data_len*2, |
cisco_eeprom_get_byte(&router->mp_eeprom,2,&version); |
652 |
2,&version); |
router->midplane_version = version; |
653 |
router->midplane_version = version; |
router->midplane_type = eeprom->name; |
654 |
return(0); |
return(0); |
655 |
} |
} |
656 |
|
|
663 |
} |
} |
664 |
|
|
665 |
/* Set the chassis base MAC address */ |
/* Set the chassis base MAC address */ |
666 |
c7200_burn_mac_addr(router->mp_eeprom_data,sizeof(router->mp_eeprom_data), |
c7200_burn_mac_addr(router,&router->mac_addr); |
|
&router->mac_addr); |
|
667 |
return(0); |
return(0); |
668 |
} |
} |
669 |
|
|
724 |
return(0); |
return(0); |
725 |
} |
} |
726 |
|
|
727 |
|
/* Create the two main PCI busses for a MV64460 based system */ |
728 |
|
static int c7200_init_mv64460(c7200_t *router) |
729 |
|
{ |
730 |
|
vm_instance_t *vm = router->vm; |
731 |
|
|
732 |
|
vm->pci_bus[0] = pci_bus_create("MB0/MB1",3); |
733 |
|
vm->pci_bus[1] = pci_bus_create("MB2",0); |
734 |
|
|
735 |
|
if (!vm->pci_bus[0] || !vm->pci_bus[1]) { |
736 |
|
vm_error(vm,"unable to create PCI data.\n"); |
737 |
|
return(-1); |
738 |
|
} |
739 |
|
|
740 |
|
return(dev_mv64460_init(vm,"mv64460",C7200_G2_MV64460_ADDR,0x10000)); |
741 |
|
} |
742 |
|
|
743 |
/* Create the PA PCI busses */ |
/* Create the PA PCI busses */ |
744 |
static int c7200_pa_create_pci_busses(c7200_t *router) |
static int c7200_pa_create_pci_busses(c7200_t *router) |
745 |
{ |
{ |
762 |
static int c7200_pa_init_pci_bridge(c7200_t *router,u_int pa_bay, |
static int c7200_pa_init_pci_bridge(c7200_t *router,u_int pa_bay, |
763 |
struct pci_bus *pci_bus,int pci_device) |
struct pci_bus *pci_bus,int pci_device) |
764 |
{ |
{ |
765 |
|
struct pci_bus *pa_bus; |
766 |
|
|
767 |
|
pa_bus = router->vm->slots_pci_bus[pa_bay]; |
768 |
|
|
769 |
switch(router->midplane_version) { |
switch(router->midplane_version) { |
770 |
case 0: |
case 0: |
771 |
case 1: |
case 1: |
772 |
dev_dec21050_init(pci_bus,pci_device,router->pa_bay[pa_bay].pci_map); |
dev_dec21050_init(pci_bus,pci_device,pa_bus); |
773 |
break; |
break; |
774 |
default: |
default: |
775 |
dev_dec21150_init(pci_bus,pci_device,router->pa_bay[pa_bay].pci_map); |
dev_dec21150_init(pci_bus,pci_device,pa_bus); |
776 |
} |
} |
777 |
return(0); |
return(0); |
778 |
} |
} |
819 |
int i; |
int i; |
820 |
|
|
821 |
/* Set the processor type: R4600 */ |
/* Set the processor type: R4600 */ |
822 |
mips64_set_prid(vm->boot_cpu,MIPS_PRID_R4600); |
mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R4600); |
823 |
|
|
824 |
/* Initialize the Galileo GT-64010 system controller */ |
/* Initialize the Galileo GT-64010 system controller */ |
825 |
if (c7200_init_gt64010(router) == -1) |
if (c7200_init_gt64010(router) == -1) |
843 |
dev_dec21050_init(vm->pci_bus[0],4,vm->pci_bus_pool[25]); |
dev_dec21050_init(vm->pci_bus[0],4,vm->pci_bus_pool[25]); |
844 |
|
|
845 |
/* Map the PA PCI busses */ |
/* Map the PA PCI busses */ |
846 |
router->pa_bay[0].pci_map = vm->pci_bus[0]; |
vm->slots_pci_bus[0] = vm->pci_bus[0]; |
847 |
|
|
848 |
for(i=1;i<C7200_MAX_PA_BAYS;i++) |
for(i=1;i<C7200_MAX_PA_BAYS;i++) |
849 |
router->pa_bay[i].pci_map = vm->pci_bus_pool[i]; |
vm->slots_pci_bus[i] = vm->pci_bus_pool[i]; |
850 |
|
|
851 |
/* PCI bridges for PA Bays 1 to 6 */ |
/* PCI bridges for PA Bays 1 to 6 */ |
852 |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1); |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1); |
867 |
int i; |
int i; |
868 |
|
|
869 |
/* Set the processor type: R4700 */ |
/* Set the processor type: R4700 */ |
870 |
mips64_set_prid(vm->boot_cpu,MIPS_PRID_R4700); |
mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R4700); |
871 |
|
|
872 |
/* Initialize the Galileo GT-64010 system controller */ |
/* Initialize the Galileo GT-64010 system controller */ |
873 |
if (c7200_init_gt64010(router) == -1) |
if (c7200_init_gt64010(router) == -1) |
891 |
dev_dec21050_init(vm->pci_bus[0],4,vm->pci_bus_pool[25]); |
dev_dec21050_init(vm->pci_bus[0],4,vm->pci_bus_pool[25]); |
892 |
|
|
893 |
/* Map the PA PCI busses */ |
/* Map the PA PCI busses */ |
894 |
router->pa_bay[0].pci_map = vm->pci_bus[0]; |
vm->slots_pci_bus[0] = vm->pci_bus[0]; |
895 |
|
|
896 |
for(i=1;i<C7200_MAX_PA_BAYS;i++) |
for(i=1;i<C7200_MAX_PA_BAYS;i++) |
897 |
router->pa_bay[i].pci_map = vm->pci_bus_pool[i]; |
vm->slots_pci_bus[i] = vm->pci_bus_pool[i]; |
898 |
|
|
899 |
/* PCI bridges for PA Bays 1 to 6 */ |
/* PCI bridges for PA Bays 1 to 6 */ |
900 |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1); |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1); |
923 |
int i; |
int i; |
924 |
|
|
925 |
/* Set the processor type: R5271 */ |
/* Set the processor type: R5271 */ |
926 |
mips64_set_prid(vm->boot_cpu,MIPS_PRID_R527x); |
mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R527x); |
927 |
|
|
928 |
/* Initialize the Galileo GT-64120 PCI controller */ |
/* Initialize the Galileo GT-64120 PCI controller */ |
929 |
if (c7200_init_gt64120(router) == -1) |
if (c7200_init_gt64120(router) == -1) |
944 |
|
|
945 |
/* Map the PA PCI busses */ |
/* Map the PA PCI busses */ |
946 |
for(i=0;i<C7200_MAX_PA_BAYS;i++) |
for(i=0;i<C7200_MAX_PA_BAYS;i++) |
947 |
router->pa_bay[i].pci_map = vm->pci_bus_pool[i]; |
vm->slots_pci_bus[i] = vm->pci_bus_pool[i]; |
948 |
|
|
949 |
/* PCI bridges for PA Bays 1 to 6 */ |
/* PCI bridges for PA Bays 1 to 6 */ |
950 |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus[0],7); |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus[0],7); |
968 |
int i; |
int i; |
969 |
|
|
970 |
/* Set the processor type: R5000 */ |
/* Set the processor type: R5000 */ |
971 |
mips64_set_prid(vm->boot_cpu,MIPS_PRID_R5000); |
mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R5000); |
972 |
|
|
973 |
/* Initialize the Galileo GT-64010 PCI controller */ |
/* Initialize the Galileo GT-64010 PCI controller */ |
974 |
if (c7200_init_gt64010(router) == -1) |
if (c7200_init_gt64010(router) == -1) |
992 |
dev_dec21050_init(vm->pci_bus[0],4,vm->pci_bus_pool[25]); |
dev_dec21050_init(vm->pci_bus[0],4,vm->pci_bus_pool[25]); |
993 |
|
|
994 |
/* Map the PA PCI busses */ |
/* Map the PA PCI busses */ |
995 |
router->pa_bay[0].pci_map = vm->pci_bus[0]; |
vm->slots_pci_bus[0] = vm->pci_bus[0]; |
996 |
|
|
997 |
for(i=1;i<C7200_MAX_PA_BAYS;i++) |
for(i=1;i<C7200_MAX_PA_BAYS;i++) |
998 |
router->pa_bay[i].pci_map = vm->pci_bus_pool[i]; |
vm->slots_pci_bus[i] = vm->pci_bus_pool[i]; |
999 |
|
|
1000 |
/* PCI bridges for PA Bays 1 to 6 */ |
/* PCI bridges for PA Bays 1 to 6 */ |
1001 |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1); |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1); |
1024 |
int i; |
int i; |
1025 |
|
|
1026 |
/* Set the processor type: R5271 */ |
/* Set the processor type: R5271 */ |
1027 |
mips64_set_prid(vm->boot_cpu,MIPS_PRID_R527x); |
mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R527x); |
1028 |
|
|
1029 |
/* Initialize the Galileo GT-64120 PCI controller */ |
/* Initialize the Galileo GT-64120 PCI controller */ |
1030 |
if (c7200_init_gt64120(router) == -1) |
if (c7200_init_gt64120(router) == -1) |
1045 |
|
|
1046 |
/* Map the PA PCI busses */ |
/* Map the PA PCI busses */ |
1047 |
for(i=0;i<C7200_MAX_PA_BAYS;i++) |
for(i=0;i<C7200_MAX_PA_BAYS;i++) |
1048 |
router->pa_bay[i].pci_map = vm->pci_bus_pool[i]; |
vm->slots_pci_bus[i] = vm->pci_bus_pool[i]; |
1049 |
|
|
1050 |
/* PCI bridges for PA Bays 1 to 6 */ |
/* PCI bridges for PA Bays 1 to 6 */ |
1051 |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus[0],7); |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus[0],7); |
1068 |
int i; |
int i; |
1069 |
|
|
1070 |
/* Set the processor type: R7000 */ |
/* Set the processor type: R7000 */ |
1071 |
mips64_set_prid(vm->boot_cpu,MIPS_PRID_R7000); |
mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R7000); |
1072 |
|
|
1073 |
/* 32 Mb of I/O memory */ |
/* 32 Mb of I/O memory */ |
1074 |
vm->iomem_size = 32; |
vm->iomem_size = 32; |
1075 |
dev_ram_init(vm,"iomem",vm->ram_mmap,C7200_IOMEM_ADDR,32*1048576); |
dev_ram_init(vm,"iomem",vm->ram_mmap,TRUE,NULL,vm->sparse_mem, |
1076 |
|
C7200_IOMEM_ADDR,32*1048576); |
1077 |
|
|
1078 |
/* Initialize the two Galileo GT-64120 system controllers */ |
/* Initialize the two Galileo GT-64120 system controllers */ |
1079 |
if (c7200_init_dual_gt64120(router) == -1) |
if (c7200_init_dual_gt64120(router) == -1) |
1102 |
|
|
1103 |
/* Map the PA PCI busses */ |
/* Map the PA PCI busses */ |
1104 |
for(i=0;i<C7200_MAX_PA_BAYS;i++) |
for(i=0;i<C7200_MAX_PA_BAYS;i++) |
1105 |
router->pa_bay[i].pci_map = vm->pci_bus_pool[i]; |
vm->slots_pci_bus[i] = vm->pci_bus_pool[i]; |
1106 |
|
|
1107 |
/* PCI bridges for PA Bays 1 to 6 */ |
/* PCI bridges for PA Bays 1 to 6 */ |
1108 |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1); |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1); |
1122 |
int i; |
int i; |
1123 |
|
|
1124 |
/* Set the processor type: R7000 */ |
/* Set the processor type: R7000 */ |
1125 |
mips64_set_prid(vm->boot_cpu,MIPS_PRID_R7000); |
mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R7000); |
1126 |
|
|
1127 |
/* |
/* |
1128 |
* Add supplemental memory (as "iomem") if we have more than 256 Mb. |
* Add supplemental memory (as "iomem") if we have more than 256 Mb. |
1130 |
if (vm->ram_size > C7200_BASE_RAM_LIMIT) { |
if (vm->ram_size > C7200_BASE_RAM_LIMIT) { |
1131 |
vm->iomem_size = vm->ram_size - C7200_BASE_RAM_LIMIT; |
vm->iomem_size = vm->ram_size - C7200_BASE_RAM_LIMIT; |
1132 |
vm->ram_size = C7200_BASE_RAM_LIMIT; |
vm->ram_size = C7200_BASE_RAM_LIMIT; |
1133 |
dev_ram_init(vm,"ram1",vm->ram_mmap, |
dev_ram_init(vm,"ram1",vm->ram_mmap,TRUE,NULL,vm->sparse_mem, |
1134 |
C7200_IOMEM_ADDR,vm->iomem_size*1048576); |
C7200_IOMEM_ADDR,vm->iomem_size*1048576); |
1135 |
} |
} |
1136 |
|
|
1153 |
|
|
1154 |
/* Map the PA PCI busses */ |
/* Map the PA PCI busses */ |
1155 |
for(i=0;i<C7200_MAX_PA_BAYS;i++) |
for(i=0;i<C7200_MAX_PA_BAYS;i++) |
1156 |
router->pa_bay[i].pci_map = vm->pci_bus_pool[i]; |
vm->slots_pci_bus[i] = vm->pci_bus_pool[i]; |
1157 |
|
|
1158 |
/* PCI bridges for PA Bays 1 to 6 */ |
/* PCI bridges for PA Bays 1 to 6 */ |
1159 |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus[0],7); |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus[0],7); |
1173 |
int i; |
int i; |
1174 |
|
|
1175 |
/* Just some tests */ |
/* Just some tests */ |
1176 |
mips64_set_prid(vm->boot_cpu,MIPS_PRID_BCM1250); |
mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_BCM1250); |
1177 |
vm->pci_bus[0] = pci_bus_create("HT/PCI bus",0); |
vm->pci_bus[0] = pci_bus_create("HT/PCI bus",0); |
1178 |
|
|
1179 |
/* SB-1 System control devices */ |
/* SB-1 System control devices */ |
1208 |
c7200_create_io_pci_bridge(router,vm->pci_bus_pool[0]); |
c7200_create_io_pci_bridge(router,vm->pci_bus_pool[0]); |
1209 |
|
|
1210 |
/* Map the PA PCI busses */ |
/* Map the PA PCI busses */ |
1211 |
router->pa_bay[0].pci_map = vm->pci_bus[0]; |
vm->slots_pci_bus[0] = vm->pci_bus[0]; |
1212 |
|
|
1213 |
|
for(i=1;i<C7200_MAX_PA_BAYS;i++) |
1214 |
|
vm->slots_pci_bus[i] = vm->pci_bus_pool[i]; |
1215 |
|
|
1216 |
|
/* PCI bridges for PA Bays 1 to 6 */ |
1217 |
|
c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1); |
1218 |
|
c7200_pa_init_pci_bridge(router,3,vm->pci_bus_pool[24],2); |
1219 |
|
c7200_pa_init_pci_bridge(router,5,vm->pci_bus_pool[24],3); |
1220 |
|
|
1221 |
|
c7200_pa_init_pci_bridge(router,2,vm->pci_bus_pool[25],1); |
1222 |
|
c7200_pa_init_pci_bridge(router,4,vm->pci_bus_pool[25],2); |
1223 |
|
c7200_pa_init_pci_bridge(router,6,vm->pci_bus_pool[25],3); |
1224 |
|
return(0); |
1225 |
|
} |
1226 |
|
|
1227 |
|
/* Initialize an NPE-G2 board (XXX not working) */ |
1228 |
|
int c7200_init_npeg2(c7200_t *router) |
1229 |
|
{ |
1230 |
|
vm_instance_t *vm = router->vm; |
1231 |
|
int i; |
1232 |
|
|
1233 |
|
/* Set the processor type: PowerPC G4 */ |
1234 |
|
ppc32_set_pvr(CPU_PPC32(vm->boot_cpu),0x80040201); |
1235 |
|
|
1236 |
|
/* Initialize the PA PCI busses */ |
1237 |
|
if (c7200_pa_create_pci_busses(router) == -1) |
1238 |
|
return(-1); |
1239 |
|
|
1240 |
|
/* Create PCI bus for PA Bay 0 (I/O Card, PCMCIA, Interfaces) */ |
1241 |
|
vm->pci_bus_pool[0] = pci_bus_create("PA Slot 0",-1); |
1242 |
|
|
1243 |
|
/* PCI bridge for I/O card device on MB0 */ |
1244 |
|
dev_plx6520cb_init(vm->pci_bus[1],3,vm->pci_bus_pool[0]); |
1245 |
|
|
1246 |
|
/* Create PCI busses for PA Bays 1,3,5 and PA Bays 2,4,6 */ |
1247 |
|
vm->pci_bus_pool[24] = pci_bus_create("PA Slots 1,3,5",-1); |
1248 |
|
vm->pci_bus_pool[25] = pci_bus_create("PA Slots 2,4,6",-1); |
1249 |
|
|
1250 |
|
dev_plx6520cb_init(vm->pci_bus[0],1,vm->pci_bus_pool[24]); |
1251 |
|
dev_plx6520cb_init(vm->pci_bus[0],2,vm->pci_bus_pool[25]); |
1252 |
|
|
1253 |
|
/* Create the hidden "I/O" PCI bridge for PCMCIA controller */ |
1254 |
|
c7200_create_io_pci_bridge(router,vm->pci_bus_pool[0]); |
1255 |
|
|
1256 |
|
/* Map the PA PCI busses */ |
1257 |
|
vm->slots_pci_bus[0] = vm->pci_bus_pool[0]; |
1258 |
|
|
1259 |
for(i=1;i<C7200_MAX_PA_BAYS;i++) |
for(i=1;i<C7200_MAX_PA_BAYS;i++) |
1260 |
router->pa_bay[i].pci_map = vm->pci_bus_pool[i]; |
vm->slots_pci_bus[i] = vm->pci_bus_pool[i]; |
1261 |
|
|
1262 |
/* PCI bridges for PA Bays 1 to 6 */ |
/* PCI bridges for PA Bays 1 to 6 */ |
1263 |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1); |
c7200_pa_init_pci_bridge(router,1,vm->pci_bus_pool[24],1); |
1294 |
} |
} |
1295 |
|
|
1296 |
/* Initialize default parameters for a C7200 */ |
/* Initialize default parameters for a C7200 */ |
1297 |
void c7200_init_defaults(c7200_t *router) |
static void c7200_init_defaults(c7200_t *router) |
1298 |
{ |
{ |
1299 |
vm_instance_t *vm = router->vm; |
vm_instance_t *vm = router->vm; |
1300 |
n_eth_addr_t *m; |
n_eth_addr_t *m; |
1301 |
m_uint16_t pid; |
m_uint16_t pid; |
1302 |
|
|
1303 |
|
/* Set platform slots characteristics */ |
1304 |
|
vm->nr_slots = C7200_MAX_PA_BAYS; |
1305 |
|
vm->slots_type = CISCO_CARD_TYPE_PA; |
1306 |
|
vm->slots_drivers = pa_drivers; |
1307 |
|
|
1308 |
pid = (m_uint16_t)getpid(); |
pid = (m_uint16_t)getpid(); |
1309 |
|
|
1310 |
/* Generate a chassis MAC address based on the instance ID */ |
/* Generate a chassis MAC address based on the instance ID */ |
1311 |
m = &router->mac_addr; |
m = &router->mac_addr; |
1312 |
m->eth_addr_byte[0] = 0xCA; |
m->eth_addr_byte[0] = vm_get_mac_addr_msb(vm); |
1313 |
m->eth_addr_byte[1] = vm->instance_id & 0xFF; |
m->eth_addr_byte[1] = vm->instance_id & 0xFF; |
1314 |
m->eth_addr_byte[2] = pid >> 8; |
m->eth_addr_byte[2] = pid >> 8; |
1315 |
m->eth_addr_byte[3] = pid & 0xFF; |
m->eth_addr_byte[3] = pid & 0xFF; |
1316 |
m->eth_addr_byte[4] = 0x00; |
m->eth_addr_byte[4] = 0x00; |
1317 |
m->eth_addr_byte[5] = 0x00; |
m->eth_addr_byte[5] = 0x00; |
1318 |
|
|
1319 |
c7200_init_eeprom_groups(router); |
c7200_init_sys_eeprom_groups(router); |
1320 |
|
c7200_init_mp_eeprom_groups(router); |
1321 |
c7200_npe_set_type(router,C7200_DEFAULT_NPE_TYPE); |
c7200_npe_set_type(router,C7200_DEFAULT_NPE_TYPE); |
1322 |
c7200_midplane_set_type(router,C7200_DEFAULT_MIDPLANE); |
c7200_midplane_set_type(router,C7200_DEFAULT_MIDPLANE); |
1323 |
|
|
1335 |
} |
} |
1336 |
|
|
1337 |
/* Run the checklist */ |
/* Run the checklist */ |
1338 |
int c7200_checklist(c7200_t *router) |
static int c7200_checklist(c7200_t *router) |
1339 |
{ |
{ |
1340 |
struct vm_instance *vm = router->vm; |
struct vm_instance *vm = router->vm; |
1341 |
int res = 0; |
int res = 0; |
1351 |
return(res); |
return(res); |
1352 |
} |
} |
1353 |
|
|
1354 |
/* Initialize the C7200 Platform */ |
/* Initialize Port Adapters */ |
1355 |
int c7200_init_platform(c7200_t *router) |
static int c7200_init_platform_pa(c7200_t *router) |
1356 |
|
{ |
1357 |
|
return(vm_slot_init_all(router->vm)); |
1358 |
|
} |
1359 |
|
|
1360 |
|
/* Initialize the C7200 Platform (MIPS) */ |
1361 |
|
static int c7200m_init_platform(c7200_t *router) |
1362 |
{ |
{ |
1363 |
struct vm_instance *vm = router->vm; |
struct vm_instance *vm = router->vm; |
1364 |
struct c7200_pa_bay *pa_bay; |
cpu_mips_t *cpu0; |
1365 |
cpu_mips_t *cpu0; |
cpu_gen_t *gen0; |
1366 |
int i; |
vm_obj_t *obj; |
1367 |
|
|
1368 |
/* Copy config register setup into "active" config register */ |
/* Copy config register setup into "active" config register */ |
1369 |
vm->conf_reg = vm->conf_reg_setup; |
vm->conf_reg = vm->conf_reg_setup; |
1384 |
vm->cpu_group = cpu_group_create("System CPU"); |
vm->cpu_group = cpu_group_create("System CPU"); |
1385 |
|
|
1386 |
/* Initialize the virtual MIPS processor */ |
/* Initialize the virtual MIPS processor */ |
1387 |
if (!(cpu0 = cpu_create(vm,0))) { |
if (!(gen0 = cpu_create(vm,CPU_TYPE_MIPS64,0))) { |
1388 |
vm_error(vm,"unable to create CPU0!\n"); |
vm_error(vm,"unable to create CPU0!\n"); |
1389 |
return(-1); |
return(-1); |
1390 |
} |
} |
1391 |
|
|
1392 |
|
cpu0 = CPU_MIPS64(gen0); |
1393 |
|
|
1394 |
/* Add this CPU to the system CPU group */ |
/* Add this CPU to the system CPU group */ |
1395 |
cpu_group_add(vm->cpu_group,cpu0); |
cpu_group_add(vm->cpu_group,gen0); |
1396 |
vm->boot_cpu = cpu0; |
vm->boot_cpu = gen0; |
1397 |
|
|
1398 |
|
/* Initialize the IRQ routing vectors */ |
1399 |
|
vm->set_irq = mips64_vm_set_irq; |
1400 |
|
vm->clear_irq = mips64_vm_clear_irq; |
1401 |
|
|
1402 |
/* Mark the Network IO interrupt as high priority */ |
/* Mark the Network IO interrupt as high priority */ |
1403 |
cpu0->irq_idle_preempt[C7200_NETIO_IRQ] = TRUE; |
cpu0->irq_idle_preempt[C7200_NETIO_IRQ] = TRUE; |
1404 |
|
cpu0->irq_idle_preempt[C7200_GT64K_IRQ] = TRUE; |
1405 |
|
|
1406 |
/* Copy some parameters from VM to CPU0 (idle PC, ...) */ |
/* Copy some parameters from VM to CPU0 (idle PC, ...) */ |
1407 |
cpu0->idle_pc = vm->idle_pc; |
cpu0->idle_pc = vm->idle_pc; |
1418 |
/* Remote emulator control */ |
/* Remote emulator control */ |
1419 |
dev_remote_control_init(vm,0x16000000,0x1000); |
dev_remote_control_init(vm,0x16000000,0x1000); |
1420 |
|
|
1421 |
/* Bootflash */ |
/* Bootflash (8 Mb) */ |
1422 |
dev_bootflash_init(vm,"bootflash",C7200_BOOTFLASH_ADDR,(8 * 1048576)); |
dev_bootflash_init(vm,"bootflash","c7200-bootflash-8mb", |
1423 |
|
C7200_BOOTFLASH_ADDR); |
1424 |
|
|
1425 |
/* NVRAM and calendar */ |
/* NVRAM and calendar */ |
1426 |
dev_nvram_init(vm,"nvram",router->npe_driver->nvram_addr, |
dev_nvram_init(vm,"nvram",router->npe_driver->nvram_addr, |
1429 |
/* Bit-bucket zone */ |
/* Bit-bucket zone */ |
1430 |
dev_zero_init(vm,"zero",C7200_BITBUCKET_ADDR,0xc00000); |
dev_zero_init(vm,"zero",C7200_BITBUCKET_ADDR,0xc00000); |
1431 |
|
|
1432 |
|
/* Initialize the NPE board */ |
1433 |
|
if (router->npe_driver->npe_init(router) == -1) |
1434 |
|
return(-1); |
1435 |
|
|
1436 |
|
/* Initialize RAM */ |
1437 |
|
vm_ram_init(vm,0x00000000ULL); |
1438 |
|
|
1439 |
|
/* Initialize ROM */ |
1440 |
|
if (!vm->rom_filename) { |
1441 |
|
/* use embedded ROM */ |
1442 |
|
dev_rom_init(vm,"rom",C7200_ROM_ADDR,vm->rom_size*1048576, |
1443 |
|
mips64_microcode,mips64_microcode_len); |
1444 |
|
} else { |
1445 |
|
/* use alternate ROM */ |
1446 |
|
dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE, |
1447 |
|
C7200_ROM_ADDR,vm->rom_size*1048576); |
1448 |
|
} |
1449 |
|
|
1450 |
|
/* Byte swapping */ |
1451 |
|
dev_bswap_init(vm,"mem_bswap",C7200_BSWAP_ADDR,1024*1048576,0x00000000ULL); |
1452 |
|
|
1453 |
|
/* PCI IO space */ |
1454 |
|
if (!(vm->pci_io_space = pci_io_data_init(vm,C7200_PCI_IO_ADDR))) |
1455 |
|
return(-1); |
1456 |
|
|
1457 |
|
/* Cirrus Logic PD6729 (PCI-to-PCMCIA host adapter) */ |
1458 |
|
dev_clpd6729_init(vm,router->pcmcia_bus, |
1459 |
|
router->npe_driver->clpd6729_pci_dev, |
1460 |
|
vm->pci_io_space,0x402,0x403); |
1461 |
|
|
1462 |
|
/* Initialize the Port Adapters */ |
1463 |
|
if (c7200_init_platform_pa(router) == -1) |
1464 |
|
return(-1); |
1465 |
|
|
1466 |
|
/* Verify the check list */ |
1467 |
|
if (c7200_checklist(router) == -1) |
1468 |
|
return(-1); |
1469 |
|
|
1470 |
/* Midplane FPGA */ |
/* Midplane FPGA */ |
1471 |
dev_c7200_mpfpga_init(router,C7200_MPFPGA_ADDR,0x1000); |
dev_c7200_mpfpga_init(router,C7200_MPFPGA_ADDR,0x1000); |
1472 |
|
|
1473 |
|
if (!(obj = vm_object_find(router->vm,"mp_fpga"))) |
1474 |
|
return(-1); |
1475 |
|
|
1476 |
|
router->mpfpga_data = obj->data; |
1477 |
|
|
1478 |
/* IO FPGA */ |
/* IO FPGA */ |
1479 |
if (dev_c7200_iofpga_init(router,C7200_IOFPGA_ADDR,0x1000) == -1) |
if (dev_c7200_iofpga_init(router,C7200_IOFPGA_ADDR,0x1000) == -1) |
1480 |
return(-1); |
return(-1); |
1481 |
|
|
1482 |
|
/* Show device list */ |
1483 |
|
c7200_show_hardware(router); |
1484 |
|
return(0); |
1485 |
|
} |
1486 |
|
|
1487 |
|
/* Initialize the C7200 Platform (PowerPC) */ |
1488 |
|
static int c7200p_init_platform(c7200_t *router) |
1489 |
|
{ |
1490 |
|
struct vm_instance *vm = router->vm; |
1491 |
|
cpu_ppc_t *cpu0; |
1492 |
|
cpu_gen_t *gen0; |
1493 |
|
vm_obj_t *obj; |
1494 |
|
|
1495 |
|
/* Copy config register setup into "active" config register */ |
1496 |
|
vm->conf_reg = vm->conf_reg_setup; |
1497 |
|
|
1498 |
|
/* Create Console and AUX ports */ |
1499 |
|
vm_init_vtty(vm); |
1500 |
|
|
1501 |
|
/* Check that the amount of RAM is valid */ |
1502 |
|
if (vm->ram_size > router->npe_driver->max_ram_size) { |
1503 |
|
vm_error(vm,"%u is not a valid RAM size for this NPE. " |
1504 |
|
"Fallback to %u Mb.\n\n", |
1505 |
|
vm->ram_size,router->npe_driver->max_ram_size); |
1506 |
|
|
1507 |
|
vm->ram_size = router->npe_driver->max_ram_size; |
1508 |
|
} |
1509 |
|
|
1510 |
|
/* Create a CPU group */ |
1511 |
|
vm->cpu_group = cpu_group_create("System CPU"); |
1512 |
|
|
1513 |
|
/* Initialize the virtual PowerPC processor */ |
1514 |
|
if (!(gen0 = cpu_create(vm,CPU_TYPE_PPC32,0))) { |
1515 |
|
vm_error(vm,"unable to create CPU0!\n"); |
1516 |
|
return(-1); |
1517 |
|
} |
1518 |
|
|
1519 |
|
cpu0 = CPU_PPC32(gen0); |
1520 |
|
|
1521 |
|
/* Add this CPU to the system CPU group */ |
1522 |
|
cpu_group_add(vm->cpu_group,gen0); |
1523 |
|
vm->boot_cpu = gen0; |
1524 |
|
|
1525 |
|
/* Mark the Network IO interrupt as high priority */ |
1526 |
|
vm->irq_idle_preempt[C7200_NETIO_IRQ] = TRUE; |
1527 |
|
|
1528 |
|
/* Copy some parameters from VM to CPU0 (idle PC, ...) */ |
1529 |
|
cpu0->idle_pc = vm->idle_pc; |
1530 |
|
|
1531 |
|
if (vm->timer_irq_check_itv) |
1532 |
|
cpu0->timer_irq_check_itv = vm->timer_irq_check_itv; |
1533 |
|
|
1534 |
|
/* Initialize the Marvell MV-64460 system controller */ |
1535 |
|
if (c7200_init_mv64460(router) == -1) |
1536 |
|
return(-1); |
1537 |
|
|
1538 |
|
if (!(obj = vm_object_find(router->vm,"mv64460"))) |
1539 |
|
return(-1); |
1540 |
|
|
1541 |
|
router->mv64460_sysctr = obj->data; |
1542 |
|
|
1543 |
|
/* Remote emulator control */ |
1544 |
|
dev_remote_control_init(vm,0xf6000000,0x1000); |
1545 |
|
|
1546 |
|
/* Bootflash (64 Mb) */ |
1547 |
|
dev_bootflash_init(vm,"bootflash","c7200-bootflash-64mb", |
1548 |
|
C7200_G2_BOOTFLASH_ADDR); |
1549 |
|
|
1550 |
|
/* NVRAM and calendar */ |
1551 |
|
vm->nvram_size = C7200_G2_NVRAM_SIZE / 1024; |
1552 |
|
dev_nvram_init(vm,"nvram",router->npe_driver->nvram_addr, |
1553 |
|
C7200_G2_NVRAM_SIZE,&vm->conf_reg); |
1554 |
|
|
1555 |
/* Initialize the NPE board */ |
/* Initialize the NPE board */ |
1556 |
if (router->npe_driver->npe_init(router) == -1) |
if (router->npe_driver->npe_init(router) == -1) |
1557 |
return(-1); |
return(-1); |
1558 |
|
|
1559 |
/* Initialize RAM */ |
/* Initialize RAM */ |
1560 |
dev_ram_init(vm,"ram",vm->ram_mmap,0x00000000ULL,vm->ram_size*1048576); |
vm_ram_init(vm,0x00000000ULL); |
1561 |
|
|
1562 |
/* Initialize ROM */ |
/* Initialize ROM */ |
1563 |
if (!vm->rom_filename) { |
if (!vm->rom_filename) { |
1564 |
/* use embedded ROM */ |
/* use embedded ROM */ |
1565 |
dev_rom_init(vm,"rom",C7200_ROM_ADDR,vm->rom_size*1048576); |
dev_rom_init(vm,"rom",C7200_G2_ROM_ADDR,vm->rom_size*1048576, |
1566 |
|
ppc32_microcode,ppc32_microcode_len); |
1567 |
} else { |
} else { |
1568 |
/* use alternate ROM */ |
/* use alternate ROM */ |
1569 |
dev_ram_init(vm,"rom",TRUE,C7200_ROM_ADDR,vm->rom_size*1048576); |
dev_ram_init(vm,"rom",TRUE,TRUE,NULL,FALSE, |
1570 |
|
C7200_G2_ROM_ADDR,vm->rom_size*1048576); |
1571 |
} |
} |
1572 |
|
|
1573 |
|
/* Byte swapping */ |
1574 |
|
dev_bswap_init(vm,"mem_bswap",C7200_G2_BSWAP_ADDR,512*1048576, |
1575 |
|
0x00000000ULL); |
1576 |
|
|
1577 |
/* PCI IO space */ |
/* PCI IO space */ |
1578 |
if (!(vm->pci_io_space = pci_io_data_init(vm,C7200_PCI_IO_ADDR))) |
if (!(vm->pci_io_space = pci_io_data_init(vm,C7200_G2_PCI_IO_ADDR))) |
1579 |
return(-1); |
return(-1); |
1580 |
|
|
1581 |
/* Cirrus Logic PD6729 (PCI-to-PCMCIA host adapter) */ |
/* Cirrus Logic PD6729 (PCI-to-PCMCIA host adapter) */ |
1583 |
router->npe_driver->clpd6729_pci_dev, |
router->npe_driver->clpd6729_pci_dev, |
1584 |
vm->pci_io_space,0x402,0x403); |
vm->pci_io_space,0x402,0x403); |
1585 |
|
|
1586 |
/* Initialize Port Adapters */ |
/* Initialize the Port Adapters */ |
1587 |
for(i=0;i<C7200_MAX_PA_BAYS;i++) { |
if (c7200_init_platform_pa(router) == -1) |
1588 |
pa_bay = &router->pa_bay[i]; |
return(-1); |
1589 |
|
|
1590 |
if (!pa_bay->dev_type) |
/* IO FPGA */ |
1591 |
continue; |
if (dev_c7200_iofpga_init(router,C7200_G2_IOFPGA_ADDR,0x1000) == -1) |
1592 |
|
return(-1); |
|
if (c7200_pa_init(router,i) == -1) { |
|
|
vm_error(vm,"unable to create Port Adapter \"%s\"\n", |
|
|
pa_bay->dev_type); |
|
|
return(-1); |
|
|
} |
|
|
} |
|
|
|
|
|
/* By default, initialize a C7200-IO-FE in slot 0 if nothing found */ |
|
|
if (!router->pa_bay[0].drv_info) { |
|
|
c7200_pa_add_binding(router,"C7200-IO-FE",0); |
|
|
c7200_pa_init(router,0); |
|
|
} |
|
1593 |
|
|
1594 |
/* Enable NVRAM operations to load/store configs */ |
/* MP FPGA */ |
1595 |
vm->nvram_extract_config = c7200_nvram_extract_config; |
if (dev_c7200_mpfpga_init(router,C7200_G2_MPFPGA_ADDR,0x10000) == -1) |
1596 |
vm->nvram_push_config = c7200_nvram_push_config; |
return(-1); |
1597 |
|
|
1598 |
/* Verify the check list */ |
if (!(obj = vm_object_find(router->vm,"mp_fpga"))) |
|
if (c7200_checklist(router) == -1) |
|
1599 |
return(-1); |
return(-1); |
1600 |
|
|
1601 |
|
router->mpfpga_data = obj->data; |
1602 |
|
|
1603 |
|
/* If we have nothing in slot 0, the console is handled by the MV64460 */ |
1604 |
|
if (!vm_slot_get_card_ptr(vm,0)) { |
1605 |
|
vm_log(vm,"CONSOLE","console managed by NPE-G2 board\n"); |
1606 |
|
mv64460_sdma_bind_vtty(router->mv64460_sysctr,0,vm->vtty_con); |
1607 |
|
mv64460_sdma_bind_vtty(router->mv64460_sysctr,1,vm->vtty_aux); |
1608 |
|
} |
1609 |
|
|
1610 |
/* Show device list */ |
/* Show device list */ |
1611 |
c7200_show_hardware(router); |
c7200_show_hardware(router); |
1612 |
return(0); |
return(0); |
1613 |
} |
} |
1614 |
|
|
1615 |
/* Boot the IOS image */ |
/* Boot the IOS image (MIPS) */ |
1616 |
int c7200_boot_ios(c7200_t *router) |
static int c7200m_boot_ios(c7200_t *router) |
1617 |
{ |
{ |
1618 |
vm_instance_t *vm = router->vm; |
vm_instance_t *vm = router->vm; |
1619 |
|
cpu_mips_t *cpu; |
1620 |
|
|
1621 |
if (!vm->boot_cpu) |
if (!vm->boot_cpu) |
1622 |
return(-1); |
return(-1); |
1631 |
} |
} |
1632 |
|
|
1633 |
/* Reset the boot CPU */ |
/* Reset the boot CPU */ |
1634 |
mips64_reset(vm->boot_cpu); |
cpu = CPU_MIPS64(vm->boot_cpu); |
1635 |
|
mips64_reset(cpu); |
1636 |
|
|
1637 |
/* Load IOS image */ |
/* Load IOS image */ |
1638 |
if (mips64_load_elf_image(vm->boot_cpu,vm->ios_image, |
if (mips64_load_elf_image(cpu,vm->ios_image, |
1639 |
&vm->ios_entry_point) < 0) |
(vm->ghost_status == VM_GHOST_RAM_USE), |
1640 |
|
&vm->ios_entry_point) < 0) |
1641 |
{ |
{ |
1642 |
vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image); |
vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image); |
1643 |
return(-1); |
return(-1); |
1646 |
/* Launch the simulation */ |
/* Launch the simulation */ |
1647 |
printf("\nC7200 '%s': starting simulation (CPU0 PC=0x%llx), " |
printf("\nC7200 '%s': starting simulation (CPU0 PC=0x%llx), " |
1648 |
"JIT %sabled.\n", |
"JIT %sabled.\n", |
1649 |
vm->name,vm->boot_cpu->pc,vm->jit_use ? "en":"dis"); |
vm->name,cpu->pc,vm->jit_use ? "en":"dis"); |
1650 |
|
|
1651 |
vm_log(vm,"C7200_BOOT", |
vm_log(vm,"C7200_BOOT", |
1652 |
"starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n", |
"starting instance (CPU0 PC=0x%llx,idle_pc=0x%llx,JIT %s)\n", |
1653 |
vm->boot_cpu->pc,vm->boot_cpu->idle_pc,vm->jit_use ? "on":"off"); |
cpu->pc,cpu->idle_pc,vm->jit_use ? "on":"off"); |
1654 |
|
|
1655 |
/* Start main CPU */ |
/* Start main CPU */ |
1656 |
vm->status = VM_STATUS_RUNNING; |
if (vm->ghost_status != VM_GHOST_RAM_GENERATE) { |
1657 |
cpu_start(vm->boot_cpu); |
vm->status = VM_STATUS_RUNNING; |
1658 |
|
cpu_start(vm->boot_cpu); |
1659 |
|
} else { |
1660 |
|
vm->status = VM_STATUS_SHUTDOWN; |
1661 |
|
} |
1662 |
return(0); |
return(0); |
1663 |
} |
} |
1664 |
|
|
1665 |
/* Initialize a Cisco 7200 instance */ |
/* Boot the IOS image (PowerPC) */ |
1666 |
int c7200_init_instance(c7200_t *router) |
static int c7200p_boot_ios(c7200_t *router) |
1667 |
|
{ |
1668 |
|
vm_instance_t *vm = router->vm; |
1669 |
|
cpu_ppc_t *cpu; |
1670 |
|
|
1671 |
|
if (!vm->boot_cpu) |
1672 |
|
return(-1); |
1673 |
|
|
1674 |
|
/* Suspend CPU activity since we will restart directly from ROM */ |
1675 |
|
vm_suspend(vm); |
1676 |
|
|
1677 |
|
/* Check that CPU activity is really suspended */ |
1678 |
|
if (cpu_group_sync_state(vm->cpu_group) == -1) { |
1679 |
|
vm_error(vm,"unable to sync with system CPUs.\n"); |
1680 |
|
return(-1); |
1681 |
|
} |
1682 |
|
|
1683 |
|
/* Reset the boot CPU */ |
1684 |
|
cpu = CPU_PPC32(vm->boot_cpu); |
1685 |
|
ppc32_reset(cpu); |
1686 |
|
|
1687 |
|
/* Load IOS image */ |
1688 |
|
if (ppc32_load_elf_image(cpu,vm->ios_image, |
1689 |
|
(vm->ghost_status == VM_GHOST_RAM_USE), |
1690 |
|
&vm->ios_entry_point) < 0) |
1691 |
|
{ |
1692 |
|
vm_error(vm,"failed to load Cisco IOS image '%s'.\n",vm->ios_image); |
1693 |
|
return(-1); |
1694 |
|
} |
1695 |
|
|
1696 |
|
/* Launch the simulation */ |
1697 |
|
printf("\nC7200P '%s': starting simulation (CPU0 IA=0x%8.8x), " |
1698 |
|
"JIT %sabled.\n", |
1699 |
|
vm->name,cpu->ia,vm->jit_use ? "en":"dis"); |
1700 |
|
|
1701 |
|
vm_log(vm,"C7200P_BOOT", |
1702 |
|
"starting instance (CPU0 IA=0x%8.8x,idle_pc=0x%8.8x,JIT %s)\n", |
1703 |
|
cpu->ia,cpu->idle_pc,vm->jit_use ? "on":"off"); |
1704 |
|
|
1705 |
|
/* Start main CPU */ |
1706 |
|
if (vm->ghost_status != VM_GHOST_RAM_GENERATE) { |
1707 |
|
vm->status = VM_STATUS_RUNNING; |
1708 |
|
cpu_start(vm->boot_cpu); |
1709 |
|
} else { |
1710 |
|
vm->status = VM_STATUS_SHUTDOWN; |
1711 |
|
} |
1712 |
|
return(0); |
1713 |
|
} |
1714 |
|
|
1715 |
|
/* Set an IRQ */ |
1716 |
|
static void c7200m_set_irq(vm_instance_t *vm,u_int irq) |
1717 |
|
{ |
1718 |
|
c7200_t *router = VM_C7200(vm); |
1719 |
|
cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu); |
1720 |
|
u_int slot,port; |
1721 |
|
|
1722 |
|
switch(irq) { |
1723 |
|
case 0 ... 7: |
1724 |
|
mips64_set_irq(cpu0,irq); |
1725 |
|
|
1726 |
|
if (cpu0->irq_idle_preempt[irq]) |
1727 |
|
cpu_idle_break_wait(cpu0->gen); |
1728 |
|
break; |
1729 |
|
|
1730 |
|
case C7200_NETIO_IRQ_BASE ... C7200_NETIO_IRQ_END: |
1731 |
|
c7200_net_irq_get_slot_port(irq,&slot,&port); |
1732 |
|
dev_c7200_mpfpga_net_set_irq(router->mpfpga_data,slot,port); |
1733 |
|
break; |
1734 |
|
} |
1735 |
|
} |
1736 |
|
|
1737 |
|
/* Clear an IRQ */ |
1738 |
|
static void c7200m_clear_irq(vm_instance_t *vm,u_int irq) |
1739 |
|
{ |
1740 |
|
c7200_t *router = VM_C7200(vm); |
1741 |
|
cpu_mips_t *cpu0 = CPU_MIPS64(vm->boot_cpu); |
1742 |
|
u_int slot,port; |
1743 |
|
|
1744 |
|
switch(irq) { |
1745 |
|
case 0 ... 7: |
1746 |
|
mips64_clear_irq(cpu0,irq); |
1747 |
|
break; |
1748 |
|
|
1749 |
|
case C7200_NETIO_IRQ_BASE ... C7200_NETIO_IRQ_END: |
1750 |
|
c7200_net_irq_get_slot_port(irq,&slot,&port); |
1751 |
|
dev_c7200_mpfpga_net_clear_irq(router->mpfpga_data,slot,port); |
1752 |
|
break; |
1753 |
|
} |
1754 |
|
} |
1755 |
|
|
1756 |
|
/* Initialize a Cisco 7200 instance (MIPS) */ |
1757 |
|
static int c7200m_init_instance(c7200_t *router) |
1758 |
{ |
{ |
1759 |
vm_instance_t *vm = router->vm; |
vm_instance_t *vm = router->vm; |
1760 |
m_uint32_t rom_entry_point; |
m_uint32_t rom_entry_point; |
1761 |
cpu_mips_t *cpu0; |
cpu_mips_t *cpu0; |
1762 |
|
|
1763 |
/* Initialize the C7200 platform */ |
/* Initialize the C7200 platform */ |
1764 |
if (c7200_init_platform(router) == -1) { |
if (c7200m_init_platform(router) == -1) { |
1765 |
vm_error(vm,"unable to initialize the platform hardware.\n"); |
vm_error(vm,"unable to initialize the platform hardware.\n"); |
1766 |
return(-1); |
return(-1); |
1767 |
} |
} |
1768 |
|
|
1769 |
|
/* IRQ routing */ |
1770 |
|
vm->set_irq = c7200m_set_irq; |
1771 |
|
vm->clear_irq = c7200m_clear_irq; |
1772 |
|
|
1773 |
/* Load IOS configuration file */ |
/* Load IOS configuration file */ |
1774 |
if (vm->ios_config != NULL) { |
if (vm->ios_config != NULL) { |
1775 |
vm_nvram_push_config(vm,vm->ios_config); |
vm_nvram_push_config(vm,vm->ios_config); |
1777 |
} |
} |
1778 |
|
|
1779 |
/* Load ROM (ELF image or embedded) */ |
/* Load ROM (ELF image or embedded) */ |
1780 |
cpu0 = vm->boot_cpu; |
cpu0 = CPU_MIPS64(vm->boot_cpu); |
1781 |
rom_entry_point = (m_uint32_t)MIPS_ROM_PC; |
rom_entry_point = (m_uint32_t)MIPS_ROM_PC; |
1782 |
|
|
1783 |
if ((vm->rom_filename != NULL) && |
if ((vm->rom_filename != NULL) && |
1784 |
(mips64_load_elf_image(cpu0,vm->rom_filename,&rom_entry_point) < 0)) |
(mips64_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0)) |
1785 |
{ |
{ |
1786 |
vm_error(vm,"unable to load alternate ROM '%s', " |
vm_error(vm,"unable to load alternate ROM '%s', " |
1787 |
"fallback to embedded ROM.\n\n",vm->rom_filename); |
"fallback to embedded ROM.\n\n",vm->rom_filename); |
1794 |
cpu0->sym_trace = 1; |
cpu0->sym_trace = 1; |
1795 |
} |
} |
1796 |
|
|
1797 |
return(c7200_boot_ios(router)); |
return(c7200m_boot_ios(router)); |
1798 |
} |
} |
1799 |
|
|
1800 |
/* Stop a Cisco 7200 instance */ |
/* Set an IRQ */ |
1801 |
int c7200_stop_instance(c7200_t *router) |
static void c7200p_set_irq(vm_instance_t *vm,u_int irq) |
1802 |
|
{ |
1803 |
|
c7200_t *router = VM_C7200(vm); |
1804 |
|
cpu_ppc_t *cpu0 = CPU_PPC32(vm->boot_cpu); |
1805 |
|
u_int slot,port; |
1806 |
|
|
1807 |
|
switch(irq) { |
1808 |
|
case C7200_VTIMER_IRQ: |
1809 |
|
ppc32_trigger_timer_irq(cpu0); |
1810 |
|
break; |
1811 |
|
case C7200_DUART_IRQ: |
1812 |
|
dev_mv64460_set_gpp_intr(router->mv64460_sysctr,10); |
1813 |
|
break; |
1814 |
|
case C7200_NETIO_IRQ: |
1815 |
|
dev_mv64460_set_gpp_intr(router->mv64460_sysctr,24); |
1816 |
|
break; |
1817 |
|
case C7200_PA_MGMT_IRQ: |
1818 |
|
dev_mv64460_set_gpp_intr(router->mv64460_sysctr,20); |
1819 |
|
break; |
1820 |
|
case C7200_OIR_IRQ: |
1821 |
|
dev_mv64460_set_gpp_intr(router->mv64460_sysctr,0); |
1822 |
|
break; |
1823 |
|
case C7200_NETIO_IRQ_BASE ... C7200_NETIO_IRQ_END: |
1824 |
|
c7200_net_irq_get_slot_port(irq,&slot,&port); |
1825 |
|
dev_c7200_mpfpga_net_set_irq(router->mpfpga_data,slot,port); |
1826 |
|
break; |
1827 |
|
} |
1828 |
|
|
1829 |
|
if (vm->irq_idle_preempt[irq]) |
1830 |
|
cpu_idle_break_wait(cpu0->gen); |
1831 |
|
} |
1832 |
|
|
1833 |
|
/* Clear an IRQ */ |
1834 |
|
static void c7200p_clear_irq(vm_instance_t *vm,u_int irq) |
1835 |
|
{ |
1836 |
|
c7200_t *router = VM_C7200(vm); |
1837 |
|
u_int slot,port; |
1838 |
|
|
1839 |
|
switch(irq) { |
1840 |
|
case C7200_DUART_IRQ: |
1841 |
|
dev_mv64460_clear_gpp_intr(router->mv64460_sysctr,10); |
1842 |
|
break; |
1843 |
|
case C7200_NETIO_IRQ: |
1844 |
|
dev_mv64460_clear_gpp_intr(router->mv64460_sysctr,24); |
1845 |
|
break; |
1846 |
|
case C7200_PA_MGMT_IRQ: |
1847 |
|
dev_mv64460_clear_gpp_intr(router->mv64460_sysctr,20); |
1848 |
|
break; |
1849 |
|
case C7200_OIR_IRQ: |
1850 |
|
dev_mv64460_clear_gpp_intr(router->mv64460_sysctr,0); |
1851 |
|
break; |
1852 |
|
case C7200_NETIO_IRQ_BASE ... C7200_NETIO_IRQ_END: |
1853 |
|
c7200_net_irq_get_slot_port(irq,&slot,&port); |
1854 |
|
dev_c7200_mpfpga_net_clear_irq(router->mpfpga_data,slot,port); |
1855 |
|
break; |
1856 |
|
} |
1857 |
|
} |
1858 |
|
|
1859 |
|
/* Initialize a Cisco 7200 instance (PowerPC) */ |
1860 |
|
static int c7200p_init_instance(c7200_t *router) |
1861 |
{ |
{ |
1862 |
vm_instance_t *vm = router->vm; |
vm_instance_t *vm = router->vm; |
1863 |
|
m_uint32_t rom_entry_point; |
1864 |
|
cpu_ppc_t *cpu0; |
1865 |
|
int i; |
1866 |
|
|
1867 |
|
/* Initialize the C7200 platform */ |
1868 |
|
if (c7200p_init_platform(router) == -1) { |
1869 |
|
vm_error(vm,"unable to initialize the platform hardware.\n"); |
1870 |
|
return(-1); |
1871 |
|
} |
1872 |
|
|
1873 |
|
/* IRQ routing */ |
1874 |
|
vm->set_irq = c7200p_set_irq; |
1875 |
|
vm->clear_irq = c7200p_clear_irq; |
1876 |
|
|
1877 |
|
/* Load ROM (ELF image or embedded) */ |
1878 |
|
cpu0 = CPU_PPC32(vm->boot_cpu); |
1879 |
|
rom_entry_point = (m_uint32_t)PPC32_ROM_START; |
1880 |
|
|
1881 |
|
if ((vm->rom_filename != NULL) && |
1882 |
|
(ppc32_load_elf_image(cpu0,vm->rom_filename,0,&rom_entry_point) < 0)) |
1883 |
|
{ |
1884 |
|
vm_error(vm,"unable to load alternate ROM '%s', " |
1885 |
|
"fallback to embedded ROM.\n\n",vm->rom_filename); |
1886 |
|
vm->rom_filename = NULL; |
1887 |
|
} |
1888 |
|
|
1889 |
|
/* Initialize the MMU (TEST) */ |
1890 |
|
for(i=0;i<PPC32_SR_NR;i++) |
1891 |
|
cpu0->sr[i] = i << 16; |
1892 |
|
|
1893 |
|
ppc32_set_sdr1(cpu0,((vm->ram_size - 2) * 1048576) + 0x1F); |
1894 |
|
ppc32_init_page_table(cpu0); |
1895 |
|
ppc32_map_zone(cpu0,cpu0->sr[C7200_G2_BOOTFLASH_ADDR >> 28], |
1896 |
|
C7200_G2_BOOTFLASH_ADDR,C7200_G2_BOOTFLASH_ADDR, |
1897 |
|
64*1048576,0,0x02); |
1898 |
|
|
1899 |
|
ppc32_map_zone(cpu0,cpu0->sr[0xD8000000 >> 28], |
1900 |
|
0xD8000000,0xD8000000,0x400000,0,0x02); |
1901 |
|
ppc32_map_zone(cpu0,cpu0->sr[0xDC000000 >> 28], |
1902 |
|
0xDC000000,0xDC000000,0x400000,0,0x02); |
1903 |
|
|
1904 |
|
/* INST */ |
1905 |
|
cpu0->bat[PPC32_IBAT_IDX][0].reg[0] = 0x00003FFE; |
1906 |
|
cpu0->bat[PPC32_IBAT_IDX][0].reg[1] = 0x00000003; |
1907 |
|
|
1908 |
|
cpu0->bat[PPC32_IBAT_IDX][3].reg[0] = 0xF0001FFE; |
1909 |
|
cpu0->bat[PPC32_IBAT_IDX][3].reg[1] = 0xF0000003; |
1910 |
|
|
1911 |
|
/* DATA */ |
1912 |
|
cpu0->bat[PPC32_DBAT_IDX][0].reg[0] = 0x00003FFE; |
1913 |
|
cpu0->bat[PPC32_DBAT_IDX][0].reg[1] = 0x00000003; |
1914 |
|
|
1915 |
|
cpu0->bat[PPC32_DBAT_IDX][3].reg[0] = 0xF0001FFE; |
1916 |
|
cpu0->bat[PPC32_DBAT_IDX][3].reg[1] = 0xF0000003; |
1917 |
|
|
1918 |
|
|
1919 |
|
return(c7200p_boot_ios(router)); |
1920 |
|
} |
1921 |
|
|
1922 |
|
/* Initialize a Cisco 7200 instance */ |
1923 |
|
static int c7200_init_instance(vm_instance_t *vm) |
1924 |
|
{ |
1925 |
|
c7200_t *router = VM_C7200(vm); |
1926 |
|
|
1927 |
|
switch(router->npe_driver->npe_family) { |
1928 |
|
case C7200_NPE_FAMILY_MIPS: |
1929 |
|
return(c7200m_init_instance(router)); |
1930 |
|
|
1931 |
|
case C7200_NPE_FAMILY_PPC: |
1932 |
|
return(c7200p_init_instance(router)); |
1933 |
|
|
1934 |
|
default: |
1935 |
|
vm_error(router->vm,"unsupported NPE family %d", |
1936 |
|
router->npe_driver->npe_family); |
1937 |
|
return(-1); |
1938 |
|
} |
1939 |
|
} |
1940 |
|
|
1941 |
|
/* Stop a Cisco 7200 instance */ |
1942 |
|
static int c7200_stop_instance(vm_instance_t *vm) |
1943 |
|
{ |
1944 |
printf("\nC7200 '%s': stopping simulation.\n",vm->name); |
printf("\nC7200 '%s': stopping simulation.\n",vm->name); |
1945 |
vm_log(vm,"C7200_STOP","stopping simulation.\n"); |
vm_log(vm,"C7200_STOP","stopping simulation.\n"); |
1946 |
|
|
1955 |
} |
} |
1956 |
|
|
1957 |
/* Free resources that were used during execution to emulate hardware */ |
/* Free resources that were used during execution to emulate hardware */ |
1958 |
c7200_free_hw_ressources(router); |
c7200_free_hw_ressources(VM_C7200(vm)); |
1959 |
vm_hardware_shutdown(vm); |
vm_hardware_shutdown(vm); |
1960 |
return(0); |
return(0); |
1961 |
} |
} |
1994 |
} |
} |
1995 |
|
|
1996 |
/* Add the new hardware elements */ |
/* Add the new hardware elements */ |
1997 |
if (c7200_pa_init(router,pa_bay) == -1) |
if (vm_slot_init(vm,pa_bay) == -1) |
1998 |
return(-1); |
return(-1); |
1999 |
|
|
2000 |
/* Resume normal operations */ |
/* Resume normal operations */ |
2009 |
int c7200_pa_stop_online(c7200_t *router,u_int pa_bay) |
int c7200_pa_stop_online(c7200_t *router,u_int pa_bay) |
2010 |
{ |
{ |
2011 |
vm_instance_t *vm = router->vm; |
vm_instance_t *vm = router->vm; |
|
struct c7200_pa_bay *bay; |
|
2012 |
|
|
2013 |
if (!pa_bay) { |
if (!pa_bay) { |
2014 |
vm_error(vm,"OIR not supported on slot 0.\n"); |
vm_error(vm,"OIR not supported on slot 0.\n"); |
2015 |
return(-1); |
return(-1); |
2016 |
} |
} |
2017 |
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
2018 |
/* The PA driver must be initialized */ |
/* The PA driver must be initialized */ |
2019 |
if (!bay->dev_type || !bay->pa_driver) { |
if (!vm_slot_get_card_ptr(vm,pa_bay)) { |
2020 |
vm_error(vm,"trying to shut down empty slot %u.\n",pa_bay); |
vm_error(vm,"trying to shut down empty slot %u.\n",pa_bay); |
2021 |
return(-1); |
return(-1); |
2022 |
} |
} |
2023 |
|
|
2024 |
/* Disable all NIOs to stop traffic forwarding */ |
/* Disable all NIOs to stop traffic forwarding */ |
2025 |
c7200_pa_disable_all_nio(router,pa_bay); |
vm_slot_disable_all_nio(vm,pa_bay); |
2026 |
|
|
2027 |
/* We can safely trigger the OIR event */ |
/* We can safely trigger the OIR event */ |
2028 |
c7200_trigger_oir_event(router,1 << pa_bay); |
c7200_trigger_oir_event(router,1 << pa_bay); |
2034 |
vm_suspend(vm); |
vm_suspend(vm); |
2035 |
|
|
2036 |
/* Device removal */ |
/* Device removal */ |
2037 |
c7200_pa_shutdown(router,pa_bay); |
vm_slot_shutdown(vm,pa_bay); |
2038 |
|
|
2039 |
/* Resume normal operations */ |
/* Resume normal operations */ |
2040 |
vm_resume(vm); |
vm_resume(vm); |
2041 |
return(0); |
return(0); |
2042 |
} |
} |
2043 |
|
|
2044 |
|
/* Get MAC address MSB */ |
2045 |
|
static u_int c7200_get_mac_addr_msb(void) |
2046 |
|
{ |
2047 |
|
return(0xCA); |
2048 |
|
} |
2049 |
|
|
2050 |
|
/* Parse specific options for the Cisco 7200 platform */ |
2051 |
|
static int c7200_cli_parse_options(vm_instance_t *vm,int option) |
2052 |
|
{ |
2053 |
|
c7200_t *router = VM_C7200(vm); |
2054 |
|
|
2055 |
|
switch(option) { |
2056 |
|
/* NPE type */ |
2057 |
|
case 't': |
2058 |
|
c7200_npe_set_type(router,optarg); |
2059 |
|
break; |
2060 |
|
|
2061 |
|
/* Midplane type */ |
2062 |
|
case 'M': |
2063 |
|
c7200_midplane_set_type(router,optarg); |
2064 |
|
break; |
2065 |
|
|
2066 |
|
/* Set the base MAC address */ |
2067 |
|
case 'm': |
2068 |
|
if (!c7200_midplane_set_mac_addr(router,optarg)) |
2069 |
|
printf("MAC address set to '%s'.\n",optarg); |
2070 |
|
break; |
2071 |
|
|
2072 |
|
/* Unknown option */ |
2073 |
|
default: |
2074 |
|
return(-1); |
2075 |
|
} |
2076 |
|
|
2077 |
|
return(0); |
2078 |
|
} |
2079 |
|
|
2080 |
|
/* Show specific CLI options */ |
2081 |
|
static void c7200_cli_show_options(vm_instance_t *vm) |
2082 |
|
{ |
2083 |
|
printf(" -t <npe_type> : Select NPE type (default: \"%s\")\n" |
2084 |
|
" -M <midplane> : Select Midplane (\"std\" or \"vxr\")\n" |
2085 |
|
" -p <pa_desc> : Define a Port Adapter\n" |
2086 |
|
" -s <pa_nio> : Bind a Network IO interface to a " |
2087 |
|
"Port Adapter\n", |
2088 |
|
C7200_DEFAULT_NPE_TYPE); |
2089 |
|
} |
2090 |
|
|
2091 |
|
/* Platform definition */ |
2092 |
|
static vm_platform_t c7200_platform = { |
2093 |
|
"c7200", "C7200", "7200", |
2094 |
|
c7200_create_instance, |
2095 |
|
c7200_delete_instance, |
2096 |
|
c7200_init_instance, |
2097 |
|
c7200_stop_instance, |
2098 |
|
c7200_nvram_extract_config, |
2099 |
|
c7200_nvram_push_config, |
2100 |
|
c7200_get_mac_addr_msb, |
2101 |
|
c7200_save_config, |
2102 |
|
c7200_cli_parse_options, |
2103 |
|
c7200_cli_show_options, |
2104 |
|
c7200_npe_show_drivers, |
2105 |
|
}; |
2106 |
|
|
2107 |
|
/* Register the c7200 platform */ |
2108 |
|
int c7200_platform_register(void) |
2109 |
|
{ |
2110 |
|
if (vm_platform_register(&c7200_platform) == -1) |
2111 |
|
return(-1); |
2112 |
|
|
2113 |
|
return(hypervisor_c7200_init(&c7200_platform)); |
2114 |
|
} |