/[dynamips]/trunk/dev_c6sup1_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 /trunk/dev_c6sup1_mpfpga.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (hide annotations)
Sat Oct 6 16:33:40 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.8-RC1/dev_c6sup1_mpfpga.c
File MIME type: text/plain
File size: 13943 byte(s)
dynamips-0.2.8-RC1

1 dpavlin 11 /*
2     * Cisco router simulation platform.
3     * Copyright (c) 2007 Christophe Fillot (cf@utc.fr)
4     *
5     * C6k-Sup1a 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 "nmc93cX6.h"
18     #include "dev_c6sup1.h"
19    
20     #define DEBUG_UNKNOWN 1
21     #define DEBUG_ACCESS 1
22     #define DEBUG_NET_IRQ 1
23    
24     /*
25     * Function 0xX000:
26     * bit 0: 0:present, 1:absent.
27     * bit 1: power ok (?)
28     */
29     #define SLOT_NOT_PRESENT 0x01
30     #define SLOT_POWER_OK 0x02
31    
32     /*
33     * Function 0xX200: requires bit 3 to be set to avoid error about power
34     * convertor failure.
35     */
36     #define SLOT_POWER_CONVERTOR 0x08
37    
38     /* Midplane FPGA private data */
39     struct c6sup1_mpfpga_data {
40     vm_obj_t vm_obj;
41     struct vdevice dev;
42    
43     c6sup1_t *router;
44     m_uint32_t irq_status;
45     m_uint32_t intr_enable;
46    
47     /* Slot/function selector */
48     u_int slot_sel;
49    
50     /* Slot status (up/down) */
51     u_int slot_status[C6SUP1_MAX_SLOTS];
52     };
53    
54     /* === Definitions for "Backplane" EEPROM (Chassis Clock, VTT, ...) ======= */
55     #define EEPROM_BP_DOUT 0 /* reg 0x3c */
56     #define EEPROM_BP_DIN 0 /* reg 0x20 */
57     #define EEPROM_BP_CLK 1
58    
59     /* Chip select (CS) bits */
60     #define EEPROM_BP_CS_CHASSIS 3 /* Chassis (6509,...) */
61     #define EEPROM_BP_CS_CHASSIS2 4 /* Chassis redundant EEPROM ? */
62     #define EEPROM_BP_CS_PS1 5 /* Power Supply #1 */
63     #define EEPROM_BP_CS_PS2 6 /* Power Supply #2 */
64     #define EEPROM_BP_CS_CLK1 7 /* Clock card #1 */
65     #define EEPROM_BP_CS_CLK2 8 /* Clock card #2 */
66     #define EEPROM_BP_CS_VTT1 9 /* VTT #1 */
67     #define EEPROM_BP_CS_VTT2 10 /* VTT #2 */
68     #define EEPROM_BP_CS_VTT3 11 /* VTT #3 */
69    
70     static const struct nmc93cX6_eeprom_def eeprom_bp_def_chassis = {
71     EEPROM_BP_CLK, EEPROM_BP_CS_CHASSIS, EEPROM_BP_DIN, EEPROM_BP_DOUT,
72     };
73    
74     static const struct nmc93cX6_eeprom_def eeprom_bp_def_chassis2 = {
75     EEPROM_BP_CLK, EEPROM_BP_CS_CHASSIS2, EEPROM_BP_DIN, EEPROM_BP_DOUT,
76     };
77    
78     static const struct nmc93cX6_eeprom_def eeprom_bp_def_ps1 = {
79     EEPROM_BP_CLK, EEPROM_BP_CS_PS1, EEPROM_BP_DIN, EEPROM_BP_DOUT,
80     };
81    
82     static const struct nmc93cX6_eeprom_def eeprom_bp_def_ps2 = {
83     EEPROM_BP_CLK, EEPROM_BP_CS_PS2, EEPROM_BP_DIN, EEPROM_BP_DOUT,
84     };
85    
86     static const struct nmc93cX6_eeprom_def eeprom_bp_def_clk1 = {
87     EEPROM_BP_CLK, EEPROM_BP_CS_CLK1, EEPROM_BP_DIN, EEPROM_BP_DOUT,
88     };
89    
90     static const struct nmc93cX6_eeprom_def eeprom_bp_def_clk2 = {
91     EEPROM_BP_CLK, EEPROM_BP_CS_CLK2, EEPROM_BP_DIN, EEPROM_BP_DOUT,
92     };
93    
94     static const struct nmc93cX6_eeprom_def eeprom_bp_def_vtt1 = {
95     EEPROM_BP_CLK, EEPROM_BP_CS_VTT1, EEPROM_BP_DIN, EEPROM_BP_DOUT,
96     };
97    
98     static const struct nmc93cX6_eeprom_def eeprom_bp_def_vtt2 = {
99     EEPROM_BP_CLK, EEPROM_BP_CS_VTT2, EEPROM_BP_DIN, EEPROM_BP_DOUT,
100     };
101    
102     static const struct nmc93cX6_eeprom_def eeprom_bp_def_vtt3 = {
103     EEPROM_BP_CLK, EEPROM_BP_CS_VTT3, EEPROM_BP_DIN, EEPROM_BP_DOUT,
104     };
105    
106     /* Backplane EEPROMs */
107     static const struct nmc93cX6_group eeprom_bp_group = {
108     EEPROM_TYPE_NMC93C56, 9, 0,
109     EEPROM_DORD_REVERSED,
110     EEPROM_DOUT_KEEP,
111     EEPROM_DEBUG_DISABLED,
112     "Backplane EEPROMs",
113     {
114     &eeprom_bp_def_chassis,
115     &eeprom_bp_def_chassis2,
116     &eeprom_bp_def_ps1,
117     &eeprom_bp_def_ps2,
118     &eeprom_bp_def_clk1,
119     &eeprom_bp_def_clk2,
120     &eeprom_bp_def_vtt1,
121     &eeprom_bp_def_vtt2,
122     &eeprom_bp_def_vtt3,
123     },
124     };
125    
126     /* === Definitions for "Supervisor" EEPROMs (Sup1A,PFC/EARL) ============== */
127     #define EEPROM_SUP_DOUT 0 /* XXX */
128     #define EEPROM_SUP_DIN 2
129     #define EEPROM_SUP_CLK 1
130     #define EEPROM_SUP_CS 3
131    
132     #define EEPROM_EARL_DOUT 2 /* XXX */
133     #define EEPROM_EARL_DIN 9
134     #define EEPROM_EARL_CLK 10
135     #define EEPROM_EARL_CS 8
136    
137     static const struct nmc93cX6_eeprom_def eeprom_sup_def = {
138     EEPROM_SUP_CLK, EEPROM_SUP_CS, EEPROM_SUP_DIN, EEPROM_SUP_DOUT,
139     };
140    
141     static const struct nmc93cX6_eeprom_def eeprom_earl_def = {
142     EEPROM_EARL_CLK, EEPROM_EARL_CS, EEPROM_EARL_DIN, EEPROM_EARL_DOUT,
143     };
144    
145     /* Supervisor EEPROMs */
146     static const struct nmc93cX6_group eeprom_sup_group = {
147     EEPROM_TYPE_NMC93C56, 2, 0,
148     EEPROM_DORD_REVERSED,
149     EEPROM_DOUT_KEEP,
150     EEPROM_DEBUG_DISABLED,
151     "Supervisor EEPROMs",
152     { &eeprom_sup_def, &eeprom_earl_def },
153     };
154    
155     /* === Definitions for "Slot" EEPROM ====================================== */
156     #define EEPROM_SLOT_DOUT 0 /* reg 0x4c */
157     #define EEPROM_SLOT_DIN 0 /* reg 0x48 */
158     #define EEPROM_SLOT_CLK 1
159     #define EEPROM_SLOT_CS 3
160    
161     static const struct nmc93cX6_eeprom_def eeprom_slot_def = {
162     EEPROM_SLOT_CLK, EEPROM_SLOT_CS, EEPROM_SLOT_DIN, EEPROM_SLOT_DOUT,
163     };
164    
165     static const struct nmc93cX6_group eeprom_slot_group = {
166     EEPROM_TYPE_NMC93C56, 1, 0,
167     EEPROM_DORD_REVERSED,
168     EEPROM_DOUT_KEEP,
169     EEPROM_DEBUG_DISABLED,
170     "Slot EEPROMs",
171     { &eeprom_slot_def },
172     };
173    
174     /* ------------------------------------------------------------------------ */
175    
176     /* Update network interrupt status */
177     static inline
178     void dev_c6sup1_mpfpga_net_update_irq(struct c6sup1_mpfpga_data *d)
179     {
180     if (d->irq_status) {
181     vm_set_irq(d->router->vm,C6SUP1_NETIO_IRQ);
182     } else {
183     vm_clear_irq(d->router->vm,C6SUP1_NETIO_IRQ);
184     }
185     }
186    
187     /* Trigger a Network IRQ for the specified slot/port */
188     void dev_c6sup1_mpfpga_net_set_irq(struct c6sup1_mpfpga_data *d,
189     u_int slot,u_int port)
190     {
191     #if DEBUG_NET_IRQ
192     vm_log(d->router->vm,"MP_FPGA","setting NetIRQ for slot %u port %u\n",
193     slot,port);
194     #endif
195     d->irq_status |= 1 << slot;
196     dev_c6sup1_mpfpga_net_update_irq(d);
197     }
198    
199     /* Clear a Network IRQ for the specified slot/port */
200     void dev_c6sup1_mpfpga_net_clear_irq(struct c6sup1_mpfpga_data *d,
201     u_int slot,u_int port)
202     {
203     #if DEBUG_NET_IRQ
204     vm_log(d->router->vm,"MP_FPGA","clearing NetIRQ for slot %u port %u\n",
205     slot,port);
206     #endif
207     d->irq_status &= ~(1 << slot);
208     dev_c6sup1_mpfpga_net_update_irq(d);
209     }
210    
211     /*
212     * dev_c6sup1_access()
213     */
214     void *dev_c6sup1_mpfpga_access(cpu_gen_t *cpu,struct vdevice *dev,
215     m_uint32_t offset,u_int op_size,u_int op_type,
216     m_uint64_t *data)
217     {
218     struct c6sup1_mpfpga_data *d = dev->priv_data;
219     struct nmc93cX6_group *grp;
220     u_int i,slot,func;
221    
222     if (op_type == MTS_READ)
223     *data = 0xFFFFFFFF;
224    
225     #if DEBUG_ACCESS
226     if (op_type == MTS_READ) {
227     cpu_log(cpu,"MP_FPGA",
228     "reading reg 0x%x at pc=0x%llx, ra=0x%llx (size=%u)\n",
229     offset,cpu_get_pc(cpu),CPU_MIPS64(cpu)->gpr[MIPS_GPR_RA],
230     op_size);
231     } else {
232     cpu_log(cpu,"MP_FPGA",
233     "writing reg 0x%x at pc=0x%llx, ra=0x%llx "
234     "data=0x%llx (size=%u)\n",
235     offset,cpu_get_pc(cpu),CPU_MIPS64(cpu)->gpr[MIPS_GPR_RA],
236     *data,op_size);
237     }
238     #endif
239    
240     switch(offset) {
241     case 0x0c:
242     case 0x14:
243     case 0x1c:
244     if (op_type == MTS_READ)
245     *data = 0;
246     break;
247    
248     case 0x18:
249     if (op_type == MTS_READ)
250     *data = 0x8000;
251     break;
252    
253     /* 0x3E80 is written regularly here (watchdog ?) */
254     case 0x20004:
255     break;
256    
257     /* Backplane EEPROMs */
258     case 0x000020:
259     if (op_type == MTS_WRITE) {
260     //m_log("EEPROM","write access(BP): data=0x%4.4llx\n",*data);
261     nmc93cX6_write(&d->router->bp_eeprom_group,(u_int)(*data));
262     }
263     break;
264    
265     /* Supervisor EEPROMs */
266     case 0x000024:
267     if (op_type == MTS_WRITE) {
268     //m_log("EEPROM","write access(SUP): data=0x%4.4llx\n",*data);
269     nmc93cX6_write(&d->router->sup_eeprom_group,(u_int)(*data));
270     }
271     break;
272    
273     /* Backplane/Supervisor EEPROMs read access */
274     case 0x00003C:
275     if (op_type == MTS_READ) {
276     *data = 0x0000;
277    
278     /* Backplane EEPROMs */
279     grp = &d->router->bp_eeprom_group;
280    
281     for(i=0;i<grp->nr_eeprom;i++) {
282     if (nmc93cX6_is_active(grp,i))
283     *data |= nmc93cX6_get_dout(grp,i);
284     }
285    
286     /* Supervisor EEPROMs */
287     grp = &d->router->sup_eeprom_group;
288    
289     for(i=0;i<grp->nr_eeprom;i++) {
290     if (nmc93cX6_is_active(grp,i))
291     if (nmc93cX6_get_dout(grp,i))
292     *data |= 0xFFFF; //nmc93cX6_get_dout(grp,i);
293     }
294     }
295     break;
296    
297     /* Slot selection */
298     case 0x000044:
299     if (op_type == MTS_WRITE) {
300     d->slot_sel = *data;
301     slot = (d->slot_sel & 0xF000) >> 12;
302     func = (d->slot_sel & 0x0F00) >> 8;
303    
304     if (slot <= C6SUP1_MAX_SLOTS) {
305     grp = &d->router->slot_eeprom_group;
306     grp->eeprom[0] = &d->router->slot_eeprom[slot-1];
307    
308     /* mark the slot as powered on */
309     if (func == 0x02) {
310     //printf("Marking slot %u as powered ON\n",slot);
311     d->slot_status[slot-1] = TRUE;
312     }
313     }
314     }
315     break;
316    
317     /* Slot EEPROM write */
318     case 0x000048:
319     if (op_type == MTS_WRITE)
320     nmc93cX6_write(&d->router->slot_eeprom_group,(u_int)(*data));
321     break;
322    
323     /* Slot EEPROM read */
324     case 0x00004c:
325     if (op_type == MTS_READ) {
326     grp = &d->router->slot_eeprom_group;
327     slot = (d->slot_sel & 0xF000) >> 12;
328     func = (d->slot_sel & 0x0F00) >> 8;
329     *data = 0;
330    
331     switch(func) {
332     /* Presence + power ? */
333     case 0x00:
334     *data = SLOT_NOT_PRESENT;
335    
336     if (grp->eeprom[0] && grp->eeprom[0]->data) {
337     *data = 0;
338    
339     /* The SUP slot is always powered */
340     if (d->slot_status[slot-1] ||
341     (slot == d->router->sup_slot))
342     *data |= SLOT_POWER_OK;
343     }
344     break;
345    
346     case 0x01:
347     *data = 0x0001;
348    
349     if (grp->eeprom[0] && grp->eeprom[0]->data) {
350     *data = 0x0000;
351     }
352     break;
353    
354     /* Power-related */
355     case 0x02:
356     *data = SLOT_POWER_CONVERTOR;
357     break;
358    
359     /* EEPROM reading */
360     case 0x05:
361     if (nmc93cX6_is_active(grp,0))
362     *data |= nmc93cX6_get_dout(grp,0);
363     break;
364    
365     default:
366     cpu_log(cpu,"MP_FPGA","slot control: unknown func 0x%2.2x\n",
367     func);
368     }
369     }
370     break;
371    
372     /* Slot Identification */
373     case 0x000004:
374     if (op_type == MTS_READ)
375     *data = (d->router->sup_slot << 8) | 0x80;
376     break;
377    
378     /* Unknown: EARL interrupt ? */
379     /* 00:00:27: %CPU_MONITOR-3-PEER_EXCEPTION:
380     CPU_MONITOR peer has failed due to exception , resetting [0/1] */
381     case 0x000050:
382     if (op_type == MTS_READ)
383     *data = 0; //0xFFFF;
384     break;
385    
386     case 0x000074:
387     if (op_type == MTS_READ)
388     *data = 0x0000; //0x3FFF;
389     break;
390    
391     #if DEBUG_UNKNOWN
392     default:
393     if (op_type == MTS_READ) {
394     cpu_log(cpu,"MP_FPGA",
395     "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
396     offset,cpu_get_pc(cpu),op_size);
397     } else {
398     cpu_log(cpu,"MP_FPGA",
399     "write to unknown addr 0x%x, value=0x%llx, pc=0x%llx "
400     "(op_size=%u)\n",offset,*data,cpu_get_pc(cpu),op_size);
401     }
402     #endif
403     }
404    
405     return NULL;
406     }
407    
408     /* Shutdown the MP FPGA device */
409     static void
410     dev_c6sup1_mpfpga_shutdown(vm_instance_t *vm,struct c6sup1_mpfpga_data *d)
411     {
412     if (d != NULL) {
413     /* Remove the device */
414     dev_remove(vm,&d->dev);
415    
416     /* Free the structure itself */
417     free(d);
418     }
419     }
420    
421     /* Initialize EEPROM groups */
422     void c6sup1_init_eeprom_groups(c6sup1_t *router)
423     {
424     struct nmc93cX6_group *grp;
425    
426     router->bp_eeprom_group = eeprom_bp_group;
427     router->sup_eeprom_group = eeprom_sup_group;
428     router->slot_eeprom_group = eeprom_slot_group;
429    
430     /* XXX */
431     grp = &router->bp_eeprom_group;
432     grp->eeprom[0] = cisco_eeprom_find_c6k("C6K-CHASSIS-6509");
433     grp->eeprom[2] = cisco_eeprom_find_c6k("C6K-POWER-1000W");
434     grp->eeprom[3] = cisco_eeprom_find_c6k("C6K-POWER-1000W");
435     grp->eeprom[6] = cisco_eeprom_find_c6k("C6K-VTT");
436     grp->eeprom[7] = cisco_eeprom_find_c6k("C6K-VTT");
437     grp->eeprom[8] = cisco_eeprom_find_c6k("C6K-VTT");
438    
439     grp = &router->sup_eeprom_group;
440     grp->eeprom[0] = cisco_eeprom_find_c6k("C6K-SUP-SUP1A-2GE");
441     grp->eeprom[1] = cisco_eeprom_find_c6k("C6K-EARL-PFC1");
442    
443     cisco_eeprom_copy(&router->slot_eeprom[0],
444     cisco_eeprom_find_c6k("C6K-SUP-SUP1A-2GE"));
445    
446     cisco_eeprom_copy(&router->slot_eeprom[8],
447     cisco_eeprom_find_c6k("C6K-LC-WS-X6248"));
448     }
449    
450     /*
451     * dev_c6sup1_mpfpga_init()
452     */
453     int dev_c6sup1_mpfpga_init(c6sup1_t *router,m_uint64_t paddr,m_uint32_t len)
454     {
455     struct c6sup1_mpfpga_data *d;
456    
457     /* Allocate private data structure */
458     if (!(d = malloc(sizeof(*d)))) {
459     fprintf(stderr,"MP_FPGA: out of memory\n");
460     return(-1);
461     }
462    
463     memset(d,0,sizeof(*d));
464     d->router = router;
465    
466     vm_object_init(&d->vm_obj);
467     d->vm_obj.name = "mp_fpga";
468     d->vm_obj.data = d;
469     d->vm_obj.shutdown = (vm_shutdown_t)dev_c6sup1_mpfpga_shutdown;
470    
471     /* Set device properties */
472     dev_init(&d->dev);
473     d->dev.name = "mp_fpga";
474     d->dev.phys_addr = paddr;
475     d->dev.phys_len = len;
476     d->dev.handler = dev_c6sup1_mpfpga_access;
477     d->dev.priv_data = d;
478    
479     /* Map this device to the VM */
480     vm_bind_device(router->vm,&d->dev);
481     vm_object_add(router->vm,&d->vm_obj);
482     return(0);
483     }

  ViewVC Help
Powered by ViewVC 1.1.26