/[dynamips]/upstream/dynamips-0.2.6-RC1/dev_c3600_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 /upstream/dynamips-0.2.6-RC1/dev_c3600_iofpga.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Sat Oct 6 16:01:44 2007 UTC (12 years, 2 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.5/dev_c3600_iofpga.c
File MIME type: text/plain
File size: 17455 byte(s)
import 0.2.5 from upstream

1 /*
2 * Cisco 3600 simulation platform.
3 * Copyright (c) 2006 Christophe Fillot (cf@utc.fr)
4 *
5 * TODO: Online Insertion/Removal (OIR).
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 "mips64.h"
19 #include "dynamips.h"
20 #include "memory.h"
21 #include "device.h"
22 #include "dev_vtty.h"
23 #include "nmc93c46.h"
24 #include "dev_c3600.h"
25
26 /* Debugging flags */
27 #define DEBUG_UNKNOWN 1
28 #define DEBUG_ACCESS 0
29
30 /* Definitions for Mainboard EEPROM */
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 Network Modules EEPROM */
37 #define EEPROM_NM_DOUT 7
38 #define EEPROM_NM_DIN 6
39 #define EEPROM_NM_CLK 2
40 #define EEPROM_NM_CS 4
41
42 /* IO FPGA structure */
43 struct iofpga_data {
44 vm_obj_t vm_obj;
45 struct vdevice dev;
46 c3600_t *router;
47
48 /* Slot select for EEPROM access */
49 u_int eeprom_slot;
50
51 /* IO Mask. Don't know the meaning */
52 m_uint8_t io_mask;
53
54 m_uint16_t sel;
55 };
56
57 /* Mainboard EEPROM definition */
58 static const struct nmc93c46_eeprom_def eeprom_mb_def = {
59 EEPROM_MB_CLK, EEPROM_MB_CS,
60 EEPROM_MB_DIN, EEPROM_MB_DOUT,
61 NULL, 0,
62 };
63
64 /* Mainboard EEPROM */
65 static const struct nmc93c46_group eeprom_mb_group = {
66 1, 0, "Mainboard EEPROM", 0, { NULL }, { { 0, 0, 0, 0, 0} },
67 };
68
69 /* NM EEPROM definition */
70 static const struct nmc93c46_eeprom_def eeprom_nm_def = {
71 EEPROM_NM_CLK, EEPROM_NM_CS,
72 EEPROM_NM_DIN, EEPROM_NM_DOUT,
73 NULL, 0,
74 };
75
76 /* NM EEPROM */
77 static const struct nmc93c46_group eeprom_nm_group = {
78 1, 0, "NM EEPROM", 0, { NULL }, { { 0, 0, 0, 0, 0} },
79 };
80
81 /* C3660 NM presence masks */
82 static const m_uint16_t c3660_nm_masks[6] = {
83 0xF0FF, /* slot 1 */
84 0xFFF0, /* slot 2 */
85 0x0FFF, /* slot 3 */
86 0xFF0F, /* slot 4 */
87 0xF0FF, /* slot 5 */
88 0xFFF0, /* slot 6 */
89 };
90
91 /* Select the current NM EEPROM */
92 static void nm_eeprom_select(struct iofpga_data *d,u_int slot)
93 {
94 d->router->nm_eeprom.data = d->router->nm_bay[slot].eeprom_data;
95 d->router->nm_eeprom.data_len = d->router->nm_bay[slot].eeprom_data_len;
96 }
97
98 /* Return the NM status register given the detected EEPROM (3620/3640) */
99 static u_int nm_get_status_1(struct iofpga_data *d)
100 {
101 u_int res = 0xFFFF;
102 int i;
103
104 for(i=0;i<4;i++) {
105 if (c3600_nm_check_eeprom(d->router,i))
106 res &= ~(0x1111 << i);
107 }
108
109 return(res);
110 }
111
112 /* Return the NM status register given the detected EEPROM (3660) */
113 static u_int nm_get_status_2(struct iofpga_data *d,u_int pos)
114 {
115 u_int res = 0xFFFF;
116 u_int start,end;
117 int i;
118
119 switch(pos) {
120 case 0: /* word 0: slot 1 - 4 */
121 start = 1;
122 end = 4;
123 break;
124 case 1: /* word 1: slot 5 - 6 */
125 start = 5;
126 end = 6;
127 break;
128 default:
129 return(res);
130 }
131
132 for(i=start;i<=end;i++) {
133 if (c3600_nm_check_eeprom(d->router,i))
134 res &= c3660_nm_masks[i-1];
135 }
136
137 return(res);
138 }
139
140 /*
141 * dev_c3620_c3640_iofpga_access()
142 */
143 static void *
144 dev_c3620_c3640_iofpga_access(cpu_mips_t *cpu,struct vdevice *dev,
145 m_uint32_t offset,u_int op_size,u_int op_type,
146 m_uint64_t *data)
147 {
148 struct iofpga_data *d = dev->priv_data;
149 u_int slot;
150
151 if (op_type == MTS_READ)
152 *data = 0x0;
153
154 #if DEBUG_ACCESS
155 if (offset != 0x0c) {
156 if (op_type == MTS_READ) {
157 cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",
158 offset,cpu->pc,op_size);
159 } else {
160 cpu_log(cpu,"IO_FPGA",
161 "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",
162 offset,cpu->pc,*data,op_size);
163 }
164 }
165 #endif
166
167 switch(offset) {
168 /* Probably flash protection (if 0, no write access allowed) */
169 case 0x00008:
170 if (op_type == MTS_READ)
171 *data = 0xFF;
172 break;
173
174 /* Bootflash of 8 Mb */
175 case 0x0000a:
176 if (op_type == MTS_READ)
177 *data = 0x1000;
178 break;
179
180 /*
181 * 0x7d00 is written here regularly.
182 * Some kind of hardware watchdog ?
183 */
184 case 0x0000c:
185 break;
186
187 /* Mainboard EEPROM */
188 case 0x0000e:
189 if (op_type == MTS_WRITE)
190 nmc93c46_write(&d->router->mb_eeprom_group,(u_int)(*data));
191 else
192 *data = nmc93c46_read(&d->router->mb_eeprom_group);
193 break;
194
195 case 0x10004: /* ??? OIR control ??? */
196 if (op_type == MTS_READ) {
197 *data = 0x0000;
198 }
199 break;
200
201 /*
202 * Network modules presence.
203 *
204 * Bit 0: 0 = NM in slot 0 is valid
205 * Bit 1: 0 = NM in slot 1 is valid
206 * Bit 2: 0 = NM in slot 2 is valid
207 * Bit 3: 0 = NM in slot 3 is valid
208 *
209 * Very well explained on Cisco website:
210 * http://www.cisco.com/en/US/customer/products/hw/routers/ps274/products_tech_note09186a0080109510.shtml
211 */
212 case 0x10006:
213 if (op_type == MTS_READ)
214 *data = nm_get_status_1(d);
215 break;
216
217 /*
218 * NM EEPROMs.
219 */
220 case 0x10008:
221 if (op_type == MTS_WRITE) {
222 d->eeprom_slot = *data & 0x03;
223 nm_eeprom_select(d,d->eeprom_slot);
224 nmc93c46_write(&d->router->nm_eeprom_group,*data);
225 } else {
226 *data = nmc93c46_read(&d->router->nm_eeprom_group);
227 }
228 break;
229
230 /* Network interrupt status */
231 case 0x20000:
232 case 0x20001:
233 case 0x20002:
234 case 0x20003:
235 /* XXX Thisn't seem to be correct (at least on 3620) */
236 slot = offset - 0x20000;
237
238 if (op_type == MTS_READ)
239 *data = 0xFF;
240
241 vm_clear_irq(d->router->vm,C3600_NETIO_IRQ);
242 break;
243
244 /*
245 * Read when a PA Management interrupt is triggered.
246 *
247 * If not 0, we get:
248 * "Error: Unexpected NM Interrupt received from slot: x"
249 */
250 case 0x20004:
251 if (op_type == MTS_READ)
252 *data = 0x00;
253 vm_clear_irq(d->router->vm,C3600_NM_MGMT_IRQ);
254 break;
255
256 /*
257 * Read when an external interrupt is triggered.
258 *
259 * Bit 4: 1 = %UNKNOWN-1-GT64010: Unknown fatal interrupt(s)
260 * Bit 6: 1 = %OIRINT: OIR Event has occurred oir_ctrl 1000 oir_stat FFFF
261 *
262 * oir_ctrl = register 0x10004
263 * oir_stat = register 0x10006
264 */
265 case 0x20006:
266 if (op_type == MTS_READ)
267 *data = 0x00;
268 vm_clear_irq(d->router->vm,C3600_EXT_IRQ);
269 break;
270
271 /* IO Mask (displayed by "show c3600") */
272 case 0x20008:
273 if (op_type == MTS_READ)
274 *data = d->io_mask;
275 else
276 d->io_mask = *data;
277 break;
278
279 /* ??? */
280 /* 0: 3640, 4 << 5: 3620, 3 << 5: 3660 */
281 case 0x30000:
282 if (op_type == MTS_READ) {
283 switch(c3600_chassis_get_id(d->router)) {
284 case 3620:
285 *data = 4 << 5;
286 break;
287 case 3640:
288 *data = 0 << 5;
289 break;
290 case 3660:
291 *data = 3 << 5;
292 break;
293 default:
294 *data = 0;
295 }
296 }
297 break;
298
299 /* ??? */
300 case 0x30002:
301 if (op_type == MTS_WRITE) {
302 d->sel = *data;
303 } else {
304 //*data = d->sel;
305 }
306 break;
307
308 /*
309 * Environmental parameters, determined with "sh env all".
310 *
311 * Bit 0: 0 = overtemperature condition.
312 * Bit 4: 0 = RPS present.
313 * Bit 5: 0 = Input Voltage status failure.
314 * Bit 6: 1 = Thermal status failure.
315 * Bit 7: 1 = DC Output Voltage status failure.
316 */
317 case 0x30004:
318 if (op_type == MTS_READ) {
319 *data = 32 + 1;
320 }
321 break;
322
323 #if DEBUG_UNKNOWN
324 default:
325 if (op_type == MTS_READ) {
326 cpu_log(cpu,"IO_FPGA",
327 "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
328 offset,cpu->pc,op_size);
329 } else {
330 cpu_log(cpu,"IO_FPGA",
331 "write to unknown addr 0x%x, value=0x%llx, "
332 "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);
333 }
334 #endif
335 }
336
337 return NULL;
338 }
339
340 /*
341 * dev_c3660_iofpga_access()
342 */
343 static void *
344 dev_c3660_iofpga_access(cpu_mips_t *cpu,struct vdevice *dev,
345 m_uint32_t offset,u_int op_size,u_int op_type,
346 m_uint64_t *data)
347 {
348 struct iofpga_data *d = dev->priv_data;
349 u_int slot;
350
351 if (op_type == MTS_READ)
352 *data = 0x0;
353
354 #if DEBUG_ACCESS
355 if (offset != 0x0c) {
356 if (op_type == MTS_READ) {
357 cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",
358 offset,cpu->pc,op_size);
359 } else {
360 cpu_log(cpu,"IO_FPGA",
361 "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",
362 offset,cpu->pc,*data,op_size);
363 }
364 }
365 #endif
366
367 switch(offset) {
368 /*
369 * 0x7d00 is written here regularly.
370 * Some kind of hardware watchdog ?
371 */
372 case 0x0000c:
373 break;
374
375 /* Probably flash protection (if 0, no write access allowed) */
376 case 0x00008:
377 if (op_type == MTS_READ)
378 *data = 0xFF;
379 break;
380
381 /* Bootflash of 8 Mb */
382 case 0x0000a:
383 if (op_type == MTS_READ)
384 *data = 0x1000;
385 break;
386
387 /* NM presence - slots 1 to 4 */
388 case 0x10006:
389 if (op_type == MTS_READ)
390 *data = nm_get_status_2(d,0);
391 break;
392
393 /* NM presence - slot 5 to 6 */
394 case 0x10008:
395 if (op_type == MTS_READ)
396 *data = nm_get_status_2(d,1);
397 break;
398
399 /* Fan status, PS presence */
400 case 0x10018:
401 if (op_type == MTS_READ)
402 *data = 0x0000;
403 break;
404
405 /* unknown, read by env monitor */
406 case 0x1001a:
407 if (op_type == MTS_READ)
408 *data = 0x0000;
409 break;
410
411 /* board temperature */
412 case 0x30004:
413 if (op_type == MTS_READ) {
414 *data = 32 + 1;
415 }
416 break;
417
418 /* sh c3600: Per Slot Intr Mask */
419 case 0x10016:
420 if (op_type == MTS_READ)
421 *data = 0x12;
422 break;
423
424 /* sh c3600: OIR fsm state slot's (12) */
425 case 0x10020:
426 if (op_type == MTS_READ)
427 *data = 0x00;
428 break;
429
430 /* sh c3600: OIR fsm state slot's (34) */
431 case 0x10022:
432 if (op_type == MTS_READ)
433 *data = 0x00;
434 break;
435
436 /* sh c3600: OIR fsm state slot's (56) */
437 case 0x10024:
438 if (op_type == MTS_READ)
439 *data = 0x00;
440 break;
441
442 /*
443 * Backplane EEPROM.
444 *
445 * Bit 7: 0=Telco chassis, 1=Enterprise chassis.
446 */
447 case 0x10000:
448 if (op_type == MTS_WRITE)
449 nmc93c46_write(&d->router->mb_eeprom_group,(u_int)(*data));
450 else
451 *data = nmc93c46_read(&d->router->mb_eeprom_group) | 0x80;
452 break;
453
454 /* NM EEPROMs - slots 1 to 6 */
455 case 0x1000a:
456 case 0x1000b:
457 case 0x1000c:
458 case 0x1000d:
459 case 0x1000e:
460 case 0x1000f:
461 slot = (offset - 0x1000a) + 1;
462
463 if (op_type == MTS_WRITE) {
464 nmc93c46_write(&d->router->c3660_nm_eeprom_group[slot],
465 (u_int)(*data));
466 } else {
467 *data = nmc93c46_read(&d->router->c3660_nm_eeprom_group[slot]);
468 }
469 break;
470
471 /* NM EEPROM - slot 0 */
472 case 0x20006:
473 if (op_type == MTS_WRITE) {
474 nmc93c46_write(&d->router->c3660_nm_eeprom_group[0],
475 (u_int)(*data));
476 } else {
477 *data = nmc93c46_read(&d->router->c3660_nm_eeprom_group[0]);
478 }
479 break;
480
481 /* Unknown EEPROMs ? */
482 case 0x20000:
483 case 0x20002:
484 case 0x20004:
485 if (op_type == MTS_READ)
486 *data = 0xFFFF;
487 break;
488
489 /* IO Mask (displayed by "show c3600") */
490 case 0x20008:
491 if (op_type == MTS_READ)
492 *data = d->io_mask;
493 else
494 d->io_mask = *data;
495 break;
496
497 /* 0: 3640, 4 << 5: 3620, 3 << 5: 3660 */
498 case 0x30000:
499 if (op_type == MTS_READ)
500 *data = 3 << 5;
501 break;
502
503 /* ??? */
504 case 0x30008:
505 if (op_type == MTS_READ)
506 *data = 0xFF;
507 break;
508
509 /*
510 * Read at net interrupt (size 4).
511 * It seems that there are 4 lines per slot.
512 *
513 * Bit 24-27: slot 1
514 * Bit 16-19: slot 2
515 * Bit 28-31: slot 3
516 * Bit 20-23: slot 4
517 * Bit 08-11: slot 5
518 * Bit 00-03: slot 6
519 *
520 * Other bits are unknown.
521 */
522 case 0x10010:
523 if (op_type == MTS_READ)
524 *data = 0xFFFFFFFF;
525 vm_clear_irq(d->router->vm,C3600_NETIO_IRQ);
526 break;
527
528 /*
529 * Read at net interrupt (size 1)
530 *
531 * Bit 7-6: we get "Unexpected AIM interrupt on AIM slot 1".
532 * Bit 5-4: we get "Unexpected AIM interrupt on AIM slot 0".
533 * Bit 0-3: net interrupt for slot 0.
534 */
535 case 0x20010:
536 if (op_type == MTS_READ)
537 *data = 0x0F;
538 break;
539
540 /*
541 * Read when a PA Management interrupt is triggered.
542 *
543 * If not 0, we get:
544 * "Error: Unexpected NM Interrupt received from slot: x"
545 */
546 case 0x10014:
547 if (op_type == MTS_READ)
548 *data = 0x00;
549 vm_clear_irq(d->router->vm,C3600_NM_MGMT_IRQ);
550 break;
551
552 /*
553 * Read when an external interrupt is triggered.
554 *
555 * Bit 4: 1 = %UNKNOWN-1-GT64010: Unknown fatal interrupt(s)
556 * Bit 6: 1 = %OIRINT: OIR Event has occurred oir_ctrl 1000 oir_stat FFFF
557 *
558 * oir_ctrl = register 0x10004
559 * oir_stat = register 0x10006
560 */
561 case 0x2000a:
562 if (op_type == MTS_READ)
563 *data = 0x54;
564 vm_clear_irq(d->router->vm,C3600_EXT_IRQ);
565 break;
566
567 #if DEBUG_UNKNOWN
568 default:
569 if (op_type == MTS_READ) {
570 cpu_log(cpu,"IO_FPGA",
571 "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
572 offset,cpu->pc,op_size);
573 } else {
574 cpu_log(cpu,"IO_FPGA",
575 "write to unknown addr 0x%x, value=0x%llx, "
576 "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);
577 }
578 #endif
579 }
580
581 return NULL;
582 }
583
584 /* Initialize EEPROM groups */
585 void c3600_init_eeprom_groups(c3600_t *router)
586 {
587 struct nmc93c46_group *g;
588 int i;
589
590 /* Copy Mainboard EEPROM definition */
591 memcpy(&router->mb_eeprom,&eeprom_mb_def,sizeof(eeprom_mb_def));
592
593 /* Initialize group */
594 g = &router->mb_eeprom_group;
595 memcpy(g,&eeprom_mb_group,sizeof(eeprom_mb_group));
596 g->def[0] = &router->mb_eeprom;
597
598 /* Copy NM EEPROM definition (3620/3640) */
599 memcpy(&router->nm_eeprom,&eeprom_nm_def,sizeof(eeprom_nm_def));
600 router->nm_eeprom.data = NULL;
601 router->nm_eeprom.data_len = 0;
602
603 /* Initialize group (3620/3640) */
604 g = &router->nm_eeprom_group;
605 memcpy(g,&eeprom_nm_group,sizeof(eeprom_nm_group));
606 g->def[0] = &router->nm_eeprom;
607
608 /* 3660 NM EEPROM */
609 for(i=0;i<C3600_MAX_NM_BAYS;i++) {
610 memcpy(&router->c3660_nm_eeprom_def[i],&eeprom_nm_def,
611 sizeof(struct nmc93c46_eeprom_def));
612
613 memcpy(&router->c3660_nm_eeprom_group[i],&eeprom_nm_group,
614 sizeof(struct nmc93c46_group));
615
616 router->c3660_nm_eeprom_group[i].def[0] =
617 &router->c3660_nm_eeprom_def[i];
618 }
619 }
620
621 /* Shutdown the IO FPGA device */
622 void dev_c3600_iofpga_shutdown(vm_instance_t *vm,struct iofpga_data *d)
623 {
624 if (d != NULL) {
625 /* Remove the device */
626 dev_remove(vm,&d->dev);
627
628 /* Free the structure itself */
629 free(d);
630 }
631 }
632
633 /*
634 * dev_c3600_iofpga_init()
635 */
636 int dev_c3600_iofpga_init(c3600_t *router,m_uint64_t paddr,m_uint32_t len)
637 {
638 vm_instance_t *vm = router->vm;
639 struct iofpga_data *d;
640
641 /* Allocate private data structure */
642 if (!(d = malloc(sizeof(*d)))) {
643 fprintf(stderr,"IO_FPGA: out of memory\n");
644 return(-1);
645 }
646
647 memset(d,0,sizeof(*d));
648 d->router = router;
649
650 vm_object_init(&d->vm_obj);
651 d->vm_obj.name = "io_fpga";
652 d->vm_obj.data = d;
653 d->vm_obj.shutdown = (vm_shutdown_t)dev_c3600_iofpga_shutdown;
654
655 /* Set device properties */
656 dev_init(&d->dev);
657 d->dev.name = "io_fpga";
658 d->dev.phys_addr = paddr;
659 d->dev.phys_len = len;
660 d->dev.priv_data = d;
661
662 switch(router->chassis_driver->chassis_id) {
663 case 3620:
664 case 3640:
665 d->dev.handler = dev_c3620_c3640_iofpga_access;
666 break;
667 case 3660:
668 d->dev.handler = dev_c3660_iofpga_access;
669 break;
670 default:
671 fprintf(stderr,"C3600 '%s': invalid chassis ID %d\n",
672 router->vm->name,router->chassis_driver->chassis_id);
673 free(d);
674 return(-1);
675 }
676
677 /* Map this device to the VM */
678 vm_bind_device(router->vm,&d->dev);
679 vm_object_add(vm,&d->vm_obj);
680 return(0);
681 }

  ViewVC Help
Powered by ViewVC 1.1.26