/[dynamips]/trunk/dev_c3745_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

Annotation of /trunk/dev_c3745_iofpga.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 dpavlin 4 /*
2     * Cisco 3745 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 dpavlin 7 #include "cpu.h"
17     #include "vm.h"
18 dpavlin 4 #include "dynamips.h"
19     #include "memory.h"
20     #include "device.h"
21     #include "dev_vtty.h"
22 dpavlin 8 #include "nmc93cX6.h"
23 dpavlin 4 #include "dev_c3745.h"
24    
25     /* Debugging flags */
26     #define DEBUG_UNKNOWN 1
27     #define DEBUG_ACCESS 0
28 dpavlin 8 #define DEBUG_NET_IRQ 0
29 dpavlin 4
30     /* Definitions for Motherboard EEPROM (0x00) */
31     #define EEPROM_MB_DOUT 3
32     #define EEPROM_MB_DIN 2
33     #define EEPROM_MB_CLK 1
34     #define EEPROM_MB_CS 0
35    
36     /* Definitions for I/O board EEPROM (0x01) */
37     #define EEPROM_IO_DOUT 3
38     #define EEPROM_IO_DIN 2
39     #define EEPROM_IO_CLK 1
40     #define EEPROM_IO_CS 8
41    
42     /* Definitions for Midplane EEPROM (0x02) */
43     #define EEPROM_MP_DOUT 3
44     #define EEPROM_MP_DIN 2
45     #define EEPROM_MP_CLK 1
46     #define EEPROM_MP_CS 9
47    
48     /* Definitions for Network Modules EEPROM */
49     #define EEPROM_NM_DOUT 7
50     #define EEPROM_NM_DIN 6
51     #define EEPROM_NM_CLK 2
52     #define EEPROM_NM_CS 4
53    
54 dpavlin 8 /* Network IRQ distribution */
55     struct net_irq_distrib {
56     u_int reg;
57     u_int offset;
58     };
59 dpavlin 4
60 dpavlin 8 static struct net_irq_distrib net_irq_dist[C3745_MAX_NM_BAYS] = {
61     { 0, 0 }, /* Slot 0: reg 0x20, 0x00XX */
62     { 1, 0 }, /* Slot 1: reg 0x22, 0x000X */
63     { 1, 4 }, /* Slot 2: reg 0x22, 0x00X0 */
64     { 1, 8 }, /* Slot 3: reg 0x22, 0x0X00 */
65     { 1, 12 }, /* Slot 4: reg 0x22, 0xX000 */
66     };
67    
68 dpavlin 4 /* IO FPGA structure */
69 dpavlin 8 struct c3745_iofpga_data {
70 dpavlin 4 vm_obj_t vm_obj;
71     struct vdevice dev;
72     c3745_t *router;
73    
74 dpavlin 8 /* Network IRQ status */
75     m_uint16_t net_irq_status[2];
76 dpavlin 4
77     /* Interrupt mask */
78     m_uint16_t intr_mask,io_mask2;
79    
80     /* EEPROM select */
81     u_int eeprom_select;
82 dpavlin 11
83     /* WIC select */
84     u_int wic_select;
85     u_int wic_cmd_pos;
86     u_int wic_cmd_valid;
87     m_uint16_t wic_cmd[2];
88 dpavlin 4 };
89    
90     /* Motherboard EEPROM definition */
91 dpavlin 8 static const struct nmc93cX6_eeprom_def eeprom_mb_def = {
92 dpavlin 4 EEPROM_MB_CLK, EEPROM_MB_CS,
93     EEPROM_MB_DIN, EEPROM_MB_DOUT,
94     };
95    
96     /* I/O board EEPROM definition */
97 dpavlin 8 static const struct nmc93cX6_eeprom_def eeprom_io_def = {
98 dpavlin 4 EEPROM_IO_CLK, EEPROM_IO_CS,
99     EEPROM_IO_DIN, EEPROM_IO_DOUT,
100     };
101    
102     /* Midplane EEPROM definition */
103 dpavlin 8 static const struct nmc93cX6_eeprom_def eeprom_mp_def = {
104 dpavlin 4 EEPROM_MP_CLK, EEPROM_MP_CS,
105     EEPROM_MP_DIN, EEPROM_MP_DOUT,
106     };
107    
108     /* System EEPROM group */
109 dpavlin 8 static const struct nmc93cX6_group eeprom_sys_group = {
110 dpavlin 11 EEPROM_TYPE_NMC93C46, 3, 0,
111     EEPROM_DORD_NORMAL,
112     EEPROM_DOUT_HIGH,
113     EEPROM_DEBUG_DISABLED,
114     "System EEPROM",
115 dpavlin 4 { &eeprom_mb_def, &eeprom_io_def, &eeprom_mp_def },
116     };
117    
118     /* NM EEPROM definition */
119 dpavlin 8 static const struct nmc93cX6_eeprom_def eeprom_nm_def = {
120 dpavlin 4 EEPROM_NM_CLK, EEPROM_NM_CS,
121     EEPROM_NM_DIN, EEPROM_NM_DOUT,
122     };
123    
124     /* NM EEPROM */
125 dpavlin 8 static const struct nmc93cX6_group eeprom_nm_group = {
126 dpavlin 11 EEPROM_TYPE_NMC93C46, 1, 0,
127     EEPROM_DORD_NORMAL,
128     EEPROM_DOUT_HIGH,
129     EEPROM_DEBUG_DISABLED,
130     "NM EEPROM",
131     { &eeprom_nm_def },
132 dpavlin 4 };
133    
134 dpavlin 8 /* Update network interrupt status */
135     static inline void dev_c3745_iofpga_net_update_irq(struct c3745_iofpga_data *d)
136     {
137     if ((d->net_irq_status[0] != 0xFFFF) || (d->net_irq_status[1] != 0xFFFF)) {
138     vm_set_irq(d->router->vm,C3745_NETIO_IRQ);
139     } else {
140     vm_clear_irq(d->router->vm,C3745_NETIO_IRQ);
141     }
142     }
143    
144     /* Trigger a Network IRQ for the specified slot/port */
145     void dev_c3745_iofpga_net_set_irq(struct c3745_iofpga_data *d,
146     u_int slot,u_int port)
147     {
148     struct net_irq_distrib *irq_dist;
149    
150     #if DEBUG_NET_IRQ
151     vm_log(d->router->vm,"IO_FPGA","setting NetIRQ for slot %u port %u\n",
152     slot,port);
153     #endif
154     irq_dist = &net_irq_dist[slot];
155     d->net_irq_status[irq_dist->reg] &= ~(1 << (irq_dist->offset + port));
156     dev_c3745_iofpga_net_update_irq(d);
157     }
158    
159     /* Clear a Network IRQ for the specified slot/port */
160     void dev_c3745_iofpga_net_clear_irq(struct c3745_iofpga_data *d,
161     u_int slot,u_int port)
162     {
163     struct net_irq_distrib *irq_dist;
164    
165     #if DEBUG_NET_IRQ
166     vm_log(d->router->vm,"IO_FPGA","clearing NetIRQ for slot %u port %u\n",
167     slot,port);
168     #endif
169     irq_dist = &net_irq_dist[slot];
170     d->net_irq_status[irq_dist->reg] |= (1 << (irq_dist->offset + port));
171     dev_c3745_iofpga_net_update_irq(d);
172     }
173    
174 dpavlin 11 /* Read a WIC EEPROM */
175     static m_uint16_t dev_c3745_read_wic_eeprom(struct c3745_iofpga_data *d)
176     {
177     struct cisco_eeprom *eeprom;
178     u_int wic_port;
179     u_int eeprom_offset;
180     m_uint8_t val[2];
181    
182     switch(d->wic_select) {
183     case 0x1700:
184     wic_port = 0x10;
185     break;
186     case 0x1D00:
187     wic_port = 0x20;
188     break;
189     case 0x3500:
190     wic_port = 0x30;
191     break;
192     default:
193     wic_port = 0;
194     }
195    
196     /* No WIC in slot or no EEPROM: fake an empty EEPROM */
197     if (!wic_port || !(eeprom = vm_slot_get_eeprom(d->router->vm,0,wic_port)))
198     return(0xFFFF);
199    
200     /* EEPROM offset is in the lowest 6 bits */
201     eeprom_offset = d->wic_cmd[0] & 0x3F;
202    
203     cisco_eeprom_get_byte(eeprom,eeprom_offset,&val[0]);
204     cisco_eeprom_get_byte(eeprom,eeprom_offset+1,&val[1]);
205    
206     return(((m_uint16_t)val[0] << 8) | val[1]);
207     }
208    
209 dpavlin 4 /*
210     * dev_c3745_iofpga_access()
211     */
212     static void *
213 dpavlin 7 dev_c3745_iofpga_access(cpu_gen_t *cpu,struct vdevice *dev,
214 dpavlin 4 m_uint32_t offset,u_int op_size,u_int op_type,
215     m_uint64_t *data)
216     {
217 dpavlin 8 struct c3745_iofpga_data *d = dev->priv_data;
218 dpavlin 4 u_int slot;
219    
220     if (op_type == MTS_READ)
221     *data = 0x0;
222 dpavlin 11
223 dpavlin 4 #if DEBUG_ACCESS
224     if (op_type == MTS_READ) {
225     cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",
226 dpavlin 7 offset,cpu_get_pc(cpu),op_size);
227 dpavlin 4 } else {
228     cpu_log(cpu,"IO_FPGA",
229     "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",
230 dpavlin 7 offset,cpu_get_pc(cpu),*data,op_size);
231 dpavlin 4 }
232     #endif
233    
234     switch(offset) {
235     /* Unknown */
236     case 0x000000:
237     if (op_type == MTS_READ)
238     *data = 0xFFFF;
239     break;
240    
241     /* Unknown */
242     case 0x000004:
243     if (op_type == MTS_READ)
244     *data = 0xFFFF;
245     break;
246    
247     /*
248     * CompactFlash.
249     *
250     * Bit 0: Slot0 Compact Flash presence.
251     * Bit 1: System Compact Flash presence.
252     */
253     case 0x000012:
254     if (op_type == MTS_READ) {
255     *data = 0xFFFF;
256    
257     /* System Flash ? */
258     if (cpu->vm->pcmcia_disk_size[0])
259     *data &= ~0x02;
260    
261     /* Slot0 Flash ? */
262     if (cpu->vm->pcmcia_disk_size[1])
263     *data &= ~0x01;
264     }
265     break;
266    
267     /* Suppress the "****TDM FPGA download failed.." message */
268     case 0x000014:
269     if (op_type == MTS_READ)
270     *data = 0x00FF;
271     break;
272    
273     /* Power supply status */
274     case 0x00000a:
275     if (op_type == MTS_READ)
276     *data = 0x0000;
277     break;
278    
279     /* Fan status */
280     case 0x00000c:
281     if (op_type == MTS_READ)
282     *data = 0x0000;
283     break;
284    
285     /* System EEPROMs */
286     case 0x00000e:
287     if (op_type == MTS_WRITE)
288 dpavlin 8 nmc93cX6_write(&d->router->sys_eeprom_group,(u_int)(*data));
289 dpavlin 4 else
290 dpavlin 8 *data = nmc93cX6_read(&d->router->sys_eeprom_group);
291 dpavlin 4 break;
292    
293     /*
294     * Network interrupt status.
295     *
296     * Bit 0: 0 = GT96100 Ethernet ports.
297     * Bit 8: 0 = AIM slot 0.
298     * Bit 9: 0 = AIM slot 1.
299     */
300     case 0x000020:
301     if (op_type == MTS_READ)
302 dpavlin 8 *data = d->net_irq_status[0];
303 dpavlin 4 break;
304    
305     /*
306     * Network interrupt status.
307     *
308     * Bit 0: 0 = Interrupt for slot 1
309     * Bit 4: 0 = Interrupt for slot 2
310     * Bit 8: 0 = Interrupt for slot 3
311     * Bit 12: 0 = Interrupt for slot 4
312     */
313     case 0x000022:
314     if (op_type == MTS_READ)
315 dpavlin 8 *data = d->net_irq_status[1];
316 dpavlin 4 break;
317    
318     /*
319     * Per Slot Intr Mask (seen with "sh platform").
320     * IO Mask 1 is the lower 8-bits.
321     */
322     case 0x00002a:
323     if (op_type == MTS_READ)
324     *data = d->intr_mask;
325     else
326     d->intr_mask = *data;
327     break;
328    
329     /* IO Mask 2 (seen with "sh platform") */
330     case 0x00002c:
331     if (op_type == MTS_READ)
332     *data = d->io_mask2;
333     else
334     d->io_mask2 = *data;
335     break;
336    
337     /* EEPROM in slots 1-4 */
338     case 0x000040:
339     case 0x000042:
340     case 0x000044:
341     case 0x000046:
342     slot = (offset - 0x000040) >> 1;
343    
344     if (op_type == MTS_WRITE)
345 dpavlin 8 nmc93cX6_write(&d->router->nm_eeprom_group[slot],(u_int)(*data));
346 dpavlin 4 else
347 dpavlin 8 *data = nmc93cX6_read(&d->router->nm_eeprom_group[slot]);
348 dpavlin 4 break;
349    
350     /* AIM slot 0 EEPROM */
351     case 0x000048:
352     if (op_type == MTS_READ)
353     *data = 0xFFFF;
354     break;
355    
356     /* AIM slot 1 EEPROM */
357     case 0x00004A:
358     if (op_type == MTS_READ)
359     *data = 0xFFFF;
360     break;
361    
362     /*
363     * NM presence.
364     *
365     * Bit 0: 0 = NM present in slot 2 (0x42)
366     * Bit 4: 0 = NM present in slot 4 (0x46)
367     * Bit 8: 0 = NM present in slot 1 (0x40)
368     * Bit 12: 0 = NM present in slot 3 (0x44)
369     */
370     case 0x00004e:
371     if (op_type == MTS_READ) {
372     *data = 0xFFFF;
373    
374 dpavlin 11 if (vm_slot_get_card_ptr(d->router->vm,1))
375 dpavlin 4 *data &= ~0x0100;
376    
377 dpavlin 11 if (vm_slot_get_card_ptr(d->router->vm,2))
378 dpavlin 4 *data &= ~0x0001;
379    
380 dpavlin 11 if (vm_slot_get_card_ptr(d->router->vm,3))
381 dpavlin 4 *data &= ~0x1000;
382    
383 dpavlin 11 if (vm_slot_get_card_ptr(d->router->vm,4))
384 dpavlin 4 *data &= ~0x0010;
385     }
386     break;
387    
388 dpavlin 11 /*
389     * VWIC/WIC related
390     * Bits 0-2: WIC presence
391     */
392 dpavlin 4 case 0x100004:
393 dpavlin 11 if (op_type == MTS_READ) {
394     *data = 0xFFFF;
395    
396     /* check WIC 0 */
397     if (vm_slot_check_eeprom(d->router->vm,0,0x10))
398     *data &= ~0x01;
399    
400     /* check WIC 1 */
401     if (vm_slot_check_eeprom(d->router->vm,0,0x20))
402     *data &= ~0x02;
403    
404     /* check WIC 2 */
405     if (vm_slot_check_eeprom(d->router->vm,0,0x30))
406     *data &= ~0x04;
407     } else {
408     d->wic_select = *data;
409     }
410     break;
411    
412 dpavlin 4 case 0x100006:
413     if (op_type == MTS_READ)
414 dpavlin 11 *data = 0x0004;
415 dpavlin 4 break;
416    
417 dpavlin 11 case 0x100008:
418     if (op_type == MTS_READ) {
419     if (d->wic_cmd_valid) {
420     *data = dev_c3745_read_wic_eeprom(d);
421     d->wic_cmd_valid = FALSE;
422     } else {
423     *data = 0xFFFF;
424     }
425     } else {
426     /*
427     * Store the EEPROM command (in 2 words).
428     *
429     * For a read, we have:
430     * Word 0: 0x180 (nmc93c46 READ) + offset (6-bits).
431     * Word 1: 0 (no data).
432     */
433     d->wic_cmd[d->wic_cmd_pos++] = *data;
434    
435     if (d->wic_cmd_pos == 2) {
436     d->wic_cmd_pos = 0;
437     d->wic_cmd_valid = TRUE;
438     }
439     }
440     break;
441    
442 dpavlin 4 #if DEBUG_UNKNOWN
443     default:
444     if (op_type == MTS_READ) {
445     cpu_log(cpu,"IO_FPGA",
446     "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
447 dpavlin 7 offset,cpu_get_pc(cpu),op_size);
448 dpavlin 4 } else {
449     cpu_log(cpu,"IO_FPGA",
450     "write to unknown addr 0x%x, value=0x%llx, "
451 dpavlin 7 "pc=0x%llx (size=%u)\n",
452     offset,*data,cpu_get_pc(cpu),op_size);
453 dpavlin 4 }
454     #endif
455     }
456    
457     return NULL;
458     }
459    
460     /* Initialize EEPROM groups */
461     void c3745_init_eeprom_groups(c3745_t *router)
462     {
463     int i;
464    
465     /* Initialize Mainboard EEPROM */
466     router->sys_eeprom_group = eeprom_sys_group;
467    
468     for(i=0;i<3;i++) {
469     router->sys_eeprom_group.eeprom[i] = &router->sys_eeprom[i];
470     router->sys_eeprom[i].data = NULL;
471     router->sys_eeprom[i].len = 0;
472     }
473    
474     /* EEPROMs for Network Modules */
475     for(i=1;i<=4;i++) {
476     router->nm_eeprom_group[i-1] = eeprom_nm_group;
477 dpavlin 11 router->nm_eeprom_group[i-1].eeprom[0] = NULL;
478 dpavlin 4 }
479     }
480    
481     /* Shutdown the IO FPGA device */
482 dpavlin 8 static void
483     dev_c3745_iofpga_shutdown(vm_instance_t *vm,struct c3745_iofpga_data *d)
484 dpavlin 4 {
485     if (d != NULL) {
486     /* Remove the device */
487     dev_remove(vm,&d->dev);
488    
489     /* Free the structure itself */
490     free(d);
491     }
492     }
493    
494     /*
495     * dev_c3745_iofpga_init()
496     */
497     int dev_c3745_iofpga_init(c3745_t *router,m_uint64_t paddr,m_uint32_t len)
498     {
499     vm_instance_t *vm = router->vm;
500 dpavlin 8 struct c3745_iofpga_data *d;
501 dpavlin 4
502     /* Allocate private data structure */
503     if (!(d = malloc(sizeof(*d)))) {
504     fprintf(stderr,"IO_FPGA: out of memory\n");
505     return(-1);
506     }
507    
508     memset(d,0,sizeof(*d));
509     d->router = router;
510 dpavlin 8 d->net_irq_status[0] = 0xFFFF;
511     d->net_irq_status[1] = 0xFFFF;
512 dpavlin 4
513     vm_object_init(&d->vm_obj);
514     d->vm_obj.name = "io_fpga";
515     d->vm_obj.data = d;
516     d->vm_obj.shutdown = (vm_shutdown_t)dev_c3745_iofpga_shutdown;
517    
518     /* Set device properties */
519     dev_init(&d->dev);
520     d->dev.name = "io_fpga";
521     d->dev.phys_addr = paddr;
522     d->dev.phys_len = len;
523     d->dev.priv_data = d;
524     d->dev.handler = dev_c3745_iofpga_access;
525    
526     /* Map this device to the VM */
527     vm_bind_device(router->vm,&d->dev);
528     vm_object_add(vm,&d->vm_obj);
529     return(0);
530     }

  ViewVC Help
Powered by ViewVC 1.1.26