|
|
1.1 root 1: /*
2: * Cisco 3725 simulation platform.
3: * Copyright (c) 2006 Christophe Fillot ([email protected])
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"
1.1.1.3 root 18: #include "cpu.h"
19: #include "vm.h"
1.1 root 20: #include "dynamips.h"
21: #include "memory.h"
22: #include "device.h"
23: #include "dev_vtty.h"
1.1.1.4 root 24: #include "nmc93cX6.h"
1.1 root 25: #include "dev_c3725.h"
26:
27: /* Debugging flags */
28: #define DEBUG_UNKNOWN 1
29: #define DEBUG_ACCESS 0
1.1.1.4 root 30: #define DEBUG_NET_IRQ 0
1.1 root 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:
1.1.1.4 root 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 */
1.1.1.5 ! root 52: { 1, 0 }, /* Slot 1: reg 0x28, 0x0000000X */
! 53: { 1, 4 }, /* Slot 2: reg 0x28, 0x000000X0 */
1.1.1.4 root 54: };
1.1 root 55:
56: /* IO FPGA structure */
1.1.1.4 root 57: struct c3725_iofpga_data {
1.1 root 58: vm_obj_t vm_obj;
59: struct vdevice dev;
60: c3725_t *router;
61:
1.1.1.4 root 62: /* Network IRQ status */
63: m_uint16_t net_irq_status[2];
64:
65: /* Interrupt mask */
1.1 root 66: m_uint16_t intr_mask;
67: };
68:
69: /* Mainboard EEPROM definition */
1.1.1.4 root 70: static const struct nmc93cX6_eeprom_def eeprom_mb_def = {
1.1 root 71: EEPROM_MB_CLK, EEPROM_MB_CS,
72: EEPROM_MB_DIN, EEPROM_MB_DOUT,
73: };
74:
75: /* Mainboard EEPROM */
1.1.1.4 root 76: static const struct nmc93cX6_group eeprom_mb_group = {
77: EEPROM_TYPE_NMC93C46, 1, 0, "Mainboard EEPROM", 0, { &eeprom_mb_def },
1.1 root 78: };
79:
80: /* NM EEPROM definition */
1.1.1.4 root 81: static const struct nmc93cX6_eeprom_def eeprom_nm_def = {
1.1 root 82: EEPROM_NM_CLK, EEPROM_NM_CS,
83: EEPROM_NM_DIN, EEPROM_NM_DOUT,
84: };
85:
86: /* NM EEPROM */
1.1.1.4 root 87: static const struct nmc93cX6_group eeprom_nm_group = {
88: EEPROM_TYPE_NMC93C46, 1, 0, "NM EEPROM", 0, { &eeprom_nm_def },
1.1 root 89: };
90:
1.1.1.4 root 91: /* Update network interrupt status */
92: static inline void dev_c3725_iofpga_net_update_irq(struct c3725_iofpga_data *d)
93: {
94: if ((d->net_irq_status[0] != 0xFFFF) || (d->net_irq_status[1] != 0xFFFF)) {
95: vm_set_irq(d->router->vm,C3725_NETIO_IRQ);
96: } else {
97: vm_clear_irq(d->router->vm,C3725_NETIO_IRQ);
98: }
99: }
100:
101: /* Trigger a Network IRQ for the specified slot/port */
102: void dev_c3725_iofpga_net_set_irq(struct c3725_iofpga_data *d,
103: u_int slot,u_int port)
104: {
105: struct net_irq_distrib *irq_dist;
106:
107: #if DEBUG_NET_IRQ
108: vm_log(d->router->vm,"IO_FPGA","setting NetIRQ for slot %u port %u\n",
109: slot,port);
110: #endif
111: irq_dist = &net_irq_dist[slot];
112: d->net_irq_status[irq_dist->reg] &= ~(1 << (irq_dist->offset + port));
113: dev_c3725_iofpga_net_update_irq(d);
114: }
115:
116: /* Clear a Network IRQ for the specified slot/port */
117: void dev_c3725_iofpga_net_clear_irq(struct c3725_iofpga_data *d,
118: u_int slot,u_int port)
119: {
120: struct net_irq_distrib *irq_dist;
121:
122: #if DEBUG_NET_IRQ
123: vm_log(d->router->vm,"IO_FPGA","clearing NetIRQ for slot %u port %u\n",
124: slot,port);
125: #endif
126: irq_dist = &net_irq_dist[slot];
127: d->net_irq_status[irq_dist->reg] |= (1 << (irq_dist->offset + port));
128: dev_c3725_iofpga_net_update_irq(d);
129: }
130:
1.1 root 131: /*
132: * dev_c3725_iofpga_access()
133: */
134: static void *
1.1.1.3 root 135: dev_c3725_iofpga_access(cpu_gen_t *cpu,struct vdevice *dev,
1.1 root 136: m_uint32_t offset,u_int op_size,u_int op_type,
137: m_uint64_t *data)
138: {
1.1.1.4 root 139: struct c3725_iofpga_data *d = dev->priv_data;
1.1 root 140:
141: if (op_type == MTS_READ)
142: *data = 0x0;
143:
144: #if DEBUG_ACCESS
145: if (op_type == MTS_READ) {
146: cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx (size=%u)\n",
1.1.1.3 root 147: offset,cpu_get_pc(cpu),op_size);
1.1 root 148: } else {
149: cpu_log(cpu,"IO_FPGA",
150: "writing reg 0x%x at pc=0x%llx, data=0x%llx (size=%u)\n",
1.1.1.3 root 151: offset,cpu_get_pc(cpu),*data,op_size);
1.1 root 152: }
153: #endif
154:
155: switch(offset) {
156: /*
157: * Platform type ?
1.1.1.2 root 158: * 0x04 and 0x05 seem to work.
1.1 root 159: */
160: case 0x36:
161: if (op_type == MTS_READ)
1.1.1.2 root 162: *data = 0x04 << 5;
1.1 root 163: break;
164:
165: /* Mainboard EEPROM */
166: case 0x0e:
167: if (op_type == MTS_WRITE)
1.1.1.4 root 168: nmc93cX6_write(&d->router->mb_eeprom_group,(u_int)(*data));
1.1 root 169: else
1.1.1.4 root 170: *data = nmc93cX6_read(&d->router->mb_eeprom_group);
1.1 root 171: break;
172:
173: case 0x12:
174: /*
175: * Bit 0: 1=No WIC in slot 0 ?
176: * Bit 1: 1=No WIC in slot 1 ?
177: * Bit 2: 1=No WIC in slot 2 ?
178: */
179: if (op_type == MTS_READ)
180: *data = 0x0007;
181: break;
182:
183: case 0x14:
184: if (op_type == MTS_READ)
185: *data = 0xFFFF;
186: break;
187:
188: case 0x18:
189: if (op_type == MTS_READ)
190: *data = 0xFFFF;
191: break;
192:
193: /* wic/vwic related */
194: case 0x40:
195: if (op_type == MTS_READ)
196: *data = 0x0004;
197: break;
198:
199: /* WIC related: 16-bit data */
200: case 0x42:
201: break;
202:
203: /* NM Slot 1 EEPROM */
204: case 0x44:
205: if (op_type == MTS_WRITE)
1.1.1.4 root 206: nmc93cX6_write(&d->router->nm_eeprom_group[0],(u_int)(*data));
1.1 root 207: else
1.1.1.4 root 208: *data = nmc93cX6_read(&d->router->nm_eeprom_group[0]);
1.1 root 209: break;
210:
211: /* NM Slot 2 EEPROM */
212: case 0x46:
213: if (op_type == MTS_WRITE)
1.1.1.4 root 214: nmc93cX6_write(&d->router->nm_eeprom_group[1],(u_int)(*data));
1.1 root 215: else
1.1.1.4 root 216: *data = nmc93cX6_read(&d->router->nm_eeprom_group[1]);
1.1 root 217: break;
218:
219: /* AIM EEPROM #0 */
220: case 0x48:
221: if (op_type == MTS_READ)
222: *data = 0xFFFF;
223: break;
224:
225: /* AIM EEPROM #1 */
226: case 0x4a:
227: if (op_type == MTS_READ)
228: *data = 0xFFFF;
229: break;
230:
231: /*
232: * NM Presence.
233: *
234: * Bit 7: 0=NM present in slot 1.
235: * Bit 11: 0=NM present in slot 2.
236: * Other bits unknown.
237: */
238: case 0x20:
239: if (op_type == MTS_READ) {
240: *data = 0xFFFF;
241:
242: if (c3725_nm_check_eeprom(d->router,1))
243: *data &= ~0x0008;
244:
245: if (c3725_nm_check_eeprom(d->router,2))
246: *data &= ~0x0800;
247: }
248: break;
249:
250: /* ??? */
251: case 0x24:
252: break;
253:
254: /* Intr Mask (sh platform) */
255: case 0x30:
256: if (op_type == MTS_READ)
257: *data = d->intr_mask;
258: else
259: d->intr_mask = *data;
260: break;
261:
262: /*
263: * Network interrupt status.
264: *
265: * Bit 0: 0 = GT96100 Ethernet ports.
266: * Other bits unknown.
267: */
268: case 0x26:
269: if (op_type == MTS_READ)
1.1.1.4 root 270: *data = d->net_irq_status[0];
1.1 root 271: break;
272:
273: /*
274: * Network interrupt status.
275: *
276: * Bit 0: 0 = NM in Slot 1.
277: * Bit 8: 0 = NM in Slot 2.
278: * Other bits unknown.
279: */
280: case 0x28:
1.1.1.4 root 281: if (op_type == MTS_READ)
282: *data = d->net_irq_status[1];
1.1 root 283: break;
284:
285: case 0x2c:
286: if (op_type == MTS_READ)
287: *data = 0xFFFF;
288: break;
289:
290: /* OIR interrupt but not supported (IRQ 6) */
291: case 0x2e:
292: if (op_type == MTS_READ)
293: *data = 0xFFFF;
294: break;
295:
296: /*
297: * Environmental monitor, determined with "sh env all".
298: *
299: * Bit 0: 1 = Fan Error
300: * Bit 1: 1 = Fan Error
301: * Bit 2: 1 = Over-temperature
302: * Bit 3: ???
303: * Bit 4: 0 = RPS present.
304: * Bit 5: 0 = Input Voltage status failure.
305: * Bit 6: 1 = Thermal status failure.
306: * Bit 7: 1 = DC Output Voltage status failure.
307: */
308: case 0x3a:
309: if (op_type == MTS_READ)
310: *data = 0x0020;
311: break;
312:
313: /*
314: * Bit 0: Slot0 Compact Flash presence.
315: * Bit 1: System Compact Flash presence.
316: */
317: case 0x3c:
318: if (op_type == MTS_READ) {
319: *data = 0xFFFF;
320:
321: /* System Flash ? */
322: if (cpu->vm->pcmcia_disk_size[0])
323: *data &= ~0x02;
324:
325: /* Slot0 Flash ? */
326: if (cpu->vm->pcmcia_disk_size[1])
327: *data &= ~0x01;
328: }
329: break;
330:
331: #if DEBUG_UNKNOWN
332: default:
333: if (op_type == MTS_READ) {
334: cpu_log(cpu,"IO_FPGA",
335: "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
1.1.1.3 root 336: offset,cpu_get_pc(cpu),op_size);
1.1 root 337: } else {
338: cpu_log(cpu,"IO_FPGA",
339: "write to unknown addr 0x%x, value=0x%llx, "
1.1.1.3 root 340: "pc=0x%llx (size=%u)\n",
341: offset,*data,cpu_get_pc(cpu),op_size);
1.1 root 342: }
343: #endif
344: }
345:
346: return NULL;
347: }
348:
349: /* Initialize EEPROM groups */
350: void c3725_init_eeprom_groups(c3725_t *router)
351: {
352: /* Initialize Mainboard EEPROM */
353: router->mb_eeprom_group = eeprom_mb_group;
354: router->mb_eeprom_group.eeprom[0] = &router->mb_eeprom;
355: router->mb_eeprom.data = NULL;
356: router->mb_eeprom.len = 0;
357:
358: /* EEPROM for NM slot 1 */
359: router->nm_eeprom_group[0] = eeprom_nm_group;
360: router->nm_eeprom_group[0].eeprom[0] = &router->nm_bay[1].eeprom;
361:
362: /* EEPROM for NM slot 2 */
363: router->nm_eeprom_group[1] = eeprom_nm_group;
364: router->nm_eeprom_group[1].eeprom[0] = &router->nm_bay[2].eeprom;
365: }
366:
367: /* Shutdown the IO FPGA device */
1.1.1.4 root 368: static void
369: dev_c3725_iofpga_shutdown(vm_instance_t *vm,struct c3725_iofpga_data *d)
1.1 root 370: {
371: if (d != NULL) {
372: /* Remove the device */
373: dev_remove(vm,&d->dev);
374:
375: /* Free the structure itself */
376: free(d);
377: }
378: }
379:
380: /*
381: * dev_c3725_iofpga_init()
382: */
383: int dev_c3725_iofpga_init(c3725_t *router,m_uint64_t paddr,m_uint32_t len)
384: {
385: vm_instance_t *vm = router->vm;
1.1.1.4 root 386: struct c3725_iofpga_data *d;
1.1 root 387:
388: /* Allocate private data structure */
389: if (!(d = malloc(sizeof(*d)))) {
390: fprintf(stderr,"IO_FPGA: out of memory\n");
391: return(-1);
392: }
393:
394: memset(d,0,sizeof(*d));
395: d->router = router;
1.1.1.4 root 396: d->net_irq_status[0] = 0xFFFF;
397: d->net_irq_status[1] = 0xFFFF;
1.1 root 398:
399: vm_object_init(&d->vm_obj);
400: d->vm_obj.name = "io_fpga";
401: d->vm_obj.data = d;
402: d->vm_obj.shutdown = (vm_shutdown_t)dev_c3725_iofpga_shutdown;
403:
404: /* Set device properties */
405: dev_init(&d->dev);
406: d->dev.name = "io_fpga";
407: d->dev.phys_addr = paddr;
408: d->dev.phys_len = len;
409: d->dev.priv_data = d;
410: d->dev.handler = dev_c3725_iofpga_access;
411:
412: /* Map this device to the VM */
413: vm_bind_device(router->vm,&d->dev);
414: vm_object_add(vm,&d->vm_obj);
415: return(0);
416: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.