15 |
#include <pthread.h> |
#include <pthread.h> |
16 |
|
|
17 |
#include "ptask.h" |
#include "ptask.h" |
18 |
#include "mips64.h" |
#include "cpu.h" |
19 |
|
#include "vm.h" |
20 |
#include "dynamips.h" |
#include "dynamips.h" |
21 |
#include "memory.h" |
#include "memory.h" |
22 |
#include "device.h" |
#include "device.h" |
40 |
#define EEPROM_NM_CLK 2 |
#define EEPROM_NM_CLK 2 |
41 |
#define EEPROM_NM_CS 4 |
#define EEPROM_NM_CS 4 |
42 |
|
|
43 |
|
#define C3600_NET_IRQ_CLEARING_DELAY 16 |
44 |
|
|
45 |
/* IO FPGA structure */ |
/* IO FPGA structure */ |
46 |
struct iofpga_data { |
struct iofpga_data { |
47 |
vm_obj_t vm_obj; |
vm_obj_t vm_obj; |
48 |
struct vdevice dev; |
struct vdevice dev; |
49 |
c3600_t *router; |
c3600_t *router; |
50 |
|
|
51 |
|
/* |
52 |
|
* Used to introduce a "delay" before clearing the network interrupt |
53 |
|
* on 3620/3640 platforms. Added due to a packet loss when using an |
54 |
|
* Ethernet NM on these platforms. |
55 |
|
* |
56 |
|
* Anyway, we should rely on the device information with appropriate IRQ |
57 |
|
* routing. |
58 |
|
*/ |
59 |
|
int net_irq_clearing_count; |
60 |
|
|
61 |
/* Slot select for EEPROM access */ |
/* Slot select for EEPROM access */ |
62 |
u_int eeprom_slot; |
u_int eeprom_slot; |
63 |
|
|
71 |
static const struct nmc93c46_eeprom_def eeprom_mb_def = { |
static const struct nmc93c46_eeprom_def eeprom_mb_def = { |
72 |
EEPROM_MB_CLK, EEPROM_MB_CS, |
EEPROM_MB_CLK, EEPROM_MB_CS, |
73 |
EEPROM_MB_DIN, EEPROM_MB_DOUT, |
EEPROM_MB_DIN, EEPROM_MB_DOUT, |
|
NULL, 0, |
|
74 |
}; |
}; |
75 |
|
|
76 |
/* Mainboard EEPROM */ |
/* Mainboard EEPROM */ |
77 |
static const struct nmc93c46_group eeprom_mb_group = { |
static const struct nmc93c46_group eeprom_mb_group = { |
78 |
1, 0, "Mainboard EEPROM", 0, { NULL }, { { 0, 0, 0, 0, 0} }, |
1, 0, "Mainboard EEPROM", 0, { &eeprom_mb_def }, |
79 |
}; |
}; |
80 |
|
|
81 |
/* NM EEPROM definition */ |
/* NM EEPROM definition */ |
82 |
static const struct nmc93c46_eeprom_def eeprom_nm_def = { |
static const struct nmc93c46_eeprom_def eeprom_nm_def = { |
83 |
EEPROM_NM_CLK, EEPROM_NM_CS, |
EEPROM_NM_CLK, EEPROM_NM_CS, |
84 |
EEPROM_NM_DIN, EEPROM_NM_DOUT, |
EEPROM_NM_DIN, EEPROM_NM_DOUT, |
|
NULL, 0, |
|
85 |
}; |
}; |
86 |
|
|
87 |
/* NM EEPROM */ |
/* NM EEPROM */ |
88 |
static const struct nmc93c46_group eeprom_nm_group = { |
static const struct nmc93c46_group eeprom_nm_group = { |
89 |
1, 0, "NM EEPROM", 0, { NULL }, { { 0, 0, 0, 0, 0} }, |
1, 0, "NM EEPROM", 0, { &eeprom_nm_def }, |
90 |
}; |
}; |
91 |
|
|
92 |
/* C3660 NM presence masks */ |
/* C3660 NM presence masks */ |
102 |
/* Select the current NM EEPROM */ |
/* Select the current NM EEPROM */ |
103 |
static void nm_eeprom_select(struct iofpga_data *d,u_int slot) |
static void nm_eeprom_select(struct iofpga_data *d,u_int slot) |
104 |
{ |
{ |
105 |
d->router->nm_eeprom.data = d->router->nm_bay[slot].eeprom_data; |
d->router->nm_eeprom_group.eeprom[0] = &d->router->nm_bay[slot].eeprom; |
|
d->router->nm_eeprom.data_len = d->router->nm_bay[slot].eeprom_data_len; |
|
106 |
} |
} |
107 |
|
|
108 |
/* Return the NM status register given the detected EEPROM (3620/3640) */ |
/* Return the NM status register given the detected EEPROM (3620/3640) */ |
151 |
* dev_c3620_c3640_iofpga_access() |
* dev_c3620_c3640_iofpga_access() |
152 |
*/ |
*/ |
153 |
static void * |
static void * |
154 |
dev_c3620_c3640_iofpga_access(cpu_mips_t *cpu,struct vdevice *dev, |
dev_c3620_c3640_iofpga_access(cpu_gen_t *cpu,struct vdevice *dev, |
155 |
m_uint32_t offset,u_int op_size,u_int op_type, |
m_uint32_t offset,u_int op_size,u_int op_type, |
156 |
m_uint64_t *data) |
m_uint64_t *data) |
157 |
{ |
{ |
165 |
if (offset != 0x0c) { |
if (offset != 0x0c) { |
166 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
167 |
cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n", |
cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n", |
168 |
offset,cpu->pc,op_size); |
offset,cpu_get_pc(cpu),op_size); |
169 |
} else { |
} else { |
170 |
cpu_log(cpu,"IO_FPGA", |
cpu_log(cpu,"IO_FPGA", |
171 |
"writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n", |
"writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n", |
172 |
offset,cpu->pc,*data,op_size); |
offset,cpu_get_pc(cpu),*data,op_size); |
173 |
} |
} |
174 |
} |
} |
175 |
#endif |
#endif |
242 |
case 0x20001: |
case 0x20001: |
243 |
case 0x20002: |
case 0x20002: |
244 |
case 0x20003: |
case 0x20003: |
245 |
/* XXX Thisn't seem to be correct (at least on 3620) */ |
/* XXX This doesn't seem to be correct (at least on 3620) */ |
246 |
slot = offset - 0x20000; |
slot = offset - 0x20000; |
247 |
|
|
248 |
if (op_type == MTS_READ) |
if (op_type == MTS_READ) |
249 |
*data = 0xFF; |
*data = 0xFF; |
250 |
|
|
251 |
vm_clear_irq(d->router->vm,C3600_NETIO_IRQ); |
if (++d->net_irq_clearing_count == C3600_NET_IRQ_CLEARING_DELAY) { |
252 |
|
vm_clear_irq(d->router->vm,C3600_NETIO_IRQ); |
253 |
|
d->net_irq_clearing_count = 0; |
254 |
|
} |
255 |
break; |
break; |
256 |
|
|
257 |
/* |
/* |
289 |
d->io_mask = *data; |
d->io_mask = *data; |
290 |
break; |
break; |
291 |
|
|
292 |
/* ??? */ |
/* |
293 |
/* 0: 3640, 4 << 5: 3620, 3 << 5: 3660 */ |
* Platform type ? |
294 |
|
* 0: 3640, 4 << 5: 3620, 3 << 5: 3660 |
295 |
|
*/ |
296 |
case 0x30000: |
case 0x30000: |
297 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
298 |
switch(c3600_chassis_get_id(d->router)) { |
switch(c3600_chassis_get_id(d->router)) { |
340 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
341 |
cpu_log(cpu,"IO_FPGA", |
cpu_log(cpu,"IO_FPGA", |
342 |
"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", |
"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", |
343 |
offset,cpu->pc,op_size); |
offset,cpu_get_pc(cpu),op_size); |
344 |
} else { |
} else { |
345 |
cpu_log(cpu,"IO_FPGA", |
cpu_log(cpu,"IO_FPGA", |
346 |
"write to unknown addr 0x%x, value=0x%llx, " |
"write to unknown addr 0x%x, value=0x%llx, " |
347 |
"pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size); |
"pc=0x%llx (size=%u)\n", |
348 |
|
offset,*data,cpu_get_pc(cpu),op_size); |
349 |
} |
} |
350 |
#endif |
#endif |
351 |
} |
} |
357 |
* dev_c3660_iofpga_access() |
* dev_c3660_iofpga_access() |
358 |
*/ |
*/ |
359 |
static void * |
static void * |
360 |
dev_c3660_iofpga_access(cpu_mips_t *cpu,struct vdevice *dev, |
dev_c3660_iofpga_access(cpu_gen_t *cpu,struct vdevice *dev, |
361 |
m_uint32_t offset,u_int op_size,u_int op_type, |
m_uint32_t offset,u_int op_size,u_int op_type, |
362 |
m_uint64_t *data) |
m_uint64_t *data) |
363 |
{ |
{ |
371 |
if (offset != 0x0c) { |
if (offset != 0x0c) { |
372 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
373 |
cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n", |
cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n", |
374 |
offset,cpu->pc,op_size); |
offset,cpu_get_pc(cpu),op_size); |
375 |
} else { |
} else { |
376 |
cpu_log(cpu,"IO_FPGA", |
cpu_log(cpu,"IO_FPGA", |
377 |
"writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n", |
"writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n", |
378 |
offset,cpu->pc,*data,op_size); |
offset,cpu_get_pc(cpu),*data,op_size); |
379 |
} |
} |
380 |
} |
} |
381 |
#endif |
#endif |
585 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
586 |
cpu_log(cpu,"IO_FPGA", |
cpu_log(cpu,"IO_FPGA", |
587 |
"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", |
"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", |
588 |
offset,cpu->pc,op_size); |
offset,cpu_get_pc(cpu),op_size); |
589 |
} else { |
} else { |
590 |
cpu_log(cpu,"IO_FPGA", |
cpu_log(cpu,"IO_FPGA", |
591 |
"write to unknown addr 0x%x, value=0x%llx, " |
"write to unknown addr 0x%x, value=0x%llx, " |
592 |
"pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size); |
"pc=0x%llx (size=%u)\n", |
593 |
|
offset,*data,cpu_get_pc(cpu),op_size); |
594 |
} |
} |
595 |
#endif |
#endif |
596 |
} |
} |
601 |
/* Initialize EEPROM groups */ |
/* Initialize EEPROM groups */ |
602 |
void c3600_init_eeprom_groups(c3600_t *router) |
void c3600_init_eeprom_groups(c3600_t *router) |
603 |
{ |
{ |
|
struct nmc93c46_group *g; |
|
604 |
int i; |
int i; |
605 |
|
|
606 |
/* Copy Mainboard EEPROM definition */ |
/* Initialize Mainboard EEPROM */ |
607 |
memcpy(&router->mb_eeprom,&eeprom_mb_def,sizeof(eeprom_mb_def)); |
router->mb_eeprom_group = eeprom_mb_group; |
608 |
|
router->mb_eeprom_group.eeprom[0] = &router->mb_eeprom; |
609 |
|
router->mb_eeprom.data = NULL; |
610 |
|
router->mb_eeprom.len = 0; |
611 |
|
|
612 |
|
/* Initialize NM EEPROM for 3620/3640 */ |
613 |
|
router->nm_eeprom_group = eeprom_nm_group; |
614 |
|
router->nm_eeprom_group.eeprom[0] = NULL; |
615 |
|
|
616 |
/* Initialize group */ |
/* Initialize NM EEPROM for 3660 */ |
|
g = &router->mb_eeprom_group; |
|
|
memcpy(g,&eeprom_mb_group,sizeof(eeprom_mb_group)); |
|
|
g->def[0] = &router->mb_eeprom; |
|
|
|
|
|
/* Copy NM EEPROM definition (3620/3640) */ |
|
|
memcpy(&router->nm_eeprom,&eeprom_nm_def,sizeof(eeprom_nm_def)); |
|
|
router->nm_eeprom.data = NULL; |
|
|
router->nm_eeprom.data_len = 0; |
|
|
|
|
|
/* Initialize group (3620/3640) */ |
|
|
g = &router->nm_eeprom_group; |
|
|
memcpy(g,&eeprom_nm_group,sizeof(eeprom_nm_group)); |
|
|
g->def[0] = &router->nm_eeprom; |
|
|
|
|
|
/* 3660 NM EEPROM */ |
|
617 |
for(i=0;i<C3600_MAX_NM_BAYS;i++) { |
for(i=0;i<C3600_MAX_NM_BAYS;i++) { |
618 |
memcpy(&router->c3660_nm_eeprom_def[i],&eeprom_nm_def, |
router->c3660_nm_eeprom_group[i] = eeprom_nm_group; |
619 |
sizeof(struct nmc93c46_eeprom_def)); |
router->c3660_nm_eeprom_group[i].eeprom[0] = &router->nm_bay[i].eeprom; |
|
|
|
|
memcpy(&router->c3660_nm_eeprom_group[i],&eeprom_nm_group, |
|
|
sizeof(struct nmc93c46_group)); |
|
|
|
|
|
router->c3660_nm_eeprom_group[i].def[0] = |
|
|
&router->c3660_nm_eeprom_def[i]; |
|
620 |
} |
} |
621 |
} |
} |
622 |
|
|