/[dynamips]/trunk/dev_c6msfc1_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_c6msfc1_mpfpga.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: 4663 byte(s)
make working copy

1 dpavlin 11 /*
2     * Cisco router simulation platform.
3     * Copyright (c) 2007 Christophe Fillot (cf@utc.fr)
4     *
5     * MSFC1 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_c6msfc1.h"
19    
20     #define DEBUG_UNKNOWN 1
21     #define DEBUG_ACCESS 1
22     #define DEBUG_NET_IRQ 1
23    
24     /* Midplane FPGA private data */
25     struct c6msfc1_mpfpga_data {
26     vm_obj_t vm_obj;
27     struct vdevice dev;
28    
29     c6msfc1_t *router;
30     m_uint32_t irq_status;
31     m_uint32_t intr_enable;
32     };
33    
34     /* Update network interrupt status */
35     static inline
36     void dev_c6msfc1_mpfpga_net_update_irq(struct c6msfc1_mpfpga_data *d)
37     {
38     if (d->irq_status) {
39     vm_set_irq(d->router->vm,C6MSFC1_NETIO_IRQ);
40     } else {
41     vm_clear_irq(d->router->vm,C6MSFC1_NETIO_IRQ);
42     }
43     }
44    
45     /* Trigger a Network IRQ for the specified slot/port */
46     void dev_c6msfc1_mpfpga_net_set_irq(struct c6msfc1_mpfpga_data *d,
47     u_int slot,u_int port)
48     {
49     #if DEBUG_NET_IRQ
50     vm_log(d->router->vm,"MP_FPGA","setting NetIRQ for slot %u port %u\n",
51     slot,port);
52     #endif
53     d->irq_status |= 1 << slot;
54     dev_c6msfc1_mpfpga_net_update_irq(d);
55     }
56    
57     /* Clear a Network IRQ for the specified slot/port */
58     void dev_c6msfc1_mpfpga_net_clear_irq(struct c6msfc1_mpfpga_data *d,
59     u_int slot,u_int port)
60     {
61     #if DEBUG_NET_IRQ
62     vm_log(d->router->vm,"MP_FPGA","clearing NetIRQ for slot %u port %u\n",
63     slot,port);
64     #endif
65     d->irq_status &= ~(1 << slot);
66     dev_c6msfc1_mpfpga_net_update_irq(d);
67     }
68    
69     /*
70     * dev_c6msfc1_access()
71     */
72     void *dev_c6msfc1_mpfpga_access(cpu_gen_t *cpu,struct vdevice *dev,
73     m_uint32_t offset,u_int op_size,u_int op_type,
74     m_uint64_t *data)
75     {
76     struct c6msfc1_mpfpga_data *d = dev->priv_data;
77    
78     if (op_type == MTS_READ)
79     *data = 0x0;
80    
81     #if DEBUG_ACCESS
82     if (op_type == MTS_READ) {
83     cpu_log(cpu,"MP_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",
84     offset,cpu_get_pc(cpu),op_size);
85     } else {
86     cpu_log(cpu,"MP_FPGA",
87     "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",
88     offset,cpu_get_pc(cpu),*data,op_size);
89     }
90     #endif
91    
92     switch(offset) {
93     /*
94     * Revision + Slot: just tell we're in slot 1 (and chip rev 2)
95     * Other bits are unknown.
96     */
97     case 0x00:
98     if (op_type == MTS_READ)
99     *data = 0x12;
100     break;
101    
102     /* Interrupt Control ("sh msfc") - unknown */
103     case 0x08:
104     if (op_type == MTS_READ)
105     *data = 0x1c;
106     break;
107    
108     /* Interrupt Enable ("sh msfc") */
109     case 0x10:
110     if (op_type == MTS_READ)
111     *data = d->intr_enable;
112     else
113     d->intr_enable = *data;
114     break;
115    
116     /*
117     * Read when a Network Interrupt is triggered.
118     * Bit 0: EOBC
119     * Bit 1: IBC
120     */
121     case 0x18:
122     case 0x1b:
123     if (op_type == MTS_READ)
124     *data = d->irq_status;
125     break;
126    
127     #if DEBUG_UNKNOWN
128     default:
129     if (op_type == MTS_READ) {
130     cpu_log(cpu,"MP_FPGA","read from unknown addr 0x%x, pc=0x%llx\n",
131     offset,cpu_get_pc(cpu));
132     } else {
133     cpu_log(cpu,"MP_FPGA","write to unknown addr 0x%x, value=0x%llx, "
134     "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu));
135     }
136     #endif
137     }
138    
139     return NULL;
140     }
141    
142     /* Shutdown the MP FPGA device */
143     static void
144     dev_c6msfc1_mpfpga_shutdown(vm_instance_t *vm,struct c6msfc1_mpfpga_data *d)
145     {
146     if (d != NULL) {
147     /* Remove the device */
148     dev_remove(vm,&d->dev);
149    
150     /* Free the structure itself */
151     free(d);
152     }
153     }
154    
155     /*
156     * dev_c6msfc1_mpfpga_init()
157     */
158     int dev_c6msfc1_mpfpga_init(c6msfc1_t *router,m_uint64_t paddr,m_uint32_t len)
159     {
160     struct c6msfc1_mpfpga_data *d;
161    
162     /* Allocate private data structure */
163     if (!(d = malloc(sizeof(*d)))) {
164     fprintf(stderr,"MP_FPGA: out of memory\n");
165     return(-1);
166     }
167    
168     memset(d,0,sizeof(*d));
169     d->router = router;
170    
171     vm_object_init(&d->vm_obj);
172     d->vm_obj.name = "mp_fpga";
173     d->vm_obj.data = d;
174     d->vm_obj.shutdown = (vm_shutdown_t)dev_c6msfc1_mpfpga_shutdown;
175    
176     /* Set device properties */
177     dev_init(&d->dev);
178     d->dev.name = "mp_fpga";
179     d->dev.phys_addr = paddr;
180     d->dev.phys_len = len;
181     d->dev.handler = dev_c6msfc1_mpfpga_access;
182     d->dev.priv_data = d;
183    
184     /* Map this device to the VM */
185     vm_bind_device(router->vm,&d->dev);
186     vm_object_add(router->vm,&d->vm_obj);
187     return(0);
188     }

  ViewVC Help
Powered by ViewVC 1.1.26