1 |
/* |
/* |
2 |
* Cisco C7200 (Predator) Simulation Platform. |
* Cisco router Simulation Platform. |
3 |
* Copyright (C) 2005-2006 Christophe Fillot. All rights reserved. |
* Copyright (c) 2005-2007 Christophe Fillot. All rights reserved. |
4 |
* |
* |
5 |
* EEPROM types: |
* EEPROM types: |
6 |
* - 0x95: PA-POS-OC3SMI |
* - 0x95: PA-POS-OC3SMI |
19 |
#include <pthread.h> |
#include <pthread.h> |
20 |
#include <assert.h> |
#include <assert.h> |
21 |
|
|
22 |
#include "mips64.h" |
#include "cpu.h" |
23 |
|
#include "vm.h" |
24 |
#include "dynamips.h" |
#include "dynamips.h" |
25 |
#include "memory.h" |
#include "memory.h" |
26 |
#include "device.h" |
#include "device.h" |
32 |
|
|
33 |
/* Debugging flags */ |
/* Debugging flags */ |
34 |
#define DEBUG_ACCESS 0 |
#define DEBUG_ACCESS 0 |
35 |
#define DEBUG_UNKNOWN 0 |
#define DEBUG_UNKNOWN 1 |
36 |
#define DEBUG_TRANSMIT 0 |
#define DEBUG_TRANSMIT 0 |
37 |
#define DEBUG_RECEIVE 0 |
#define DEBUG_RECEIVE 0 |
38 |
|
|
54 |
#define POS_OC3_TXDESC_WRAP 0x40000000 /* Wrap ring */ |
#define POS_OC3_TXDESC_WRAP 0x40000000 /* Wrap ring */ |
55 |
#define POS_OC3_TXDESC_CONT 0x08000000 /* Packet continues */ |
#define POS_OC3_TXDESC_CONT 0x08000000 /* Packet continues */ |
56 |
#define POS_OC3_TXDESC_LEN_MASK 0x1fff |
#define POS_OC3_TXDESC_LEN_MASK 0x1fff |
|
#define POS_OC3_TXDESC_ADDR_MASK 0x3fffffff /* Buffer address (?) */ |
|
57 |
|
|
58 |
/* RX Descriptor */ |
/* RX Descriptor */ |
59 |
struct rx_desc { |
struct rx_desc { |
100 |
/* |
/* |
101 |
* pos_access() |
* pos_access() |
102 |
*/ |
*/ |
103 |
static void *dev_pos_access(cpu_mips_t *cpu,struct vdevice *dev, |
static void *dev_pos_access(cpu_gen_t *cpu,struct vdevice *dev, |
104 |
m_uint32_t offset,u_int op_size,u_int op_type, |
m_uint32_t offset,u_int op_size,u_int op_type, |
105 |
m_uint64_t *data) |
m_uint64_t *data) |
106 |
{ |
{ |
107 |
struct pos_oc3_data *d = dev->priv_data; |
struct pos_oc3_data *d = dev->priv_data; |
108 |
|
|
112 |
#if DEBUG_ACCESS |
#if DEBUG_ACCESS |
113 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
114 |
cpu_log(cpu,d->name,"read access to offset = 0x%x, pc = 0x%llx\n", |
cpu_log(cpu,d->name,"read access to offset = 0x%x, pc = 0x%llx\n", |
115 |
offset,cpu->pc); |
offset,cpu_get_pc(cpu)); |
116 |
} else { |
} else { |
117 |
if (offset != 0x404) |
if (offset != 0x404) |
118 |
cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, " |
cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, " |
119 |
"val = 0x%llx\n",offset,cpu->pc,*data); |
"val = 0x%llx\n",offset,cpu_get_pc(cpu),*data); |
120 |
} |
} |
121 |
#endif |
#endif |
122 |
|
|
139 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
140 |
cpu_log(cpu,d->name, |
cpu_log(cpu,d->name, |
141 |
"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", |
"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", |
142 |
offset,cpu->pc,op_size); |
offset,cpu_get_pc(cpu),op_size); |
143 |
} else { |
} else { |
144 |
cpu_log(cpu,d->name, |
cpu_log(cpu,d->name, |
145 |
"write to unknown addr 0x%x, value=0x%llx, " |
"write to unknown addr 0x%x, value=0x%llx, " |
146 |
"pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size); |
"pc=0x%llx (size=%u)\n", |
147 |
|
offset,*data,cpu_get_pc(cpu),op_size); |
148 |
} |
} |
149 |
#endif |
#endif |
150 |
} |
} |
155 |
/* |
/* |
156 |
* pos_rx_access() |
* pos_rx_access() |
157 |
*/ |
*/ |
158 |
static void *dev_pos_rx_access(cpu_mips_t *cpu,struct vdevice *dev, |
static void *dev_pos_rx_access(cpu_gen_t *cpu,struct vdevice *dev, |
159 |
m_uint32_t offset,u_int op_size,u_int op_type, |
m_uint32_t offset,u_int op_size,u_int op_type, |
160 |
m_uint64_t *data) |
m_uint64_t *data) |
161 |
{ |
{ |
167 |
#if DEBUG_ACCESS |
#if DEBUG_ACCESS |
168 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
169 |
cpu_log(cpu,d->name,"read access to offset = 0x%x, pc = 0x%llx\n", |
cpu_log(cpu,d->name,"read access to offset = 0x%x, pc = 0x%llx\n", |
170 |
offset,cpu->pc); |
offset,cpu_get_pc(cpu)); |
171 |
} else { |
} else { |
172 |
cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, " |
cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, " |
173 |
"val = 0x%llx\n",offset,cpu->pc,*data); |
"val = 0x%llx\n",offset,cpu_get_pc(cpu),*data); |
174 |
} |
} |
175 |
#endif |
#endif |
176 |
|
|
194 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
195 |
cpu_log(cpu,d->rx_name, |
cpu_log(cpu,d->rx_name, |
196 |
"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", |
"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", |
197 |
offset,cpu->pc,op_size); |
offset,cpu_get_pc(cpu),op_size); |
198 |
} else { |
} else { |
199 |
cpu_log(cpu,d->rx_name, |
cpu_log(cpu,d->rx_name, |
200 |
"write to unknown addr 0x%x, value=0x%llx, " |
"write to unknown addr 0x%x, value=0x%llx, " |
201 |
"pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size); |
"pc=0x%llx (size=%u)\n", |
202 |
|
offset,*data,cpu_get_pc(cpu),op_size); |
203 |
} |
} |
204 |
#endif |
#endif |
205 |
} |
} |
210 |
/* |
/* |
211 |
* pos_tx_access() |
* pos_tx_access() |
212 |
*/ |
*/ |
213 |
static void *dev_pos_tx_access(cpu_mips_t *cpu,struct vdevice *dev, |
static void *dev_pos_tx_access(cpu_gen_t *cpu,struct vdevice *dev, |
214 |
m_uint32_t offset,u_int op_size,u_int op_type, |
m_uint32_t offset,u_int op_size,u_int op_type, |
215 |
m_uint64_t *data) |
m_uint64_t *data) |
216 |
{ |
{ |
222 |
#if DEBUG_ACCESS |
#if DEBUG_ACCESS |
223 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
224 |
cpu_log(cpu,d->tx_name,"read access to offset = 0x%x, pc = 0x%llx\n", |
cpu_log(cpu,d->tx_name,"read access to offset = 0x%x, pc = 0x%llx\n", |
225 |
offset,cpu->pc); |
offset,cpu_get_pc(cpu)); |
226 |
} else { |
} else { |
227 |
cpu_log(cpu,d->tx_name,"write access to vaddr = 0x%x, pc = 0x%llx, " |
cpu_log(cpu,d->tx_name,"write access to vaddr = 0x%x, pc = 0x%llx, " |
228 |
"val = 0x%llx\n",offset,cpu->pc,*data); |
"val = 0x%llx\n",offset,cpu_get_pc(cpu),*data); |
229 |
} |
} |
230 |
#endif |
#endif |
231 |
|
|
249 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
250 |
cpu_log(cpu,d->tx_name, |
cpu_log(cpu,d->tx_name, |
251 |
"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", |
"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", |
252 |
offset,cpu->pc,op_size); |
offset,cpu_get_pc(cpu),op_size); |
253 |
} else { |
} else { |
254 |
cpu_log(cpu,d->tx_name, |
cpu_log(cpu,d->tx_name, |
255 |
"write to unknown addr 0x%x, value=0x%llx, " |
"write to unknown addr 0x%x, value=0x%llx, " |
256 |
"pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size); |
"pc=0x%llx (size=%u)\n", |
257 |
|
offset,*data,cpu_get_pc(cpu),op_size); |
258 |
} |
} |
259 |
#endif |
#endif |
260 |
} |
} |
265 |
/* |
/* |
266 |
* pos_cs_access() |
* pos_cs_access() |
267 |
*/ |
*/ |
268 |
static void *dev_pos_cs_access(cpu_mips_t *cpu,struct vdevice *dev, |
static void *dev_pos_cs_access(cpu_gen_t *cpu,struct vdevice *dev, |
269 |
m_uint32_t offset,u_int op_size,u_int op_type, |
m_uint32_t offset,u_int op_size,u_int op_type, |
270 |
m_uint64_t *data) |
m_uint64_t *data) |
271 |
{ |
{ |
277 |
#if DEBUG_ACCESS |
#if DEBUG_ACCESS |
278 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
279 |
cpu_log(cpu,d->cs_name,"read access to offset = 0x%x, pc = 0x%llx\n", |
cpu_log(cpu,d->cs_name,"read access to offset = 0x%x, pc = 0x%llx\n", |
280 |
offset,cpu->pc); |
offset,cpu_get_pc(cpu)); |
281 |
} else { |
} else { |
282 |
cpu_log(cpu,d->cs_name,"write access to vaddr = 0x%x, pc = 0x%llx, " |
cpu_log(cpu,d->cs_name,"write access to vaddr = 0x%x, pc = 0x%llx, " |
283 |
"val = 0x%llx\n",offset,cpu->pc,*data); |
"val = 0x%llx\n",offset,cpu_get_pc(cpu),*data); |
284 |
} |
} |
285 |
#endif |
#endif |
286 |
|
|
302 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
303 |
cpu_log(cpu,d->cs_name, |
cpu_log(cpu,d->cs_name, |
304 |
"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", |
"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", |
305 |
offset,cpu->pc,op_size); |
offset,cpu_get_pc(cpu),op_size); |
306 |
} else { |
} else { |
307 |
cpu_log(cpu,d->cs_name, |
cpu_log(cpu,d->cs_name, |
308 |
"write to unknown addr 0x%x, value=0x%llx, " |
"write to unknown addr 0x%x, value=0x%llx, " |
309 |
"pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size); |
"pc=0x%llx (size=%u)\n", |
310 |
|
offset,*data,cpu_get_pc(cpu),op_size); |
311 |
} |
} |
312 |
#endif |
#endif |
313 |
} |
} |
500 |
static int dev_pos_oc3_handle_txring(struct pos_oc3_data *d) |
static int dev_pos_oc3_handle_txring(struct pos_oc3_data *d) |
501 |
{ |
{ |
502 |
u_char pkt[POS_OC3_MAX_PKT_SIZE],*pkt_ptr; |
u_char pkt[POS_OC3_MAX_PKT_SIZE],*pkt_ptr; |
503 |
m_uint32_t tx_start,clen,tot_len,addr; |
m_uint32_t clen,tot_len,norm_len; |
504 |
|
m_uint32_t tx_start,addr; |
505 |
struct tx_desc txd0,ctxd,*ptxd; |
struct tx_desc txd0,ctxd,*ptxd; |
506 |
int i,done = FALSE; |
int i,done = FALSE; |
507 |
|
|
543 |
if (clen != 0) { |
if (clen != 0) { |
544 |
addr = ptxd->tdes[1]; |
addr = ptxd->tdes[1]; |
545 |
|
|
546 |
/* ugly hack, to allow this to work with SRAM platforms */ |
norm_len = normalize_size(clen,4,0); |
|
if ((addr & ~POS_OC3_TXDESC_ADDR_MASK) == 0xc0000000) |
|
|
addr = ptxd->tdes[1] & POS_OC3_TXDESC_ADDR_MASK; |
|
|
|
|
547 |
physmem_copy_from_vm(d->vm,pkt_ptr,addr,clen); |
physmem_copy_from_vm(d->vm,pkt_ptr,addr,clen); |
548 |
|
mem_bswap32(pkt_ptr,norm_len); |
549 |
} |
} |
550 |
|
|
551 |
pkt_ptr += clen; |
pkt_ptr += clen; |
589 |
/* |
/* |
590 |
* pci_pos_read() |
* pci_pos_read() |
591 |
*/ |
*/ |
592 |
static m_uint32_t pci_pos_read(cpu_mips_t *cpu,struct pci_device *dev,int reg) |
static m_uint32_t pci_pos_read(cpu_gen_t *cpu,struct pci_device *dev,int reg) |
593 |
{ |
{ |
594 |
struct pos_oc3_data *d = dev->priv_data; |
struct pos_oc3_data *d = dev->priv_data; |
595 |
|
|
608 |
/* |
/* |
609 |
* pci_pos_write() |
* pci_pos_write() |
610 |
*/ |
*/ |
611 |
static void pci_pos_write(cpu_mips_t *cpu,struct pci_device *dev, |
static void pci_pos_write(cpu_gen_t *cpu,struct pci_device *dev, |
612 |
int reg,m_uint32_t value) |
int reg,m_uint32_t value) |
613 |
{ |
{ |
614 |
struct pos_oc3_data *d = dev->priv_data; |
struct pos_oc3_data *d = dev->priv_data; |