/[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 9 - (hide annotations)
Sat Oct 6 16:26:06 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7-RC3/dev_c3745_iofpga.c
File MIME type: text/plain
File size: 11116 byte(s)
dynamips-0.2.7-RC3

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

  ViewVC Help
Powered by ViewVC 1.1.26