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

Annotation of /upstream/dynamips-0.2.6-RC1/dev_c7200_mpfpga.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations)
Sat Oct 6 16:03:58 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 11611 byte(s)
import dynamips-0.2.6-RC1

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

  ViewVC Help
Powered by ViewVC 1.1.26