/[dynamips]/upstream/dynamips-0.2.6-RC2/dev_c7200_bri.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-RC2/dev_c7200_bri.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations)
Sat Oct 6 16:05:34 2007 UTC (13 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 26374 byte(s)
dynamips-0.2.6-RC2

1 /*
2 * Cisco C7200 (Predator) Simulation Platform.
3 * Copyright (C) 2005-2006 Christophe Fillot. All rights reserved.
4 *
5 * EEPROM types:
6 * - 0x3d: PA-4B
7 * - 0x3e: PA-8B
8 *
9 * Vernon Missouri offered a PA-4B.
10 *
11 * It is based on the Munich32 chip:
12 * http://www.infineon.com//upload/Document/cmc_upload/migrated_files/document_files/Datasheet/m32_34m.pdf
13 *
14 * There is also one TP3420A per BRI port.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <errno.h>
22 #include <pthread.h>
23 #include <assert.h>
24
25 #include "mips64.h"
26 #include "dynamips.h"
27 #include "memory.h"
28 #include "device.h"
29 #include "net.h"
30 #include "net_io.h"
31 #include "ptask.h"
32 #include "dev_c7200.h"
33
34 /* Debugging flags */
35 #define DEBUG_ACCESS 1
36 #define DEBUG_TRANSMIT 0
37 #define DEBUG_RECEIVE 0
38
39 /* PCI vendor/product codes */
40 #define BRI_PCI_VENDOR_ID 0x10ee
41 #define BRI_PCI_PRODUCT_ID 0x4013
42
43 /* Memory used by the munich32 chip */
44 #define MUNICH32_MEM_SIZE 0x40000
45
46 /* Maximum packet size */
47 #define M32_MAX_PKT_SIZE 8192
48
49 /* 32 timeslots and 32 channels for a Munich32 chip */
50 #define M32_NR_TIMESLOTS 32
51 #define M32_NR_CHANNELS 32
52
53 /* Offsets */
54 #define M32_OFFSET_TS 0x0c /* Timeslots */
55 #define M32_OFFSET_CHAN 0x8c /* Channel specification */
56 #define M32_OFFSET_CRDA 0x28c /* Current RX descriptor address */
57 #define M32_OFFSET_CTDA 0x30c /* Current TX descriptor address */
58
59 /* Action Specification */
60 #define M32_AS_PCM_MASK 0xE0000000 /* PCM Highway Format */
61 #define M32_AS_PCM_SHIFT 29
62 #define M32_AS_MFL_MASK 0x1FFF0000 /* Maximum Frame Length */
63 #define M32_AS_MFL_SHIFT 16
64 #define M32_AS_IN 0x00008000 /* Initialization Procedure */
65 #define M32_AS_ICO 0x00004000 /* Initialize Channel Only */
66 #define M32_AS_CHAN_MASK 0x00001F00 /* Channel Number */
67 #define M32_AS_CHAN_SHIFT 8
68 #define M32_AS_IM 0x00000080 /* Interrupt Mask */
69 #define M32_AS_RES 0x00000040 /* Reset */
70 #define M32_AS_LOOPS_MASK 0x00000038 /* Loops (LOC,LOOP,LOOPI) */
71 #define M32_AS_LOOPS_SHIFT 3
72 #define M32_AS_IA 0x00000004 /* Interrupt Attention */
73
74 /* Interrupt Information */
75 #define M32_II_INT 0x80000000 /* Interrupt */
76 #define M32_II_VN3 0x20000000 /* Silicon version number */
77 #define M32_II_VN2 0x10000000
78 #define M32_II_VN1 0x08000000
79 #define M32_II_FRC 0x04000000 /* Framing bits changed */
80 #define M32_II_ARACK 0x00008000 /* Action Request Acknowledge */
81 #define M32_II_ARF 0x00004000 /* Action Request Failed */
82 #define M32_II_HI 0x00002000 /* Host Initiated Interrupt */
83 #define M32_II_FI 0x00001000 /* Frame Indication */
84 #define M32_II_IFC 0x00000800 /* Idle Flag Change */
85 #define M32_II_SF 0x00000400 /* Short Frame */
86 #define M32_II_ERR 0x00000200 /* Error condition */
87 #define M32_II_FO 0x00000100 /* Overflow/Underflow */
88 #define M32_II_RT 0x00000020 /* Direction (Transmit/Receive Int) */
89
90 /* Timeslot Assignment */
91 #define M32_TS_TTI 0x20000000 /* Transmit Timeslot Inhibit */
92 #define M32_TS_TCN_MASK 0x1F000000 /* Transmit Channel Number Mask */
93 #define M32_TS_TCN_SHIFT 24
94 #define M32_TS_TFM_MASK 0x00FF0000 /* Transmit Fill Mask */
95 #define M32_TS_TFM_SHIFT 16
96 #define M32_TS_RTI 0x00002000 /* Receive Timeslot Inhibit */
97 #define M32_TS_RCN_MASK 0x00001F00 /* Receive Channel Number Mask */
98 #define M32_TS_RCN_SHIFT 8
99 #define M32_TS_RFM_MASK 0x000000FF /* Receive Fill Mask */
100 #define M32_TS_RFM_SHIFT 0
101
102 /* Transmit Descriptor */
103 #define M32_TXDESC_FE 0x80000000 /* Frame End */
104 #define M32_TXDESC_HOLD 0x40000000 /* Hold=0: usable by Munich */
105 #define M32_TXDESC_HI 0x20000000 /* Host Initiated Interrupt */
106 #define M32_TXDESC_NO_MASK 0x1FFF0000 /* Number of bytes */
107 #define M32_TXDESC_NO_SHIFT 16
108 #define M32_TXDESC_V110 0x00008000 /* V.110/X.30 frame */
109 #define M32_TXDESC_CSM 0x00000800 /* CRC Select per Message */
110 #define M32_TXDESC_FNUM 0x000001FF /* Inter-Frame Time-Fill chars */
111
112 /* Munich32 TX descriptor */
113 struct m32_tx_desc {
114 m_uint32_t params; /* Size + Flags */
115 m_uint32_t tdp; /* Transmit Data Pointer */
116 m_uint32_t ntdp; /* Next Transmit Descriptor Pointer */
117 };
118
119 /* Receive Descriptor (parameters) */
120 #define M32_RXDESC_HOLD 0x40000000 /* Hold */
121 #define M32_RXDESC_HI 0x20000000 /* Host Initiated Interrupt */
122 #define M32_RXDESC_NO_MASK 0x1FFF0000 /* Size of receive data section */
123 #define M32_RXDESC_NO_SHIFT 16
124
125 /* Receive Descriptor (status) */
126 #define M32_RXDESC_FE 0x80000000 /* Frame End */
127 #define M32_RXDESC_C 0x40000000
128 #define M32_RXDESC_BNO_MASK 0x1FFF0000 /* Bytes stored in data section */
129 #define M32_RXDESC_BNO_SHIFT 16
130 #define M32_RXDESC_SF 0x00004000
131 #define M32_RXDESC_LOSS 0x00002000 /* Error in sync pattern */
132 #define M32_RXDESC_CRCO 0x00001000 /* CRC error */
133 #define M32_RXDESC_NOB 0x00000800 /* Bit content not divisible by 8 */
134 #define M32_RXDESC_LFD 0x00000400 /* Long Frame Detected */
135 #define M32_RXDESC_RA 0x00000200 /* Receive Abort */
136 #define M32_RXDESC_ROF 0x00000100 /* Overflow of internal buffer */
137
138 /* Munich32 RX descriptor */
139 struct m32_rx_desc {
140 m_uint32_t params; /* RX parameters (hold, hi, ...) */
141 m_uint32_t status; /* Status */
142 m_uint32_t rdp; /* Receive Data Pointer */
143 m_uint32_t nrdp; /* Next Receive Descriptor Pointer */
144 };
145
146 /* Munich32 channel */
147 struct m32_channel {
148 m_uint32_t status;
149 m_uint32_t frda;
150 m_uint32_t ftda;
151 m_uint32_t itbs;
152
153 /* Physical addresses of current RX and TX descriptors */
154 m_uint32_t rx_current,tx_current;
155
156 /* Poll mode */
157 u_int poll_mode;
158 };
159
160 /* Munich32 chip data */
161 struct m32_data {
162 /* Virtual machine */
163 vm_instance_t *vm;
164
165 /* TX ring scanner task id */
166 ptask_id_t tx_tid;
167
168 /* Interrupt Queue */
169 m_uint32_t iq_base_addr;
170 m_uint32_t iq_cur_addr;
171 u_int iq_size;
172
173 /* Timeslots */
174 m_uint32_t timeslots[M32_NR_TIMESLOTS];
175
176 /* Channels */
177 struct m32_channel channels[M32_NR_CHANNELS];
178
179 /* Embedded config memory */
180 m_uint32_t cfg_mem[MUNICH32_MEM_SIZE/4];
181 };
182
183 /* === TP3420 SID === */
184
185 /* Activation / Desactivation */
186 #define TP3420_SID_NOP 0xFF /* No Operation */
187 #define TP3420_SID_PDN 0x00 /* Power Down */
188 #define TP3420_SID_PUP 0x20 /* Power Up */
189 #define TP3420_SID_DR 0x01 /* Deactivation Request */
190 #define TP3420_SID_FI2 0x02 /* Force Info 2 (NT Only) */
191 #define TP3420_SID_MMA 0x1F /* Monitor Mode Activation */
192
193 /* Device Modes */
194 #define TP3420_SID_NTA 0x04 /* NT Mode, Adaptive Sampling */
195 #define TP3420_SID_NTF 0x05 /* NT Mode, Fixed Sampling */
196 #define TP3420_SID_TES 0x06 /* TE Mode, Digital System Interface Slave */
197 #define TP3420_SID_TEM 0x07 /* TE Mode, Digital System Interface Master */
198
199 /* Digital Interface Formats */
200 #define TP3420_SID_DIF1 0x08 /* Digital System Interface Format 1 */
201 #define TP3420_SID_DIF2 0x09 /* Digital System Interface Format 2 */
202 #define TP3420_SID_DIF3 0x0A /* Digital System Interface Format 3 */
203 #define TP3420_SID_DIF4 0x0B /* Digital System Interface Format 4 */
204
205 /* BCLK Frequency Settings */
206 #define TP3420_SID_BCLK1 0x98 /* Set BCLK to 2.048 Mhz */
207 #define TP3420_SID_BCLK2 0x99 /* Set BCLK to 256 Khz */
208 #define TP3420_SID_BCLK3 0x9A /* Set BCLK to 512 Khz */
209 #define TP3420_SID_BCLK4 0x9B /* Set BCLK to 2.56 Mhz */
210
211 /* B Channel Exchange */
212 #define TP3420_SID_BDIR 0x0C /* B Channels Mapped Direct (B1->B1,B2->B2) */
213 #define TP3420_SID_BEX 0x0D /* B Channels Exchanged (B1->B2,B2->B1) */
214
215 /* D Channel Access */
216 #define TP3420_SID_DREQ1 0x0E /* D Channel Request, Class 1 Message */
217 #define TP3420_SID_DREQ2 0x0F /* D Channel Request, Class 2 Message */
218
219 /* D Channel Access Control */
220 #define TP3420_SID_DACCE 0x90 /* Enable D-Channel Access Mechanism */
221 #define TP3420_SID_DACCD 0x91 /* Disable D-Channel Access Mechanism */
222 #define TP3420_SID_EBIT0 0x96 /* Force Echo Bit to 0 */
223 #define TP3420_SID_EBITI 0x97 /* Force Echo Bit to Inverted Received D bit */
224 #define TP3420_SID_EBITN 0x9C /* Reset EBITI and EBIT0 to Normal Condition */
225 #define TP3420_SID_DCKE 0xF1 /* D Channel Clock Enable */
226
227 /* End Of Message (EOM) Interrupt */
228 #define TP3420_SID_EIE 0x10 /* EOM Interrupt Enabled */
229 #define TP3420_SID_EID 0x11 /* EOM Interrupt Disabled */
230
231 /* B1 Channel Enable/Disable */
232 #define TP3420_SID_B1E 0x14 /* B1 Channel Enabled */
233 #define TP3420_SID_B1D 0x15 /* B1 Channel Disabled */
234
235 /* B2 Channel Enable/Disable */
236 #define TP3420_SID_B2E 0x16 /* B2 Channel Enabled */
237 #define TP3420_SID_B2D 0x17 /* B2 Channel Disabled */
238
239 /* Loopback Tests Modes */
240 #define TP3420_SID_CAL 0x1B /* Clear All Loopbacks */
241
242 /* Control Device State Reading */
243 #define TP3420_SID_ENST 0x92 /* Enable the Device State Output on NOCST */
244 #define TP3420_SID_DISST 0x93 /* Disable the Device State Output on NOCST */
245
246 /* PIN Signal Selection */
247 #define TP3420_SID_PINDEF 0xE0 /* Redefine PIN signals */
248
249 /* TP3420 Status Register */
250 #define TP3420_SR_LSD 0x02 /* Line Signal Detected Far-End */
251 #define TP3420_SR_AP 0x03 /* Activation Pending */
252 #define TP3420_SR_AI 0x0C /* Activation Indication */
253 #define TP3420_SR_EI 0x0E /* Error Indication */
254 #define TP3420_SR_DI 0x0F /* Deactivation Indication */
255 #define TP3420_SR_EOM 0x06 /* End of D-channel TX message */
256 #define TP3420_SR_CON 0x07 /* Lost Contention for D channel */
257
258 /* NO Change Return status */
259 #define TP3420_SR_NOC 0x00 /* NOC Status after DISST command */
260 #define TP3420_SR_NOCST 0x80 /* NOC Status after ENST command */
261
262 /* BRI Channel Index */
263 #define BRI_CHAN_INDEX_B1 0
264 #define BRI_CHAN_INDEX_B2 1
265 #define BRI_CHAN_INDEX_D 2
266
267 /* PA-4B Data */
268 struct pa_4b_data {
269 char *name;
270
271 /* Virtual machine */
272 vm_instance_t *vm;
273
274 /* Virtual device */
275 struct vdevice *dev;
276
277 /* PCI device information */
278 struct pci_device *pci_dev;
279
280 /* NetIO descriptor */
281 netio_desc_t *nio;
282
283 /* Munich32 data and base offset */
284 struct m32_data m32_data;
285 u_int m32_offset;
286 };
287
288 /* Log a PA-4B/PA-8B message */
289 #define BRI_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)
290
291 /* Read a configuration word */
292 static inline m_uint32_t m32_get_cfgw(struct m32_data *d,m_uint32_t offset)
293 {
294 return(d->cfg_mem[offset >> 2]);
295 }
296
297 /* Write a configuration word */
298 static inline void m32_set_cfgw(struct m32_data *d,m_uint32_t offset,
299 m_uint32_t val)
300 {
301 d->cfg_mem[offset >> 2] = val;
302 }
303
304 /* Post an interrupt into the interrupt queue */
305 static int m32_post_interrupt(struct m32_data *d,m_uint32_t iq_value)
306 {
307 if (!d->iq_base_addr)
308 return(-1);
309
310 /* The INT bit is mandatory */
311 iq_value |= M32_II_INT;
312
313 #if 0
314 printf("M32: Posting interrupt iq_val=0x%8.8x at 0x%8.8x\n",
315 iq_value,d->iq_cur_addr);
316 #endif
317
318 physmem_copy_u32_to_vm(d->vm,d->iq_cur_addr,iq_value);
319 d->iq_cur_addr += sizeof(m_uint32_t);
320
321 if (d->iq_cur_addr >= (d->iq_base_addr + d->iq_size))
322 d->iq_cur_addr = d->iq_base_addr;
323
324 return(0);
325 }
326
327 /* Fetch a timeslot assignment */
328 static int m32_fetch_ts_assign(struct m32_data *d,u_int ts_id)
329 {
330 m_uint32_t offset;
331
332 offset = M32_OFFSET_TS + (ts_id * sizeof(m_uint32_t));
333 d->timeslots[ts_id] = m32_get_cfgw(d,offset);
334 return(0);
335 }
336
337 /* Fetch all timeslot assignments */
338 static int m32_fetch_all_ts(struct m32_data *d)
339 {
340 m_uint32_t offset = M32_OFFSET_TS;
341 u_int i;
342
343 for(i=0;i<M32_NR_TIMESLOTS;i++,offset+=sizeof(m_uint32_t))
344 d->timeslots[i] = m32_get_cfgw(d,offset);
345
346 return(0);
347 }
348
349 /* Show timeslots assignments (debugging) */
350 static void m32_show_ts_assign(struct m32_data *d)
351 {
352 m_uint32_t ts;
353 u_int i;
354
355 printf("MUNICH32 timeslots:\n");
356
357 for(i=0;i<M32_NR_TIMESLOTS;i++) {
358 ts = d->timeslots[i];
359
360 if ((ts & (M32_TS_TTI|M32_TS_RTI)) != (M32_TS_TTI|M32_TS_RTI)) {
361 printf(" Timeslot %2u: ",i);
362
363 if (!(ts & M32_TS_TTI)) {
364 printf("TCN=%2u TFM=0x%2.2x ",
365 (ts & M32_TS_TCN_MASK) >> M32_TS_TCN_SHIFT,
366 (ts & M32_TS_TFM_MASK) >> M32_TS_TFM_SHIFT);
367 }
368
369 if (!(ts & M32_TS_RTI)) {
370 printf("RCN=%2u RFM=0x%2.2x",
371 (ts & M32_TS_RCN_MASK) >> M32_TS_RCN_SHIFT,
372 (ts & M32_TS_RFM_MASK) >> M32_TS_RFM_SHIFT);
373 }
374
375 printf("\n");
376 }
377 }
378
379 printf("\n");
380 }
381
382 /* Show info about a channels (debugging) */
383 static void m32_show_channel(struct m32_data *d,u_int chan_id)
384 {
385 struct m32_channel *chan;
386
387 chan = &d->channels[chan_id];
388 printf("M32 Channel %u:\n",chan_id);
389 printf(" Status : 0x%8.8x\n",chan->status);
390 printf(" FRDA : 0x%8.8x\n",chan->frda);
391 printf(" FTDA : 0x%8.8x\n",chan->ftda);
392 printf(" ITBS : 0x%8.8x\n",chan->itbs);
393 }
394
395 /* Fetch a channel specification */
396 static int m32_fetch_chan_spec(struct m32_data *d,u_int chan_id)
397 {
398 struct m32_channel *chan;
399 m_uint32_t offset;
400
401 offset = M32_OFFSET_CHAN + (chan_id * 4 * sizeof(m_uint32_t));
402 chan = &d->channels[chan_id];
403
404 chan->status = m32_get_cfgw(d,offset);
405 chan->frda = m32_get_cfgw(d,offset+4);
406 chan->ftda = m32_get_cfgw(d,offset+8);
407 chan->itbs = m32_get_cfgw(d,offset+12);
408
409 chan->poll_mode = 0;
410 chan->rx_current = chan->frda;
411 chan->tx_current = chan->ftda;
412
413 m32_set_cfgw(d,M32_OFFSET_CTDA+(chan_id*4),chan->tx_current);
414
415 #if 1
416 if (chan_id == 2) {
417 printf("M32: Fetched channel %u\n",chan_id);
418 //m32_show_ts_assign(d);
419 m32_show_channel(d,chan_id);
420 }
421 #endif
422 return(0);
423 }
424
425 /* Fetch all channel specifications */
426 static void m32_fetch_all_chan_spec(struct m32_data *d)
427 {
428 u_int i;
429
430 for(i=0;i<M32_NR_CHANNELS;i++)
431 m32_fetch_chan_spec(d,i);
432 }
433
434 /* Try to acquire the specified TX descriptor */
435 static int m32_tx_acquire(struct m32_data *d,m_uint32_t txd_addr,
436 struct m32_tx_desc *txd)
437 {
438 m_uint32_t params;
439
440 if (!(params = physmem_copy_u32_from_vm(d->vm,txd_addr)) & M32_TXDESC_HOLD)
441 return(FALSE);
442
443 txd->params = params;
444 txd->tdp = physmem_copy_u32_from_vm(d->vm,txd_addr+4);
445 txd->ntdp = physmem_copy_u32_from_vm(d->vm,txd_addr+8);
446 return(TRUE);
447 }
448
449 /* Try to acquire the next TX descriptor */
450 static int m32_tx_acquire_next(struct m32_data *d,m_uint32_t *txd_addr)
451 {
452 m_uint32_t params;
453
454 /* HOLD bit must be reset */
455 if ((params = physmem_copy_u32_from_vm(d->vm,*txd_addr)) & M32_TXDESC_HOLD)
456 return(FALSE);
457
458 *txd_addr = physmem_copy_u32_from_vm(d->vm,(*txd_addr)+8);
459 return(TRUE);
460 }
461
462 /* Scan a channel TX ring */
463 static inline int m32_tx_scan(struct m32_data *d,u_int chan_id)
464 {
465 struct m32_channel *chan = &d->channels[chan_id];
466 m_uint8_t pkt[M32_MAX_PKT_SIZE];
467 struct m32_tx_desc txd;
468 m_uint32_t pkt_len;
469
470 if (!chan->tx_current)
471 return(FALSE);
472
473 switch(chan->poll_mode) {
474 case 0:
475 m32_set_cfgw(d,M32_OFFSET_CTDA+(chan_id*4),chan->tx_current);
476
477 /* Try to transmit data */
478 if (!m32_tx_acquire(d,chan->tx_current,&txd))
479 return(FALSE);
480
481 printf("M32: TX scanner for channel %u (tx_current=0x%8.8x)\n",
482 chan_id,chan->tx_current);
483
484 printf("M32: params=0x%8.8x, next=0x%8.8x.\n",txd.params,txd.ntdp);
485
486 /* The descriptor has been acquired */
487 pkt_len = (txd.params & M32_TXDESC_NO_MASK) >> M32_TXDESC_NO_SHIFT;
488 physmem_copy_from_vm(d->vm,pkt,txd.tdp,pkt_len);
489
490 printf("M32: data_ptr=0x%x, len=%u\n",txd.tdp,pkt_len);
491 mem_dump(stdout,pkt,pkt_len);
492
493 /* Poll the next descriptor (wait for HOLD bit to be reset */
494 chan->poll_mode = 1;
495
496 if (txd.params & M32_TXDESC_FE) {
497 m32_post_interrupt(d,M32_II_FI | chan_id);
498 vm_set_irq(d->vm,2);
499 }
500
501 break;
502
503 case 1:
504 if (!m32_tx_acquire_next(d,&chan->tx_current))
505 return(FALSE);
506
507 printf("M32: branching on next descriptor 0x%x\n",chan->tx_current);
508 chan->poll_mode = 0;
509 break;
510 }
511
512 return(TRUE);
513 }
514
515 /* Scan the all channel TX rings */
516 static void m32_tx_scan_all_channels(struct m32_data *d)
517 {
518 u_int i;
519
520 for(i=0;i<M32_NR_CHANNELS;i++)
521 m32_tx_scan(d,i);
522 }
523
524 /*
525 * Handle an action request.
526 *
527 * IN, ICO and RES bits are mutually exclusive.
528 */
529 static int m32_action_req(struct m32_data *d,m_uint32_t action)
530 {
531 u_int chan_id;
532
533 /* Define a new Interrupt Queue */
534 if (action & M32_AS_IA) {
535 d->iq_base_addr = d->iq_cur_addr = m32_get_cfgw(d,4);
536 d->iq_size = ((m32_get_cfgw(d,8) & 0xFF) + 1) * 16 * sizeof(m_uint32_t);
537 }
538
539 /* Initialization Procedure */
540 if (action & M32_AS_IN) {
541 /* Fetch all timeslots assignments */
542 m32_fetch_all_ts(d);
543
544 /* Fetch specification of the specified channel */
545 chan_id = (action & M32_AS_CHAN_MASK) >> M32_AS_CHAN_SHIFT;
546 m32_fetch_chan_spec(d,chan_id);
547
548 /* Generate acknowledge */
549 if (!(action & M32_AS_IM))
550 m32_post_interrupt(d,M32_II_ARACK);
551 }
552
553 /* Initialize Channel Only */
554 if (action & M32_AS_ICO) {
555 /* Fetch specification of the specified channel */
556 chan_id = (action & M32_AS_CHAN_MASK) >> M32_AS_CHAN_SHIFT;
557 m32_fetch_chan_spec(d,chan_id);
558
559 /* Generate acknowledge */
560 if (!(action & M32_AS_IM))
561 m32_post_interrupt(d,M32_II_ARACK);
562 }
563
564 /* Reset */
565 if (action & M32_AS_RES) {
566 /* Fetch all timeslots assignments */
567 m32_fetch_all_ts(d);
568
569 /* Fetch all channel specifications */
570 m32_fetch_all_chan_spec(d);
571
572 /* Generate acknowledge */
573 if (!(action & M32_AS_IM))
574 m32_post_interrupt(d,M32_II_ARACK);
575 }
576
577 return(0);
578 }
579
580 /* Munich32 general access function */
581 static void *m32_gen_access(struct m32_data *d,cpu_mips_t *cpu,
582 m_uint32_t offset,u_int op_size,u_int op_type,
583 m_uint64_t *data)
584 {
585 u_int p;
586
587 switch(offset) {
588 /* Action Specification */
589 case 0x0:
590 if (op_type == MTS_WRITE)
591 m32_action_req(d,*data);
592 return NULL;
593
594 /* Configuration memory */
595 default:
596 switch(op_size) {
597 case 4:
598 if (op_type == MTS_READ)
599 *data = m32_get_cfgw(d,offset);
600 else
601 m32_set_cfgw(d,offset,*data);
602 break;
603
604 case 1:
605 if (op_type == MTS_READ) {
606 *data = m32_get_cfgw(d,offset & ~0x03);
607 *data >>= (24 - ((offset & 0x03) << 3));
608 *data &= 0xFF;
609 } else {
610 printf("UNSUPPORTED(1)!!!!\n");
611 }
612 break;
613
614 case 2:
615 if (op_type == MTS_READ) {
616 *data = m32_get_cfgw(d,offset & ~0x03);
617 *data >>= (16 - ((offset & 0x03) << 3));
618 *data &= 0xFFFF;
619 } else {
620 printf("UNSUPPORTED(2)!!!!\n");
621 }
622 break;
623
624 case 8:
625 if (op_type == MTS_READ) {
626 *data = (m_uint64_t)m32_get_cfgw(d,offset) << 32;
627 *data |= m32_get_cfgw(d,offset+4);
628 } else {
629 printf("UNSUPPORTED(8)!!!!\n");
630 }
631 break;
632
633 default:
634 printf("UNSUPPORTED (size=%u)!!!\n",op_size);
635 }
636 }
637
638 return NULL;
639 }
640
641 /*
642 * pa_4b_access()
643 */
644 void *pa_4b_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset,
645 u_int op_size,u_int op_type,m_uint64_t *data)
646 {
647 struct pa_4b_data *d = dev->priv_data;
648 static m_uint32_t test1,test2,test3;
649
650 if (op_type == MTS_READ)
651 *data = 0xFFFFFFFF;
652
653 #if DEBUG_ACCESS
654 if (offset >= MUNICH32_MEM_SIZE) {
655 if (op_type == MTS_READ) {
656 cpu_log(cpu,d->name,"read access to offset = 0x%x, pc = 0x%llx "
657 "(op_size=%u)\n",offset,cpu->pc,op_size);
658 } else {
659 cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, "
660 "val = 0x%llx (op_size=%u)\n",offset,cpu->pc,*data,op_size);
661 }
662 }
663 #endif
664
665 /* Specific cases */
666 switch(offset) {
667 case 0x40008:
668 if (op_type == MTS_READ)
669 *data = 0xFF;
670 break;
671
672 case 0x40030:
673 if (op_type == MTS_READ)
674 *data = 0xFF;
675 break;
676
677 case 0x40000:
678 if (op_type == MTS_READ)
679 *data = 0xFFFF;
680 break;
681
682 case 0x40020:
683 if (op_type == MTS_READ)
684 *data = 0xFFFFFFFF; //test2;
685 else
686 test2 = *data;
687 break;
688
689 case 0x40021:
690 if (op_type == MTS_READ)
691 *data = 0xFF; //test3;
692 else
693 test3 = *data;
694 break;
695
696 case 0x40023:
697 if (op_type == MTS_READ)
698 *data = 0xFF;
699 break;
700
701 case 0x40040:
702 if (op_type == MTS_READ)
703 *data = 0x04;
704 break;
705
706 /* Channels enabled ? */
707 case 0x40044:
708 if (op_type == MTS_READ)
709 *data = 0xFF; /* 0x02 */
710 break;
711
712 /* SID */
713 case 0x40050:
714 if (op_type == MTS_WRITE) {
715 test1 = *data;
716 } else {
717 switch(test1) {
718 case TP3420_SID_PUP:
719 *data = TP3420_SR_AI;
720 vm_set_irq(d->vm,C7200_PA_MGMT_IRQ);
721 break;
722 case TP3420_SID_ENST:
723 *data = 0xB0;
724 break;
725 default:
726 *data = 0x03;
727 break;
728 }
729 }
730 break;
731
732 default:
733 if (offset < MUNICH32_MEM_SIZE)
734 return(m32_gen_access(&d->m32_data,cpu,offset - d->m32_offset,
735 op_size,op_type,data));
736 }
737
738 return NULL;
739 }
740
741 /*
742 * pci_munich32_read()
743 */
744 static m_uint32_t pci_munich32_read(cpu_mips_t *cpu,struct pci_device *dev,
745 int reg)
746 {
747 struct pa_4b_data *d = dev->priv_data;
748
749 #if DEBUG_ACCESS
750 BRI_LOG(d,"read PCI register 0x%x\n",reg);
751 #endif
752 switch(reg) {
753 case PCI_REG_BAR0:
754 return(d->dev->phys_addr);
755 default:
756 return(0);
757 }
758 }
759
760 /*
761 * pci_munich32_write()
762 */
763 static void pci_munich32_write(cpu_mips_t *cpu,struct pci_device *dev,
764 int reg,m_uint32_t value)
765 {
766 struct pa_4b_data *d = dev->priv_data;
767
768 #if DEBUG_ACCESS
769 BRI_LOG(d,"write 0x%x to PCI register 0x%x\n",value,reg);
770 #endif
771
772 switch(reg) {
773 case PCI_REG_BAR0:
774 vm_map_device(cpu->vm,d->dev,(m_uint64_t)value);
775 BRI_LOG(d,"registers are mapped at 0x%x\n",value);
776 break;
777 }
778 }
779
780 /*
781 * dev_c7200_bri_init()
782 *
783 * Add a PA-4B/PA-8B port adapter into specified slot.
784 */
785 int dev_c7200_pa_bri_init(c7200_t *router,char *name,u_int pa_bay)
786 {
787 struct pci_device *pci_dev;
788 struct pa_4b_data *d;
789 struct vdevice *dev;
790
791 /* Allocate the private data structure for PA-4B chip */
792 if (!(d = malloc(sizeof(*d)))) {
793 fprintf(stderr,"%s (PA-4B): out of memory\n",name);
794 return(-1);
795 }
796
797 memset(d,0,sizeof(*d));
798 d->m32_offset = 0x08;
799 d->m32_data.vm = router->vm;
800
801 /* Set the EEPROM */
802 c7200_pa_set_eeprom(router,pa_bay,cisco_eeprom_find_pa("PA-4B"));
803
804 /* Add as PCI device PA-4B */
805 pci_dev = pci_dev_add(router->pa_bay[pa_bay].pci_map,name,
806 BRI_PCI_VENDOR_ID,BRI_PCI_PRODUCT_ID,
807 0,0,C7200_NETIO_IRQ,d,
808 NULL,pci_munich32_read,pci_munich32_write);
809
810 if (!pci_dev) {
811 fprintf(stderr,"%s (PA-4B): unable to create PCI device.\n",name);
812 return(-1);
813 }
814
815 /* Create the PA-4B structure */
816 d->name = name;
817 d->pci_dev = pci_dev;
818 d->vm = router->vm;
819
820 /* Create the device itself */
821 if (!(dev = dev_create(name))) {
822 fprintf(stderr,"%s (PA-4B): unable to create device.\n",name);
823 return(-1);
824 }
825
826 dev->phys_len = 0x800000;
827 dev->handler = pa_4b_access;
828
829 /* Store device info */
830 dev->priv_data = d;
831 d->dev = dev;
832
833 /* Map this device to the VM */
834 vm_bind_device(router->vm,dev);
835
836 /* Store device info into the router structure */
837 return(c7200_pa_set_drvinfo(router,pa_bay,d));
838 }
839
840 /* Remove a PA-4B from the specified slot */
841 int dev_c7200_pa_bri_shutdown(c7200_t *router,u_int pa_bay)
842 {
843 struct c7200_pa_bay *bay;
844 struct pa_4b_data *d;
845
846 if (!(bay = c7200_pa_get_info(router,pa_bay)))
847 return(-1);
848
849 d = bay->drv_info;
850
851 /* Remove the PA EEPROM */
852 c7200_pa_unset_eeprom(router,pa_bay);
853
854 /* Remove the PCI device */
855 pci_dev_remove(d->pci_dev);
856
857 /* Remove the device from the CPU address space */
858 vm_unbind_device(router->vm,d->dev);
859 cpu_group_rebuild_mts(router->vm->cpu_group);
860
861 /* Free the device structure itself */
862 free(d->dev);
863 free(d);
864 return(0);
865 }
866
867 /* Bind a Network IO descriptor to a specific port */
868 int dev_c7200_pa_bri_set_nio(c7200_t *router,u_int pa_bay,u_int port_id,
869 netio_desc_t *nio)
870 {
871 struct pa_4b_data *d;
872
873 if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay)))
874 return(-1);
875
876 if (d->nio != NULL)
877 return(-1);
878
879 d->nio = nio;
880
881 /* TEST */
882 d->m32_data.tx_tid = ptask_add((ptask_callback)m32_tx_scan_all_channels,&d->m32_data,NULL);
883
884 //netio_rxl_add(nio,(netio_rx_handler_t)dev_pa_4b_handle_rxring,d,NULL);
885 return(0);
886 }
887
888 /* Bind a Network IO descriptor to a specific port */
889 int dev_c7200_pa_bri_unset_nio(c7200_t *router,u_int pa_bay,u_int port_id)
890 {
891 struct pa_4b_data *d;
892
893 if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay)))
894 return(-1);
895
896 if (d->nio) {
897 /* TEST */
898 ptask_remove(d->m32_data.tx_tid);
899
900 //netio_rxl_remove(d->nio);
901 d->nio = NULL;
902 }
903 return(0);
904 }
905
906 /* PA-4B driver */
907 struct c7200_pa_driver dev_c7200_pa_4b_driver = {
908 "PA-4B", 0,
909 dev_c7200_pa_bri_init,
910 dev_c7200_pa_bri_shutdown,
911 dev_c7200_pa_bri_set_nio,
912 dev_c7200_pa_bri_unset_nio,
913 NULL,
914 };

  ViewVC Help
Powered by ViewVC 1.1.26