/[dynamips]/upstream/dynamips-0.2.7-RC1/dev_c7200_mpfpga.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 /upstream/dynamips-0.2.7-RC1/dev_c7200_mpfpga.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (show annotations)
Sat Oct 6 16:23:47 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 11376 byte(s)
dynamips-0.2.7-RC1

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * Cisco c7200 Midplane FPGA.
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "cpu.h"
13 #include "vm.h"
14 #include "dynamips.h"
15 #include "memory.h"
16 #include "device.h"
17 #include "nmc93c46.h"
18 #include "dev_c7200.h"
19
20 #define DEBUG_UNKNOWN 1
21 #define DEBUG_ACCESS 0
22 #define DEBUG_OIR 1
23
24 /*
25 * Definitions for Port Adapter Status.
26 */
27 #define PCI_BAY0_3V_OK 0x00000002 /* IO card 3V */
28 #define PCI_BAY0_5V_OK 0x00000004 /* IO card 5V */
29
30 #define PCI_BAY1_5V_OK 0x00000200 /* Bay 1 5V */
31 #define PCI_BAY1_3V_OK 0x00000400 /* Bay 1 3V */
32
33 #define PCI_BAY2_5V_OK 0x00002000 /* Bay 2 5V */
34 #define PCI_BAY2_3V_OK 0x00004000 /* Bay 2 3V */
35
36 #define PCI_BAY3_5V_OK 0x02000000 /* Bay 3 5V */
37 #define PCI_BAY3_3V_OK 0x04000000 /* Bay 3 3V */
38
39 #define PCI_BAY4_5V_OK 0x00020000 /* Bay 4 5V */
40 #define PCI_BAY4_3V_OK 0x00040000 /* Bay 4 3V */
41
42 #define PCI_BAY5_5V_OK 0x20000000 /* Bay 5 5V */
43 #define PCI_BAY5_3V_OK 0x40000000 /* Bay 5 3V */
44
45 #define PCI_BAY6_5V_OK 0x00200000 /* Bay 6 5V */
46 #define PCI_BAY6_3V_OK 0x00400000 /* Bay 6 3V */
47
48 /*
49 * Definitions for EEPROM access (slots 0,1,3,4) (0x60)
50 */
51 #define BAY0_EEPROM_SELECT_BIT 1
52 #define BAY0_EEPROM_CLOCK_BIT 3
53 #define BAY0_EEPROM_DIN_BIT 4
54 #define BAY0_EEPROM_DOUT_BIT 6
55
56 #define BAY1_EEPROM_SELECT_BIT 9
57 #define BAY1_EEPROM_CLOCK_BIT 11
58 #define BAY1_EEPROM_DIN_BIT 12
59 #define BAY1_EEPROM_DOUT_BIT 14
60
61 #define BAY3_EEPROM_SELECT_BIT 25
62 #define BAY3_EEPROM_CLOCK_BIT 27
63 #define BAY3_EEPROM_DIN_BIT 28
64 #define BAY3_EEPROM_DOUT_BIT 30
65
66 #define BAY4_EEPROM_SELECT_BIT 17
67 #define BAY4_EEPROM_CLOCK_BIT 19
68 #define BAY4_EEPROM_DIN_BIT 20
69 #define BAY4_EEPROM_DOUT_BIT 22
70
71 /*
72 * Definitions for EEPROM access (slots 2,5,6) (0x68)
73 */
74 #define BAY2_EEPROM_SELECT_BIT 9
75 #define BAY2_EEPROM_CLOCK_BIT 11
76 #define BAY2_EEPROM_DIN_BIT 12
77 #define BAY2_EEPROM_DOUT_BIT 14
78
79 #define BAY5_EEPROM_SELECT_BIT 25
80 #define BAY5_EEPROM_CLOCK_BIT 27
81 #define BAY5_EEPROM_DIN_BIT 28
82 #define BAY5_EEPROM_DOUT_BIT 30
83
84 #define BAY6_EEPROM_SELECT_BIT 17
85 #define BAY6_EEPROM_CLOCK_BIT 19
86 #define BAY6_EEPROM_DIN_BIT 20
87 #define BAY6_EEPROM_DOUT_BIT 22
88
89 /* PA Bay EEPROM definitions */
90 static const struct nmc93c46_eeprom_def eeprom_bay_def[C7200_MAX_PA_BAYS] = {
91 /* Bay 0 */
92 { BAY0_EEPROM_CLOCK_BIT , BAY0_EEPROM_SELECT_BIT,
93 BAY0_EEPROM_DIN_BIT , BAY0_EEPROM_DOUT_BIT,
94 },
95
96 /* Bay 1 */
97 { BAY1_EEPROM_CLOCK_BIT , BAY1_EEPROM_SELECT_BIT,
98 BAY1_EEPROM_DIN_BIT , BAY1_EEPROM_DOUT_BIT,
99 },
100
101 /* Bay 2 */
102 { BAY2_EEPROM_CLOCK_BIT , BAY2_EEPROM_SELECT_BIT,
103 BAY2_EEPROM_DIN_BIT , BAY2_EEPROM_DOUT_BIT,
104 },
105
106 /* Bay 3 */
107 { BAY3_EEPROM_CLOCK_BIT , BAY3_EEPROM_SELECT_BIT,
108 BAY3_EEPROM_DIN_BIT , BAY3_EEPROM_DOUT_BIT,
109 },
110
111 /* Bay 4 */
112 { BAY4_EEPROM_CLOCK_BIT , BAY4_EEPROM_SELECT_BIT,
113 BAY4_EEPROM_DIN_BIT , BAY4_EEPROM_DOUT_BIT,
114 },
115
116 /* Bay 5 */
117 { BAY5_EEPROM_CLOCK_BIT , BAY5_EEPROM_SELECT_BIT,
118 BAY5_EEPROM_DIN_BIT , BAY5_EEPROM_DOUT_BIT,
119 },
120
121 /* Bay 6 */
122 { BAY6_EEPROM_CLOCK_BIT , BAY6_EEPROM_SELECT_BIT,
123 BAY6_EEPROM_DIN_BIT , BAY6_EEPROM_DOUT_BIT,
124 },
125 };
126
127 /* EEPROM group #1 (Bays 0, 1, 3, 4) */
128 static const struct nmc93c46_group eeprom_bays_g1 = {
129 4, 0, "PA Bays (Group #1) EEPROM", FALSE,
130
131 { &eeprom_bay_def[0], &eeprom_bay_def[1],
132 &eeprom_bay_def[3], &eeprom_bay_def[4],
133 },
134 };
135
136 /* EEPROM group #2 (Bays 2, 5, 6) */
137 static const struct nmc93c46_group eeprom_bays_g2 = {
138 3, 0, "PA Bays (Group #2) EEPROM", FALSE,
139
140 { &eeprom_bay_def[2], &eeprom_bay_def[5], &eeprom_bay_def[6] },
141 };
142
143 /* Midplane FPGA private data */
144 struct mpfpga_data {
145 vm_obj_t vm_obj;
146 struct vdevice dev;
147
148 c7200_t *router;
149 m_uint32_t pa_status_reg;
150 m_uint32_t pa_ctrl_reg;
151 };
152
153 /* Update Port Adapter Status */
154 static void pa_update_status_reg(struct mpfpga_data *d)
155 {
156 m_uint32_t res = 0;
157
158 /* PA Power. Bay 0 is always powered */
159 res |= PCI_BAY0_5V_OK | PCI_BAY0_3V_OK;
160
161 /* We fake power on bays defined by the final user */
162 if (c7200_pa_check_eeprom(d->router,1))
163 res |= PCI_BAY1_5V_OK | PCI_BAY1_3V_OK;
164
165 if (c7200_pa_check_eeprom(d->router,2))
166 res |= PCI_BAY2_5V_OK | PCI_BAY2_3V_OK;
167
168 if (c7200_pa_check_eeprom(d->router,3))
169 res |= PCI_BAY3_5V_OK | PCI_BAY3_3V_OK;
170
171 if (c7200_pa_check_eeprom(d->router,4))
172 res |= PCI_BAY4_5V_OK | PCI_BAY4_3V_OK;
173
174 if (c7200_pa_check_eeprom(d->router,5))
175 res |= PCI_BAY5_5V_OK | PCI_BAY5_3V_OK;
176
177 if (c7200_pa_check_eeprom(d->router,6))
178 res |= PCI_BAY6_5V_OK | PCI_BAY6_3V_OK;
179
180 d->pa_status_reg = res;
181 }
182
183 /*
184 * dev_mpfpga_access()
185 */
186 void *dev_c7200_mpfpga_access(cpu_gen_t *cpu,struct vdevice *dev,
187 m_uint32_t offset,u_int op_size,u_int op_type,
188 m_uint64_t *data)
189 {
190 struct mpfpga_data *d = dev->priv_data;
191
192 if (op_type == MTS_READ)
193 *data = 0x0;
194
195 /* Optimization: this is written regularly */
196 if (offset == 0x7b)
197 return NULL;
198
199 #if DEBUG_ACCESS
200 if (op_type == MTS_READ) {
201 cpu_log(cpu,"MP_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",
202 offset,cpu_get_pc(cpu),op_size);
203 } else {
204 cpu_log(cpu,"MP_FPGA",
205 "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",
206 offset,cpu_get_pc(cpu),*data,op_size);
207 }
208 #endif
209
210 switch(offset) {
211 case 0x10: /* interrupt mask, should be done more efficiently */
212 case 0x11:
213 case 0x12:
214 case 0x13:
215 if (op_type == MTS_READ) {
216 *data = 0xFFFFFFFF;
217 vm_clear_irq(d->router->vm,C7200_NETIO_IRQ);
218 }
219 break;
220
221 case 0x18: /* interrupt mask, should be done more efficiently */
222 case 0x19:
223 case 0x1a:
224 if (op_type == MTS_READ) {
225 *data = 0xFFFFFFFF;
226 vm_clear_irq(d->router->vm,C7200_NETIO_IRQ);
227 }
228 break;
229
230 /*
231 * - PCI errors (seen with IRQ 6)
232 * - Used when PA Mgmt IRQ is triggered.
233 *
234 * If the PA Mgmt IRQ is triggered for an undefined slot, a crash
235 * occurs with "Error: Unexpected NM Interrupt received from slot: 6"
236 * So, we use the PA status reg as mask to return something safe
237 * (slot order is identical).
238 */
239 case 0x40:
240 if (op_type == MTS_READ)
241 *data = 0x66666600 & d->pa_status_reg;
242
243 vm_clear_irq(d->router->vm,C7200_PA_MGMT_IRQ);
244 break;
245
246 case 0x48: /* ??? (test) */
247 if (op_type == MTS_READ)
248 *data = 0xFFFFFFFF;
249 break;
250
251 /*
252 * This corresponds to err_stat in error message when IRQ 6 is
253 * triggered.
254 *
255 * Bit 7 => SRAM error.
256 * Bits 1-6 => OIR on slot 1-6
257 */
258 case 0x70:
259 if (op_type == MTS_READ) {
260 #if DEBUG_OIR
261 cpu_log(cpu,"MP_FPGA","reading reg 0x%x at pc=0x%llx, val=0x%x\n",
262 offset,cpu_get_pc(cpu),d->router->oir_status);
263 #endif
264 *data = d->router->oir_status;
265 vm_clear_irq(d->router->vm,C7200_OIR_IRQ);
266 } else {
267 #if DEBUG_OIR
268 cpu_log(cpu,"MP_FPGA","writing reg 0x%x at pc=0x%llx "
269 "(data=0x%llx)\n",offset,cpu_get_pc(cpu),*data);
270 #endif
271 d->router->oir_status &= ~(*data);
272 vm_clear_irq(d->router->vm,C7200_OIR_IRQ);
273 }
274 break;
275
276 /*
277 * This corresponds to err_enable in error message when IRQ 6 is
278 * triggered. No idea of what it really means.
279 */
280 case 0x78:
281 if (op_type == MTS_READ) {
282 #if DEBUG_OIR
283 cpu_log(cpu,"MP_FPGA","reading 0x78 at pc=0x%llx\n",
284 cpu_get_pc(cpu));
285 #endif
286 *data = 0x00;
287 } else {
288 #if DEBUG_OIR
289 cpu_log(cpu,"MP_FPGA","writing reg 0x78 at pc=0x%llx "
290 "(data=0x%llx)\n",cpu_get_pc(cpu),*data);
291 #endif
292 }
293 break;
294
295 case 0x38: /* TDM status */
296 break;
297
298 case 0x50: /* Port Adapter Status */
299 if (op_type == MTS_READ) {
300 pa_update_status_reg(d);
301 *data = d->pa_status_reg;
302 }
303 break;
304
305 case 0x58: /* Port Adapter Control */
306 if (op_type == MTS_WRITE)
307 d->pa_ctrl_reg = *data;
308 else
309 *data = d->pa_ctrl_reg;
310 break;
311
312 case 0x60: /* EEPROM for PA in slots 0,1,3,4 */
313 if (op_type == MTS_WRITE)
314 nmc93c46_write(&d->router->pa_eeprom_g1,*data);
315 else
316 *data = nmc93c46_read(&d->router->pa_eeprom_g1);
317 break;
318
319 case 0x68: /* EEPROM for PA in slots 2,5,6 */
320 if (op_type == MTS_WRITE)
321 nmc93c46_write(&d->router->pa_eeprom_g2,*data);
322 else
323 *data = nmc93c46_read(&d->router->pa_eeprom_g2);
324 break;
325
326 case 0x7b: /* ??? */
327 break;
328
329 #if DEBUG_UNKNOWN
330 default:
331 if (op_type == MTS_READ) {
332 cpu_log(cpu,"MP_FPGA","read from addr 0x%x, pc=0x%llx\n",
333 offset,cpu_get_pc(cpu));
334 } else {
335 cpu_log(cpu,"MP_FPGA","write to addr 0x%x, value=0x%llx, "
336 "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu));
337 }
338 #endif
339 }
340
341 return NULL;
342 }
343
344 /* Initialize EEPROM groups */
345 static void init_eeprom_groups(c7200_t *router)
346 {
347 /* Group 1: bays 0, 1, 3, 4 */
348 router->pa_eeprom_g1 = eeprom_bays_g1;
349 router->pa_eeprom_g1.eeprom[0] = &router->pa_bay[0].eeprom;
350 router->pa_eeprom_g1.eeprom[1] = &router->pa_bay[1].eeprom;
351 router->pa_eeprom_g1.eeprom[2] = &router->pa_bay[3].eeprom;
352 router->pa_eeprom_g1.eeprom[3] = &router->pa_bay[4].eeprom;
353
354 /* Group 2: bays 2, 5, 6 */
355 router->pa_eeprom_g2 = eeprom_bays_g2;
356 router->pa_eeprom_g2.eeprom[0] = &router->pa_bay[2].eeprom;
357 router->pa_eeprom_g2.eeprom[1] = &router->pa_bay[5].eeprom;
358 router->pa_eeprom_g2.eeprom[2] = &router->pa_bay[6].eeprom;
359 }
360
361 /* Shutdown the MP FPGA device */
362 void dev_c7200_mpfpga_shutdown(vm_instance_t *vm,struct mpfpga_data *d)
363 {
364 if (d != NULL) {
365 /* Remove the device */
366 dev_remove(vm,&d->dev);
367
368 /* Free the structure itself */
369 free(d);
370 }
371 }
372
373 /*
374 * dev_c7200_mpfpga_init()
375 */
376 int dev_c7200_mpfpga_init(c7200_t *router,m_uint64_t paddr,m_uint32_t len)
377 {
378 struct mpfpga_data *d;
379
380 /* Allocate private data structure */
381 if (!(d = malloc(sizeof(*d)))) {
382 fprintf(stderr,"MP_FPGA: out of memory\n");
383 return(-1);
384 }
385
386 memset(d,0,sizeof(*d));
387 d->router = router;
388
389 /* Initialize EEPROMs */
390 init_eeprom_groups(router);
391
392 vm_object_init(&d->vm_obj);
393 d->vm_obj.name = "mp_fpga";
394 d->vm_obj.data = d;
395 d->vm_obj.shutdown = (vm_shutdown_t)dev_c7200_mpfpga_shutdown;
396
397 /* Set device properties */
398 dev_init(&d->dev);
399 d->dev.name = "mp_fpga";
400 d->dev.phys_addr = paddr;
401 d->dev.phys_len = len;
402 d->dev.handler = dev_c7200_mpfpga_access;
403 d->dev.priv_data = d;
404
405 /* Map this device to the VM */
406 vm_bind_device(router->vm,&d->dev);
407 vm_object_add(router->vm,&d->vm_obj);
408 return(0);
409 }

  ViewVC Help
Powered by ViewVC 1.1.26