/[dynamips]/trunk/dev_c2600_iofpga.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/dev_c2600_iofpga.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Sat Oct 6 16:45:40 2007 UTC (12 years ago) by dpavlin
File MIME type: text/plain
File size: 8769 byte(s)
make working copy

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <termios.h>
12 #include <fcntl.h>
13 #include <pthread.h>
14
15 #include "ptask.h"
16 #include "cpu.h"
17 #include "vm.h"
18 #include "dynamips.h"
19 #include "memory.h"
20 #include "device.h"
21 #include "dev_vtty.h"
22 #include "nmc93cX6.h"
23 #include "dev_mpc860.h"
24 #include "dev_c2600.h"
25
26 /* Debugging flags */
27 #define DEBUG_UNKNOWN 1
28 #define DEBUG_ACCESS 0
29 #define DEBUG_NET_IRQ 0
30
31 /* Definitions for Mainboard EEPROM */
32 #define EEPROM_MB_DOUT 3
33 #define EEPROM_MB_DIN 2
34 #define EEPROM_MB_CLK 1
35 #define EEPROM_MB_CS 0
36
37 /* Definitions for Network Modules EEPROM */
38 #define EEPROM_NM_DOUT 7
39 #define EEPROM_NM_DIN 6
40 #define EEPROM_NM_CLK 2
41 #define EEPROM_NM_CS 4
42
43 #define C2691_NET_IRQ_CLEARING_DELAY 16
44
45 /* Network IRQ distribution */
46 static u_int net_irq_dist[C2600_MAX_NM_BAYS] = {
47 4, /* reg 0x08, bits 4-5 */
48 0, /* reg 0x08, bits 0-3 */
49 };
50
51 /* IO FPGA structure */
52 struct c2600_iofpga_data {
53 vm_obj_t vm_obj;
54 struct vdevice dev;
55 c2600_t *router;
56
57 /* Network Interrupt status */
58 m_uint8_t net_irq_status;
59
60 /* Interrupt mask */
61 m_uint16_t intr_mask;
62
63 /* WIC SPI selection */
64 m_uint8_t wic_select;
65 };
66
67 /* Mainboard EEPROM definition */
68 static const struct nmc93cX6_eeprom_def eeprom_mb_def = {
69 EEPROM_MB_CLK, EEPROM_MB_CS,
70 EEPROM_MB_DIN, EEPROM_MB_DOUT,
71 };
72
73 /* Mainboard EEPROM */
74 static const struct nmc93cX6_group eeprom_mb_group = {
75 EEPROM_TYPE_NMC93C46, 1, 0,
76 EEPROM_DORD_NORMAL,
77 EEPROM_DOUT_HIGH,
78 EEPROM_DEBUG_DISABLED,
79 "Mainboard EEPROM",
80 { &eeprom_mb_def },
81 };
82
83 /* NM EEPROM definition */
84 static const struct nmc93cX6_eeprom_def eeprom_nm_def = {
85 EEPROM_NM_CLK, EEPROM_NM_CS,
86 EEPROM_NM_DIN, EEPROM_NM_DOUT,
87 };
88
89 /* NM EEPROM */
90 static const struct nmc93cX6_group eeprom_nm_group = {
91 EEPROM_TYPE_NMC93C46, 1, 0,
92 EEPROM_DORD_NORMAL,
93 EEPROM_DOUT_HIGH,
94 EEPROM_DEBUG_DISABLED,
95 "NM EEPROM",
96 { &eeprom_nm_def },
97 };
98
99 /* Update network interrupt status */
100 static inline void dev_c2600_iofpga_net_update_irq(struct c2600_iofpga_data *d)
101 {
102 if (d->net_irq_status) {
103 vm_set_irq(d->router->vm,C2600_NETIO_IRQ);
104 } else {
105 vm_clear_irq(d->router->vm,C2600_NETIO_IRQ);
106 }
107 }
108
109 /* Trigger a Network IRQ for the specified slot/port */
110 void dev_c2600_iofpga_net_set_irq(struct c2600_iofpga_data *d,
111 u_int slot,u_int port)
112 {
113 #if DEBUG_NET_IRQ
114 vm_log(d->router->vm,"IO_FPGA","setting NetIRQ for slot %u port %u\n",
115 slot,port);
116 #endif
117 d->net_irq_status |= 1 << (net_irq_dist[slot] + port);
118 dev_c2600_iofpga_net_update_irq(d);
119 }
120
121 /* Clear a Network IRQ for the specified slot/port */
122 void dev_c2600_iofpga_net_clear_irq(struct c2600_iofpga_data *d,
123 u_int slot,u_int port)
124 {
125 #if DEBUG_NET_IRQ
126 vm_log(d->router->vm,"IO_FPGA","clearing NetIRQ for slot %u port %u\n",
127 slot,port);
128 #endif
129 d->net_irq_status &= ~(1 << (net_irq_dist[slot] + port));
130 dev_c2600_iofpga_net_update_irq(d);
131 }
132
133 /* Callback for MPC860 SPI Transmit */
134 static void dev_c2600_mpc860_spi_tx_callback(struct mpc860_data *mpc_data,
135 u_char *buffer,u_int len,
136 void *user_arg)
137 {
138 struct c2600_iofpga_data *d = user_arg;
139 struct cisco_eeprom *eeprom;
140 u_char reply_buf[4];
141 u_int wic_port;
142 u_int eeprom_offset;
143
144 if (d->wic_select & 0x20)
145 wic_port = 0x10;
146 else if (d->wic_select & 0x08)
147 wic_port = 0x20;
148 else {
149 vm_error(d->router->vm,"unknown value for wic_select (0x%8.8x)\n",
150 d->wic_select);
151 wic_port = 0;
152 }
153
154 /* No WIC in slot or no EEPROM: fake an empty EEPROM */
155 if (!wic_port || !(eeprom = vm_slot_get_eeprom(d->router->vm,0,wic_port))) {
156 memset(reply_buf,0xFF,sizeof(reply_buf));
157 mpc860_spi_receive(mpc_data,reply_buf,sizeof(reply_buf));
158 return;
159 }
160
161 /* Read request: 0x03 offset 0x00 0x00 */
162 eeprom_offset = buffer[1];
163
164 reply_buf[0] = 0;
165 reply_buf[1] = 0;
166 cisco_eeprom_get_byte(eeprom,eeprom_offset,&reply_buf[2]);
167 cisco_eeprom_get_byte(eeprom,eeprom_offset+1,&reply_buf[3]);
168
169 mpc860_spi_receive(mpc_data,reply_buf,sizeof(reply_buf));
170 }
171
172 /*
173 * dev_c2600_iofpga_access()
174 */
175 static void *
176 dev_c2600_iofpga_access(cpu_gen_t *cpu,struct vdevice *dev,
177 m_uint32_t offset,u_int op_size,u_int op_type,
178 m_uint64_t *data)
179 {
180 struct c2600_iofpga_data *d = dev->priv_data;
181
182 if (op_type == MTS_READ)
183 *data = 0x0;
184
185 #if DEBUG_ACCESS
186 if (op_type == MTS_READ) {
187 cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",
188 offset,cpu_get_pc(cpu),op_size);
189 } else {
190 cpu_log(cpu,"IO_FPGA",
191 "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",
192 offset,cpu_get_pc(cpu),*data,op_size);
193 }
194 #endif
195
196 switch(offset) {
197 case 0x04:
198 if (op_type == MTS_READ)
199 *data = 0x00;
200 break;
201
202 /*
203 * Network Interrupt.
204 *
205 * Bit 0-3: slot 1.
206 * Bit 4: slot 0 (MB), port 0
207 * Bit 5: slot 0 (MB), port 1
208 * Other: AIM ? (error messages displayed)
209 */
210 case 0x08:
211 if (op_type == MTS_READ)
212 *data = d->net_irq_status;
213 break;
214
215 case 0x10:
216 if (op_type == MTS_READ)
217 *data = d->wic_select;
218 else {
219 d->wic_select = *data;
220 }
221 break;
222
223 case 0x14:
224 if (op_type == MTS_READ)
225 *data = 0; //0xFFFFFFFF;
226 break;
227
228 /*
229 * Flash Related: 0x1y
230 *
231 * Bit 1: card present in slot 0 / WIC 0.
232 * Bit 2: card present in slot 0 / WIC 1.
233 *
234 * Other bits unknown.
235 */
236 case 0x0c:
237 if (op_type == MTS_READ) {
238 *data = 0x10;
239
240 /* check WIC 0 */
241 if (vm_slot_check_eeprom(d->router->vm,0,0x10))
242 *data |= 0x02;
243
244 /* check WIC 1 */
245 if (vm_slot_check_eeprom(d->router->vm,0,0x20))
246 *data |= 0x04;
247 }
248 break;
249
250 /* NM EEPROM */
251 case 0x1c:
252 if (op_type == MTS_WRITE)
253 nmc93cX6_write(&d->router->nm_eeprom_group,(u_int)(*data));
254 else
255 *data = nmc93cX6_read(&d->router->nm_eeprom_group);
256 break;
257
258 #if DEBUG_UNKNOWN
259 default:
260 if (op_type == MTS_READ) {
261 cpu_log(cpu,"IO_FPGA",
262 "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
263 offset,cpu_get_pc(cpu),op_size);
264 } else {
265 cpu_log(cpu,"IO_FPGA",
266 "write to unknown addr 0x%x, value=0x%llx, "
267 "pc=0x%llx (size=%u)\n",
268 offset,*data,cpu_get_pc(cpu),op_size);
269 }
270 #endif
271 }
272
273 return NULL;
274 }
275
276 /* Shutdown the IO FPGA device */
277 static void
278 dev_c2600_iofpga_shutdown(vm_instance_t *vm,struct c2600_iofpga_data *d)
279 {
280 if (d != NULL) {
281 /* Remove the device */
282 dev_remove(vm,&d->dev);
283
284 /* Free the structure itself */
285 free(d);
286 }
287 }
288
289 /*
290 * dev_c2600_iofpga_init()
291 */
292 int dev_c2600_iofpga_init(c2600_t *router,m_uint64_t paddr,m_uint32_t len)
293 {
294 vm_instance_t *vm = router->vm;
295 struct c2600_iofpga_data *d;
296
297 /* Allocate private data structure */
298 if (!(d = malloc(sizeof(*d)))) {
299 fprintf(stderr,"IO_FPGA: out of memory\n");
300 return(-1);
301 }
302
303 memset(d,0,sizeof(*d));
304 d->router = router;
305
306 vm_object_init(&d->vm_obj);
307 d->vm_obj.name = "io_fpga";
308 d->vm_obj.data = d;
309 d->vm_obj.shutdown = (vm_shutdown_t)dev_c2600_iofpga_shutdown;
310
311 /* Set device properties */
312 dev_init(&d->dev);
313 d->dev.name = "io_fpga";
314 d->dev.phys_addr = paddr;
315 d->dev.phys_len = len;
316 d->dev.priv_data = d;
317 d->dev.handler = dev_c2600_iofpga_access;
318
319 /* Initialize the MPC860 SPI TX callback to read mainboard WIC EEPROMs */
320 mpc860_spi_set_tx_callback(router->mpc_data,
321 dev_c2600_mpc860_spi_tx_callback,d);
322
323 /* Map this device to the VM */
324 vm_bind_device(router->vm,&d->dev);
325 vm_object_add(vm,&d->vm_obj);
326 return(0);
327 }
328
329 /* Initialize EEPROM groups */
330 void c2600_init_eeprom_groups(c2600_t *router)
331 {
332 /* Initialize Mainboard EEPROM */
333 router->mb_eeprom_group = eeprom_mb_group;
334 router->mb_eeprom_group.eeprom[0] = &router->mb_eeprom;
335 router->mb_eeprom.data = NULL;
336 router->mb_eeprom.len = 0;
337
338 /* EEPROM for NM slot 1 */
339 router->nm_eeprom_group = eeprom_nm_group;
340 }

  ViewVC Help
Powered by ViewVC 1.1.26