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

Annotation of /trunk/dev_c7200_bri.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (hide annotations)
Sat Oct 6 16:29:14 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7/dev_c7200_bri.c
File MIME type: text/plain
File size: 26408 byte(s)
dynamips-0.2.7

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

  ViewVC Help
Powered by ViewVC 1.1.26