/[dynamips]/trunk/dev_c1700_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_c1700_iofpga.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 13 - (hide annotations)
Fri Oct 12 09:40:41 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 7647 byte(s)
boot linux kernel from DSM G600
1 dpavlin 11 /*
2     * Cisco router 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     #include "cpu.h"
17     #include "vm.h"
18     #include "dynamips.h"
19     #include "memory.h"
20     #include "device.h"
21     #include "dev_vtty.h"
22     #include "nmc93cX6.h"
23     #include "dev_mpc860.h"
24     #include "dev_c1700.h"
25    
26     /* Debugging flags */
27     #define DEBUG_UNKNOWN 1
28 dpavlin 13 #define DEBUG_ACCESS 1
29     #define DEBUG_WIC 1
30     #define DEBUG_NET_IRQ 1
31 dpavlin 11
32     /* Definitions for Mainboard EEPROM */
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     /* Network IRQ distribution */
39     static u_int net_irq_dist[C1700_MAX_NM_BAYS] = {
40     0, /* XXX: required/does exist ??? */
41     };
42    
43     /* IO FPGA structure */
44     struct c1700_iofpga_data {
45     vm_obj_t vm_obj;
46     struct vdevice dev;
47     c1700_t *router;
48    
49     /* Network Interrupt status */
50     m_uint8_t net_irq_status;
51    
52     /* Interrupt mask */
53     m_uint16_t intr_mask;
54    
55     /* WIC SPI selection */
56     m_uint8_t wic_select;
57     };
58    
59     /* Mainboard EEPROM definition */
60     static const struct nmc93cX6_eeprom_def eeprom_mb_def = {
61     EEPROM_MB_CLK, EEPROM_MB_CS,
62     EEPROM_MB_DIN, EEPROM_MB_DOUT,
63     };
64    
65     /* Mainboard EEPROM */
66     static const struct nmc93cX6_group eeprom_mb_group = {
67     EEPROM_TYPE_NMC93C46, 1, 0,
68     EEPROM_DORD_NORMAL,
69     EEPROM_DOUT_HIGH,
70     EEPROM_DEBUG_DISABLED,
71     "Mainboard EEPROM",
72     { &eeprom_mb_def },
73     };
74    
75     /* Update network interrupt status */
76     static inline void dev_c1700_iofpga_net_update_irq(struct c1700_iofpga_data *d)
77     {
78     if (d->net_irq_status) {
79     vm_set_irq(d->router->vm,C1700_NETIO_IRQ);
80     } else {
81     vm_clear_irq(d->router->vm,C1700_NETIO_IRQ);
82     }
83     }
84    
85     /* Trigger a Network IRQ for the specified slot/port */
86     void dev_c1700_iofpga_net_set_irq(struct c1700_iofpga_data *d,
87     u_int slot,u_int port)
88     {
89     #if DEBUG_NET_IRQ
90     vm_log(d->router->vm,"IO_FPGA","setting NetIRQ for slot %u port %u\n",
91     slot,port);
92     #endif
93     d->net_irq_status |= 1 << (net_irq_dist[slot] + port);
94     dev_c1700_iofpga_net_update_irq(d);
95     }
96    
97     /* Clear a Network IRQ for the specified slot/port */
98     void dev_c1700_iofpga_net_clear_irq(struct c1700_iofpga_data *d,
99     u_int slot,u_int port)
100     {
101     #if DEBUG_NET_IRQ
102     vm_log(d->router->vm,"IO_FPGA","clearing NetIRQ for slot %u port %u\n",
103     slot,port);
104     #endif
105     d->net_irq_status &= ~(1 << (net_irq_dist[slot] + port));
106     dev_c1700_iofpga_net_update_irq(d);
107     }
108    
109     /* Callback for MPC860 SPI Transmit */
110     static void dev_c1700_mpc860_spi_tx_callback(struct mpc860_data *mpc_data,
111     u_char *buffer,u_int len,
112     void *user_arg)
113     {
114     struct c1700_iofpga_data *d = user_arg;
115     struct cisco_eeprom *eeprom;
116     u_char reply_buf[4];
117     u_int wic_port;
118     u_int eeprom_offset;
119    
120     if (d->wic_select & 0x20)
121     wic_port = 0x10;
122     else if (d->wic_select & 0x08)
123     wic_port = 0x20;
124     else {
125     #if DEBUG_WIC
126     vm_error(d->router->vm,"unknown value for wic_select (0x%8.8x)\n",
127     d->wic_select);
128     #endif
129     wic_port = 0;
130     }
131    
132     /* No WIC in slot or no EEPROM: fake an empty EEPROM */
133     if (!wic_port || !(eeprom = vm_slot_get_eeprom(d->router->vm,0,wic_port))) {
134     memset(reply_buf,0xFF,sizeof(reply_buf));
135     mpc860_spi_receive(mpc_data,reply_buf,sizeof(reply_buf));
136     return;
137     }
138    
139     /* Read request: 0x03 offset 0x00 0x00 */
140     eeprom_offset = buffer[1];
141    
142     reply_buf[0] = 0;
143     reply_buf[1] = 0;
144     cisco_eeprom_get_byte(eeprom,eeprom_offset,&reply_buf[2]);
145     cisco_eeprom_get_byte(eeprom,eeprom_offset+1,&reply_buf[3]);
146    
147     mpc860_spi_receive(mpc_data,reply_buf,sizeof(reply_buf));
148     }
149    
150     /*
151     * dev_c1700_iofpga_access()
152     */
153     static void *
154     dev_c1700_iofpga_access(cpu_gen_t *cpu,struct vdevice *dev,
155     m_uint32_t offset,u_int op_size,u_int op_type,
156     m_uint64_t *data)
157     {
158     struct c1700_iofpga_data *d = dev->priv_data;
159    
160     if (op_type == MTS_READ)
161     *data = 0x0;
162    
163     #if DEBUG_ACCESS
164     if (op_type == MTS_READ) {
165     cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",
166     offset,cpu_get_pc(cpu),op_size);
167     } else {
168     cpu_log(cpu,"IO_FPGA",
169     "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",
170     offset,cpu_get_pc(cpu),*data,op_size);
171     }
172     #endif
173    
174     switch(offset) {
175     /* Unknown */
176     case 0x04:
177     break;
178    
179     /*
180     * Bit 1: card present in slot 0 / WIC 0.
181     * Bit 2: card present in slot 0 / WIC 1.
182     * Bit 3: compression/VPN module ? (mention of "slot 3")
183     * Other bits unknown.
184     */
185     case 0x10:
186     if (op_type == MTS_READ) {
187     *data = 0;
188    
189     /* check WIC 0 */
190     if (vm_slot_check_eeprom(d->router->vm,0,0x10))
191     *data |= 0x02;
192    
193     /* check WIC 1 */
194     if (vm_slot_check_eeprom(d->router->vm,0,0x20))
195     *data |= 0x04;
196     }
197     break;
198    
199     /* WIC card selection for EEPROM reading */
200     case 0x18:
201     if (op_type == MTS_READ)
202     *data = d->wic_select;
203     else {
204     d->wic_select = *data;
205     }
206     break;
207    
208     /* Unknown, read on 1760 */
209     case 0x4c:
210     if (op_type == MTS_READ)
211     *data = 0xFF;
212     break;
213    
214     #if DEBUG_UNKNOWN
215     default:
216     if (op_type == MTS_READ) {
217     cpu_log(cpu,"IO_FPGA",
218     "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
219     offset,cpu_get_pc(cpu),op_size);
220     } else {
221     cpu_log(cpu,"IO_FPGA",
222     "write to unknown addr 0x%x, value=0x%llx, "
223     "pc=0x%llx (size=%u)\n",
224     offset,*data,cpu_get_pc(cpu),op_size);
225     }
226     #endif
227     }
228    
229     return NULL;
230     }
231    
232     /* Shutdown the IO FPGA device */
233     static void
234     dev_c1700_iofpga_shutdown(vm_instance_t *vm,struct c1700_iofpga_data *d)
235     {
236     if (d != NULL) {
237     /* Remove the device */
238     dev_remove(vm,&d->dev);
239    
240     /* Free the structure itself */
241     free(d);
242     }
243     }
244    
245     /*
246     * dev_c1700_iofpga_init()
247     */
248     int dev_c1700_iofpga_init(c1700_t *router,m_uint64_t paddr,m_uint32_t len)
249     {
250     vm_instance_t *vm = router->vm;
251     struct c1700_iofpga_data *d;
252    
253     /* Allocate private data structure */
254     if (!(d = malloc(sizeof(*d)))) {
255     fprintf(stderr,"IO_FPGA: out of memory\n");
256     return(-1);
257     }
258    
259     memset(d,0,sizeof(*d));
260     d->router = router;
261    
262     vm_object_init(&d->vm_obj);
263     d->vm_obj.name = "io_fpga";
264     d->vm_obj.data = d;
265     d->vm_obj.shutdown = (vm_shutdown_t)dev_c1700_iofpga_shutdown;
266    
267     /* Set device properties */
268     dev_init(&d->dev);
269     d->dev.name = "io_fpga";
270     d->dev.phys_addr = paddr;
271     d->dev.phys_len = len;
272     d->dev.priv_data = d;
273     d->dev.handler = dev_c1700_iofpga_access;
274    
275     /* Initialize the MPC860 SPI TX callback to read mainboard WIC EEPROMs */
276     mpc860_spi_set_tx_callback(router->mpc_data,
277     dev_c1700_mpc860_spi_tx_callback,d);
278    
279     /* Map this device to the VM */
280     vm_bind_device(router->vm,&d->dev);
281     vm_object_add(vm,&d->vm_obj);
282     return(0);
283     }
284    
285     /* Initialize EEPROM groups */
286     void c1700_init_eeprom_groups(c1700_t *router)
287     {
288     /* Initialize Mainboard EEPROM */
289     router->mb_eeprom_group = eeprom_mb_group;
290     router->mb_eeprom_group.eeprom[0] = &router->mb_eeprom;
291     router->mb_eeprom.data = NULL;
292     router->mb_eeprom.len = 0;
293     }

  ViewVC Help
Powered by ViewVC 1.1.26