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

Contents of /trunk/dev_c3725_iofpga.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 /*
2 * Cisco 3725 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 #include "cpu.h"
19 #include "vm.h"
20 #include "dynamips.h"
21 #include "memory.h"
22 #include "device.h"
23 #include "dev_vtty.h"
24 #include "nmc93cX6.h"
25 #include "dev_c3725.h"
26
27 /* Debugging flags */
28 #define DEBUG_UNKNOWN 1
29 #define DEBUG_ACCESS 0
30 #define DEBUG_NET_IRQ 0
31
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 /* Definitions for Network Modules EEPROM */
39 #define EEPROM_NM_DOUT 7
40 #define EEPROM_NM_DIN 6
41 #define EEPROM_NM_CLK 2
42 #define EEPROM_NM_CS 4
43
44 /* Network IRQ distribution */
45 struct net_irq_distrib {
46 u_int reg;
47 u_int offset;
48 };
49
50 static struct net_irq_distrib net_irq_dist[C3725_MAX_NM_BAYS] = {
51 { 0, 0 }, /* Slot 0: reg 0x26, 0x000000XX */
52 { 1, 0 }, /* Slot 1: reg 0x28, 0x0000000X */
53 { 1, 4 }, /* Slot 2: reg 0x28, 0x000000X0 */
54 };
55
56 /* IO FPGA structure */
57 struct c3725_iofpga_data {
58 vm_obj_t vm_obj;
59 struct vdevice dev;
60 c3725_t *router;
61
62 /* Network IRQ status */
63 m_uint16_t net_irq_status[2];
64
65 /* Interrupt mask */
66 m_uint16_t intr_mask;
67
68 /* WIC select */
69 u_int wic_select;
70 u_int wic_cmd_pos;
71 u_int wic_cmd_valid;
72 m_uint16_t wic_cmd[2];
73 };
74
75 /* Mainboard EEPROM definition */
76 static const struct nmc93cX6_eeprom_def eeprom_mb_def = {
77 EEPROM_MB_CLK, EEPROM_MB_CS,
78 EEPROM_MB_DIN, EEPROM_MB_DOUT,
79 };
80
81 /* Mainboard EEPROM */
82 static const struct nmc93cX6_group eeprom_mb_group = {
83 EEPROM_TYPE_NMC93C46, 1, 0,
84 EEPROM_DORD_NORMAL,
85 EEPROM_DOUT_HIGH,
86 EEPROM_DEBUG_DISABLED,
87 "Mainboard EEPROM",
88 { &eeprom_mb_def },
89 };
90
91 /* NM EEPROM definition */
92 static const struct nmc93cX6_eeprom_def eeprom_nm_def = {
93 EEPROM_NM_CLK, EEPROM_NM_CS,
94 EEPROM_NM_DIN, EEPROM_NM_DOUT,
95 };
96
97 /* NM EEPROM */
98 static const struct nmc93cX6_group eeprom_nm_group = {
99 EEPROM_TYPE_NMC93C46, 1, 0,
100 EEPROM_DORD_NORMAL,
101 EEPROM_DOUT_HIGH,
102 EEPROM_DEBUG_DISABLED,
103 "NM EEPROM",
104 { &eeprom_nm_def },
105 };
106
107 /* Update network interrupt status */
108 static inline void dev_c3725_iofpga_net_update_irq(struct c3725_iofpga_data *d)
109 {
110 if ((d->net_irq_status[0] != 0xFFFF) || (d->net_irq_status[1] != 0xFFFF)) {
111 vm_set_irq(d->router->vm,C3725_NETIO_IRQ);
112 } else {
113 vm_clear_irq(d->router->vm,C3725_NETIO_IRQ);
114 }
115 }
116
117 /* Trigger a Network IRQ for the specified slot/port */
118 void dev_c3725_iofpga_net_set_irq(struct c3725_iofpga_data *d,
119 u_int slot,u_int port)
120 {
121 struct net_irq_distrib *irq_dist;
122
123 #if DEBUG_NET_IRQ
124 vm_log(d->router->vm,"IO_FPGA","setting NetIRQ for slot %u port %u\n",
125 slot,port);
126 #endif
127 irq_dist = &net_irq_dist[slot];
128 d->net_irq_status[irq_dist->reg] &= ~(1 << (irq_dist->offset + port));
129 dev_c3725_iofpga_net_update_irq(d);
130 }
131
132 /* Clear a Network IRQ for the specified slot/port */
133 void dev_c3725_iofpga_net_clear_irq(struct c3725_iofpga_data *d,
134 u_int slot,u_int port)
135 {
136 struct net_irq_distrib *irq_dist;
137
138 #if DEBUG_NET_IRQ
139 vm_log(d->router->vm,"IO_FPGA","clearing NetIRQ for slot %u port %u\n",
140 slot,port);
141 #endif
142 irq_dist = &net_irq_dist[slot];
143 d->net_irq_status[irq_dist->reg] |= (1 << (irq_dist->offset + port));
144 dev_c3725_iofpga_net_update_irq(d);
145 }
146
147 /* Read a WIC EEPROM */
148 static m_uint16_t dev_c3725_read_wic_eeprom(struct c3725_iofpga_data *d)
149 {
150 struct cisco_eeprom *eeprom;
151 u_int wic_port;
152 u_int eeprom_offset;
153 m_uint8_t val[2];
154
155 switch(d->wic_select) {
156 case 0x1700:
157 wic_port = 0x10;
158 break;
159 case 0x1D00:
160 wic_port = 0x20;
161 break;
162 case 0x3500:
163 wic_port = 0x30;
164 break;
165 default:
166 wic_port = 0;
167 }
168
169 /* No WIC in slot or no EEPROM: fake an empty EEPROM */
170 if (!wic_port || !(eeprom = vm_slot_get_eeprom(d->router->vm,0,wic_port)))
171 return(0xFFFF);
172
173 /* EEPROM offset is in the lowest 6 bits */
174 eeprom_offset = d->wic_cmd[0] & 0x3F;
175
176 cisco_eeprom_get_byte(eeprom,eeprom_offset,&val[0]);
177 cisco_eeprom_get_byte(eeprom,eeprom_offset+1,&val[1]);
178
179 return(((m_uint16_t)val[0] << 8) | val[1]);
180 }
181
182 /*
183 * dev_c3725_iofpga_access()
184 */
185 static void *
186 dev_c3725_iofpga_access(cpu_gen_t *cpu,struct vdevice *dev,
187 m_uint32_t offset,u_int op_size,u_int op_type,
188 m_uint64_t *data)
189 {
190 struct c3725_iofpga_data *d = dev->priv_data;
191
192 if (op_type == MTS_READ)
193 *data = 0x0;
194
195 #if DEBUG_ACCESS
196 if (op_type == MTS_READ) {
197 cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",
198 offset,cpu_get_pc(cpu),op_size);
199 } else {
200 cpu_log(cpu,"IO_FPGA",
201 "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",
202 offset,cpu_get_pc(cpu),*data,op_size);
203 }
204 #endif
205
206 switch(offset) {
207 /*
208 * Platform type ?
209 * 0x04 and 0x05 seem to work.
210 */
211 case 0x36:
212 if (op_type == MTS_READ)
213 *data = 0x04 << 5;
214 break;
215
216 /* Mainboard EEPROM */
217 case 0x0e:
218 if (op_type == MTS_WRITE)
219 nmc93cX6_write(&d->router->mb_eeprom_group,(u_int)(*data));
220 else
221 *data = nmc93cX6_read(&d->router->mb_eeprom_group);
222 break;
223
224 case 0x12:
225 /*
226 * Bit 0: 1=No WIC in slot 0.
227 * Bit 1: 1=No WIC in slot 1.
228 * Bit 2: 1=No WIC in slot 2.
229 */
230 if (op_type == MTS_READ) {
231 *data = 0xFFFF;
232
233 /* check WIC 0 */
234 if (vm_slot_check_eeprom(d->router->vm,0,0x10))
235 *data &= ~0x01;
236
237 /* check WIC 1 */
238 if (vm_slot_check_eeprom(d->router->vm,0,0x20))
239 *data &= ~0x02;
240
241 /* check WIC 2 */
242 if (vm_slot_check_eeprom(d->router->vm,0,0x30))
243 *data &= ~0x04;
244 } else {
245 d->wic_select = *data;
246 }
247 break;
248
249 case 0x14:
250 if (op_type == MTS_READ)
251 *data = 0xFFFF;
252 break;
253
254 case 0x18:
255 if (op_type == MTS_READ)
256 *data = 0xFFFF;
257 break;
258
259 /* wic/vwic related */
260 case 0x40:
261 if (op_type == MTS_READ)
262 *data = 0x0004;
263 break;
264
265 /* WIC related: 16-bit data */
266 case 0x42:
267 if (op_type == MTS_READ) {
268 if (d->wic_cmd_valid) {
269 *data = dev_c3725_read_wic_eeprom(d);
270 d->wic_cmd_valid = FALSE;
271 } else {
272 *data = 0xFFFF;
273 }
274 } else {
275 /*
276 * Store the EEPROM command (in 2 words).
277 *
278 * For a read, we have:
279 * Word 0: 0x180 (nmc93c46 READ) + offset (6-bits).
280 * Word 1: 0 (no data).
281 */
282 d->wic_cmd[d->wic_cmd_pos++] = *data;
283
284 if (d->wic_cmd_pos == 2) {
285 d->wic_cmd_pos = 0;
286 d->wic_cmd_valid = TRUE;
287 }
288 }
289 break;
290
291 /* NM Slot 1 EEPROM */
292 case 0x44:
293 if (op_type == MTS_WRITE)
294 nmc93cX6_write(&d->router->nm_eeprom_group[0],(u_int)(*data));
295 else
296 *data = nmc93cX6_read(&d->router->nm_eeprom_group[0]);
297 break;
298
299 /* NM Slot 2 EEPROM */
300 case 0x46:
301 if (op_type == MTS_WRITE)
302 nmc93cX6_write(&d->router->nm_eeprom_group[1],(u_int)(*data));
303 else
304 *data = nmc93cX6_read(&d->router->nm_eeprom_group[1]);
305 break;
306
307 /* AIM EEPROM #0 */
308 case 0x48:
309 if (op_type == MTS_READ)
310 *data = 0xFFFF;
311 break;
312
313 /* AIM EEPROM #1 */
314 case 0x4a:
315 if (op_type == MTS_READ)
316 *data = 0xFFFF;
317 break;
318
319 /*
320 * NM Presence.
321 *
322 * Bit 7: 0=NM present in slot 1.
323 * Bit 11: 0=NM present in slot 2.
324 * Other bits unknown.
325 */
326 case 0x20:
327 if (op_type == MTS_READ) {
328 *data = 0xFFFF;
329
330 if (vm_slot_get_card_ptr(d->router->vm,1))
331 *data &= ~0x0008;
332
333 if (vm_slot_get_card_ptr(d->router->vm,2))
334 *data &= ~0x0800;
335 }
336 break;
337
338 /* ??? */
339 case 0x24:
340 break;
341
342 /* Intr Mask (sh platform) */
343 case 0x30:
344 if (op_type == MTS_READ)
345 *data = d->intr_mask;
346 else
347 d->intr_mask = *data;
348 break;
349
350 /*
351 * Network interrupt status.
352 *
353 * Bit 0: 0 = GT96100 Ethernet ports.
354 * Other bits unknown.
355 */
356 case 0x26:
357 if (op_type == MTS_READ)
358 *data = d->net_irq_status[0];
359 break;
360
361 /*
362 * Network interrupt status.
363 *
364 * Bit 0: 0 = NM in Slot 1.
365 * Bit 8: 0 = NM in Slot 2.
366 * Other bits unknown.
367 */
368 case 0x28:
369 if (op_type == MTS_READ)
370 *data = d->net_irq_status[1];
371 break;
372
373 case 0x2c:
374 if (op_type == MTS_READ)
375 *data = 0xFFFF;
376 break;
377
378 /* OIR interrupt but not supported (IRQ 6) */
379 case 0x2e:
380 if (op_type == MTS_READ)
381 *data = 0xFFFF;
382 break;
383
384 /*
385 * Environmental monitor, determined with "sh env all".
386 *
387 * Bit 0: 1 = Fan Error
388 * Bit 1: 1 = Fan Error
389 * Bit 2: 1 = Over-temperature
390 * Bit 3: ???
391 * Bit 4: 0 = RPS present.
392 * Bit 5: 0 = Input Voltage status failure.
393 * Bit 6: 1 = Thermal status failure.
394 * Bit 7: 1 = DC Output Voltage status failure.
395 */
396 case 0x3a:
397 if (op_type == MTS_READ)
398 *data = 0x0020;
399 break;
400
401 /*
402 * Bit 0: Slot0 Compact Flash presence.
403 * Bit 1: System Compact Flash presence.
404 */
405 case 0x3c:
406 if (op_type == MTS_READ) {
407 *data = 0xFFFF;
408
409 /* System Flash ? */
410 if (cpu->vm->pcmcia_disk_size[0])
411 *data &= ~0x02;
412
413 /* Slot0 Flash ? */
414 if (cpu->vm->pcmcia_disk_size[1])
415 *data &= ~0x01;
416 }
417 break;
418
419 #if DEBUG_UNKNOWN
420 default:
421 if (op_type == MTS_READ) {
422 cpu_log(cpu,"IO_FPGA",
423 "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
424 offset,cpu_get_pc(cpu),op_size);
425 } else {
426 cpu_log(cpu,"IO_FPGA",
427 "write to unknown addr 0x%x, value=0x%llx, "
428 "pc=0x%llx (size=%u)\n",
429 offset,*data,cpu_get_pc(cpu),op_size);
430 }
431 #endif
432 }
433
434 return NULL;
435 }
436
437 /* Initialize EEPROM groups */
438 void c3725_init_eeprom_groups(c3725_t *router)
439 {
440 /* Initialize Mainboard EEPROM */
441 router->mb_eeprom_group = eeprom_mb_group;
442 router->mb_eeprom_group.eeprom[0] = &router->mb_eeprom;
443 router->mb_eeprom.data = NULL;
444 router->mb_eeprom.len = 0;
445
446 /* EEPROM for NM slot 1 */
447 router->nm_eeprom_group[0] = eeprom_nm_group;
448 router->nm_eeprom_group[0].eeprom[0] = NULL;
449
450 /* EEPROM for NM slot 2 */
451 router->nm_eeprom_group[1] = eeprom_nm_group;
452 router->nm_eeprom_group[1].eeprom[0] = NULL;
453 }
454
455 /* Shutdown the IO FPGA device */
456 static void
457 dev_c3725_iofpga_shutdown(vm_instance_t *vm,struct c3725_iofpga_data *d)
458 {
459 if (d != NULL) {
460 /* Remove the device */
461 dev_remove(vm,&d->dev);
462
463 /* Free the structure itself */
464 free(d);
465 }
466 }
467
468 /*
469 * dev_c3725_iofpga_init()
470 */
471 int dev_c3725_iofpga_init(c3725_t *router,m_uint64_t paddr,m_uint32_t len)
472 {
473 vm_instance_t *vm = router->vm;
474 struct c3725_iofpga_data *d;
475
476 /* Allocate private data structure */
477 if (!(d = malloc(sizeof(*d)))) {
478 fprintf(stderr,"IO_FPGA: out of memory\n");
479 return(-1);
480 }
481
482 memset(d,0,sizeof(*d));
483 d->router = router;
484 d->net_irq_status[0] = 0xFFFF;
485 d->net_irq_status[1] = 0xFFFF;
486
487 vm_object_init(&d->vm_obj);
488 d->vm_obj.name = "io_fpga";
489 d->vm_obj.data = d;
490 d->vm_obj.shutdown = (vm_shutdown_t)dev_c3725_iofpga_shutdown;
491
492 /* Set device properties */
493 dev_init(&d->dev);
494 d->dev.name = "io_fpga";
495 d->dev.phys_addr = paddr;
496 d->dev.phys_len = len;
497 d->dev.priv_data = d;
498 d->dev.handler = dev_c3725_iofpga_access;
499
500 /* Map this device to the VM */
501 vm_bind_device(router->vm,&d->dev);
502 vm_object_add(vm,&d->vm_obj);
503 return(0);
504 }

  ViewVC Help
Powered by ViewVC 1.1.26