/[dynamips]/upstream/dynamips-0.2.7-RC2/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

Annotation of /upstream/dynamips-0.2.7-RC2/dev_c7200_mpfpga.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7 - (hide annotations)
Sat Oct 6 16:23:47 2007 UTC (16 years, 6 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7-RC1/dev_c7200_mpfpga.c
File MIME type: text/plain
File size: 11376 byte(s)
dynamips-0.2.7-RC1

1 dpavlin 1 /*
2 dpavlin 7 * Cisco router simulation platform.
3 dpavlin 1 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4     *
5 dpavlin 7 * Cisco c7200 Midplane FPGA.
6 dpavlin 1 */
7    
8     #include <stdio.h>
9     #include <stdlib.h>
10     #include <string.h>
11    
12 dpavlin 7 #include "cpu.h"
13     #include "vm.h"
14 dpavlin 1 #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 dpavlin 7 #define DEBUG_OIR 1
23 dpavlin 1
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 dpavlin 3 },
95 dpavlin 1
96     /* Bay 1 */
97     { BAY1_EEPROM_CLOCK_BIT , BAY1_EEPROM_SELECT_BIT,
98     BAY1_EEPROM_DIN_BIT , BAY1_EEPROM_DOUT_BIT,
99 dpavlin 3 },
100 dpavlin 1
101     /* Bay 2 */
102     { BAY2_EEPROM_CLOCK_BIT , BAY2_EEPROM_SELECT_BIT,
103     BAY2_EEPROM_DIN_BIT , BAY2_EEPROM_DOUT_BIT,
104 dpavlin 3 },
105 dpavlin 1
106     /* Bay 3 */
107     { BAY3_EEPROM_CLOCK_BIT , BAY3_EEPROM_SELECT_BIT,
108     BAY3_EEPROM_DIN_BIT , BAY3_EEPROM_DOUT_BIT,
109 dpavlin 3 },
110 dpavlin 1
111     /* Bay 4 */
112     { BAY4_EEPROM_CLOCK_BIT , BAY4_EEPROM_SELECT_BIT,
113     BAY4_EEPROM_DIN_BIT , BAY4_EEPROM_DOUT_BIT,
114 dpavlin 3 },
115 dpavlin 1
116     /* Bay 5 */
117     { BAY5_EEPROM_CLOCK_BIT , BAY5_EEPROM_SELECT_BIT,
118     BAY5_EEPROM_DIN_BIT , BAY5_EEPROM_DOUT_BIT,
119 dpavlin 3 },
120 dpavlin 1
121     /* Bay 6 */
122     { BAY6_EEPROM_CLOCK_BIT , BAY6_EEPROM_SELECT_BIT,
123     BAY6_EEPROM_DIN_BIT , BAY6_EEPROM_DOUT_BIT,
124 dpavlin 3 },
125 dpavlin 1 };
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 dpavlin 3 { &eeprom_bay_def[0], &eeprom_bay_def[1],
132     &eeprom_bay_def[3], &eeprom_bay_def[4],
133     },
134 dpavlin 1 };
135    
136     /* EEPROM group #2 (Bays 2, 5, 6) */
137     static const struct nmc93c46_group eeprom_bays_g2 = {
138 dpavlin 3 3, 0, "PA Bays (Group #2) EEPROM", FALSE,
139 dpavlin 1
140 dpavlin 3 { &eeprom_bay_def[2], &eeprom_bay_def[5], &eeprom_bay_def[6] },
141 dpavlin 1 };
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 dpavlin 7
161 dpavlin 1 /* 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 dpavlin 7 void *dev_c7200_mpfpga_access(cpu_gen_t *cpu,struct vdevice *dev,
187 dpavlin 1 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 dpavlin 7 offset,cpu_get_pc(cpu),op_size);
203 dpavlin 1 } else {
204     cpu_log(cpu,"MP_FPGA",
205     "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",
206 dpavlin 7 offset,cpu_get_pc(cpu),*data,op_size);
207 dpavlin 1 }
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 dpavlin 7 vm_clear_irq(d->router->vm,C7200_PA_MGMT_IRQ);
244 dpavlin 1 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 dpavlin 7 offset,cpu_get_pc(cpu),d->router->oir_status);
263 dpavlin 1 #endif
264     *data = d->router->oir_status;
265 dpavlin 7 vm_clear_irq(d->router->vm,C7200_OIR_IRQ);
266 dpavlin 1 } else {
267     #if DEBUG_OIR
268     cpu_log(cpu,"MP_FPGA","writing reg 0x%x at pc=0x%llx "
269 dpavlin 7 "(data=0x%llx)\n",offset,cpu_get_pc(cpu),*data);
270 dpavlin 1 #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 dpavlin 7 cpu_log(cpu,"MP_FPGA","reading 0x78 at pc=0x%llx\n",
284     cpu_get_pc(cpu));
285 dpavlin 1 #endif
286     *data = 0x00;
287     } else {
288     #if DEBUG_OIR
289     cpu_log(cpu,"MP_FPGA","writing reg 0x78 at pc=0x%llx "
290 dpavlin 7 "(data=0x%llx)\n",cpu_get_pc(cpu),*data);
291 dpavlin 1 #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 dpavlin 7 offset,cpu_get_pc(cpu));
334 dpavlin 1 } else {
335     cpu_log(cpu,"MP_FPGA","write to addr 0x%x, value=0x%llx, "
336 dpavlin 7 "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu));
337 dpavlin 1 }
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 dpavlin 3 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 dpavlin 1
354     /* Group 2: bays 2, 5, 6 */
355 dpavlin 3 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 dpavlin 1 }
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