/[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

Contents of /trunk/dev_c3745_iofpga.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 /*
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 #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_c3745.h"
24
25 /* Debugging flags */
26 #define DEBUG_UNKNOWN 1
27 #define DEBUG_ACCESS 0
28 #define DEBUG_NET_IRQ 0
29
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 /* Network IRQ distribution */
55 struct net_irq_distrib {
56 u_int reg;
57 u_int offset;
58 };
59
60 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 /* IO FPGA structure */
69 struct c3745_iofpga_data {
70 vm_obj_t vm_obj;
71 struct vdevice dev;
72 c3745_t *router;
73
74 /* Network IRQ status */
75 m_uint16_t net_irq_status[2];
76
77 /* Interrupt mask */
78 m_uint16_t intr_mask,io_mask2;
79
80 /* EEPROM select */
81 u_int eeprom_select;
82
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 };
89
90 /* Motherboard EEPROM definition */
91 static const struct nmc93cX6_eeprom_def eeprom_mb_def = {
92 EEPROM_MB_CLK, EEPROM_MB_CS,
93 EEPROM_MB_DIN, EEPROM_MB_DOUT,
94 };
95
96 /* I/O board EEPROM definition */
97 static const struct nmc93cX6_eeprom_def eeprom_io_def = {
98 EEPROM_IO_CLK, EEPROM_IO_CS,
99 EEPROM_IO_DIN, EEPROM_IO_DOUT,
100 };
101
102 /* Midplane EEPROM definition */
103 static const struct nmc93cX6_eeprom_def eeprom_mp_def = {
104 EEPROM_MP_CLK, EEPROM_MP_CS,
105 EEPROM_MP_DIN, EEPROM_MP_DOUT,
106 };
107
108 /* System EEPROM group */
109 static const struct nmc93cX6_group eeprom_sys_group = {
110 EEPROM_TYPE_NMC93C46, 3, 0,
111 EEPROM_DORD_NORMAL,
112 EEPROM_DOUT_HIGH,
113 EEPROM_DEBUG_DISABLED,
114 "System EEPROM",
115 { &eeprom_mb_def, &eeprom_io_def, &eeprom_mp_def },
116 };
117
118 /* NM EEPROM definition */
119 static const struct nmc93cX6_eeprom_def eeprom_nm_def = {
120 EEPROM_NM_CLK, EEPROM_NM_CS,
121 EEPROM_NM_DIN, EEPROM_NM_DOUT,
122 };
123
124 /* NM EEPROM */
125 static const struct nmc93cX6_group eeprom_nm_group = {
126 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 };
133
134 /* 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 /* 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 /*
210 * dev_c3745_iofpga_access()
211 */
212 static void *
213 dev_c3745_iofpga_access(cpu_gen_t *cpu,struct vdevice *dev,
214 m_uint32_t offset,u_int op_size,u_int op_type,
215 m_uint64_t *data)
216 {
217 struct c3745_iofpga_data *d = dev->priv_data;
218 u_int slot;
219
220 if (op_type == MTS_READ)
221 *data = 0x0;
222
223 #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 offset,cpu_get_pc(cpu),op_size);
227 } else {
228 cpu_log(cpu,"IO_FPGA",
229 "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",
230 offset,cpu_get_pc(cpu),*data,op_size);
231 }
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 nmc93cX6_write(&d->router->sys_eeprom_group,(u_int)(*data));
289 else
290 *data = nmc93cX6_read(&d->router->sys_eeprom_group);
291 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 *data = d->net_irq_status[0];
303 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 *data = d->net_irq_status[1];
316 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 nmc93cX6_write(&d->router->nm_eeprom_group[slot],(u_int)(*data));
346 else
347 *data = nmc93cX6_read(&d->router->nm_eeprom_group[slot]);
348 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 if (vm_slot_get_card_ptr(d->router->vm,1))
375 *data &= ~0x0100;
376
377 if (vm_slot_get_card_ptr(d->router->vm,2))
378 *data &= ~0x0001;
379
380 if (vm_slot_get_card_ptr(d->router->vm,3))
381 *data &= ~0x1000;
382
383 if (vm_slot_get_card_ptr(d->router->vm,4))
384 *data &= ~0x0010;
385 }
386 break;
387
388 /*
389 * VWIC/WIC related
390 * Bits 0-2: WIC presence
391 */
392 case 0x100004:
393 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 case 0x100006:
413 if (op_type == MTS_READ)
414 *data = 0x0004;
415 break;
416
417 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 #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 offset,cpu_get_pc(cpu),op_size);
448 } else {
449 cpu_log(cpu,"IO_FPGA",
450 "write to unknown addr 0x%x, value=0x%llx, "
451 "pc=0x%llx (size=%u)\n",
452 offset,*data,cpu_get_pc(cpu),op_size);
453 }
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 router->nm_eeprom_group[i-1].eeprom[0] = NULL;
478 }
479 }
480
481 /* Shutdown the IO FPGA device */
482 static void
483 dev_c3745_iofpga_shutdown(vm_instance_t *vm,struct c3745_iofpga_data *d)
484 {
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 struct c3745_iofpga_data *d;
501
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 d->net_irq_status[0] = 0xFFFF;
511 d->net_irq_status[1] = 0xFFFF;
512
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