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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 dpavlin 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     /* EEPROM definition (3D = PA-4B, 3E = PA-8B) */
289     static const m_uint16_t eeprom_pa_4b_data[64] = {
290     0x013D, 0x0202, 0xffff, 0xffff, 0x490C, 0x7806, 0x0000, 0x0000,
291     0x5000, 0x0000, 0x0208, 0x1900, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF,
292     };
293    
294     static const struct c7200_eeprom eeprom_pa_4b = {
295     "PA-4B", (m_uint16_t *)eeprom_pa_4b_data,
296     sizeof(eeprom_pa_4b_data)/2,
297     };
298    
299     /* Log a PA-4B/PA-8B message */
300     #define BRI_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)
301    
302     /* Read a configuration word */
303     static inline m_uint32_t m32_get_cfgw(struct m32_data *d,m_uint32_t offset)
304     {
305     return(d->cfg_mem[offset >> 2]);
306     }
307    
308     /* Write a configuration word */
309     static inline void m32_set_cfgw(struct m32_data *d,m_uint32_t offset,
310     m_uint32_t val)
311     {
312     d->cfg_mem[offset >> 2] = val;
313     }
314    
315     /* Post an interrupt into the interrupt queue */
316     static int m32_post_interrupt(struct m32_data *d,m_uint32_t iq_value)
317     {
318     if (!d->iq_base_addr)
319     return(-1);
320    
321     /* The INT bit is mandatory */
322     iq_value |= M32_II_INT;
323    
324     #if 0
325     printf("M32: Posting interrupt iq_val=0x%8.8x at 0x%8.8x\n",
326     iq_value,d->iq_cur_addr);
327     #endif
328    
329     physmem_copy_u32_to_vm(d->vm,d->iq_cur_addr,iq_value);
330     d->iq_cur_addr += sizeof(m_uint32_t);
331    
332     if (d->iq_cur_addr >= (d->iq_base_addr + d->iq_size))
333     d->iq_cur_addr = d->iq_base_addr;
334    
335     return(0);
336     }
337    
338     /* Fetch a timeslot assignment */
339     static int m32_fetch_ts_assign(struct m32_data *d,u_int ts_id)
340     {
341     m_uint32_t offset;
342    
343     offset = M32_OFFSET_TS + (ts_id * sizeof(m_uint32_t));
344     d->timeslots[ts_id] = m32_get_cfgw(d,offset);
345     return(0);
346     }
347    
348     /* Fetch all timeslot assignments */
349     static int m32_fetch_all_ts(struct m32_data *d)
350     {
351     m_uint32_t offset = M32_OFFSET_TS;
352     u_int i;
353    
354     for(i=0;i<M32_NR_TIMESLOTS;i++,offset+=sizeof(m_uint32_t))
355     d->timeslots[i] = m32_get_cfgw(d,offset);
356    
357     return(0);
358     }
359    
360     /* Show timeslots assignments (debugging) */
361     static void m32_show_ts_assign(struct m32_data *d)
362     {
363     m_uint32_t ts;
364     u_int i;
365    
366     printf("MUNICH32 timeslots:\n");
367    
368     for(i=0;i<M32_NR_TIMESLOTS;i++) {
369     ts = d->timeslots[i];
370    
371     if ((ts & (M32_TS_TTI|M32_TS_RTI)) != (M32_TS_TTI|M32_TS_RTI)) {
372     printf(" Timeslot %2u: ",i);
373    
374     if (!(ts & M32_TS_TTI)) {
375     printf("TCN=%2u TFM=0x%2.2x ",
376     (ts & M32_TS_TCN_MASK) >> M32_TS_TCN_SHIFT,
377     (ts & M32_TS_TFM_MASK) >> M32_TS_TFM_SHIFT);
378     }
379    
380     if (!(ts & M32_TS_RTI)) {
381     printf("RCN=%2u RFM=0x%2.2x",
382     (ts & M32_TS_RCN_MASK) >> M32_TS_RCN_SHIFT,
383     (ts & M32_TS_RFM_MASK) >> M32_TS_RFM_SHIFT);
384     }
385    
386     printf("\n");
387     }
388     }
389    
390     printf("\n");
391     }
392    
393     /* Show info about a channels (debugging) */
394     static void m32_show_channel(struct m32_data *d,u_int chan_id)
395     {
396     struct m32_channel *chan;
397    
398     chan = &d->channels[chan_id];
399     printf("M32 Channel %u:\n",chan_id);
400     printf(" Status : 0x%8.8x\n",chan->status);
401     printf(" FRDA : 0x%8.8x\n",chan->frda);
402     printf(" FTDA : 0x%8.8x\n",chan->ftda);
403     printf(" ITBS : 0x%8.8x\n",chan->itbs);
404     }
405    
406     /* Fetch a channel specification */
407     static int m32_fetch_chan_spec(struct m32_data *d,u_int chan_id)
408     {
409     struct m32_channel *chan;
410     m_uint32_t offset;
411    
412     offset = M32_OFFSET_CHAN + (chan_id * 4 * sizeof(m_uint32_t));
413     chan = &d->channels[chan_id];
414    
415     chan->status = m32_get_cfgw(d,offset);
416     chan->frda = m32_get_cfgw(d,offset+4);
417     chan->ftda = m32_get_cfgw(d,offset+8);
418     chan->itbs = m32_get_cfgw(d,offset+12);
419    
420     chan->poll_mode = 0;
421     chan->rx_current = chan->frda;
422     chan->tx_current = chan->ftda;
423    
424     m32_set_cfgw(d,M32_OFFSET_CTDA+(chan_id*4),chan->tx_current);
425    
426     #if 1
427     if (chan_id == 2) {
428     printf("M32: Fetched channel %u\n",chan_id);
429     //m32_show_ts_assign(d);
430     m32_show_channel(d,chan_id);
431     }
432     #endif
433     return(0);
434     }
435    
436     /* Fetch all channel specifications */
437     static void m32_fetch_all_chan_spec(struct m32_data *d)
438     {
439     u_int i;
440    
441     for(i=0;i<M32_NR_CHANNELS;i++)
442     m32_fetch_chan_spec(d,i);
443     }
444    
445     /* Try to acquire the specified TX descriptor */
446     static int m32_tx_acquire(struct m32_data *d,m_uint32_t txd_addr,
447     struct m32_tx_desc *txd)
448     {
449     m_uint32_t params;
450    
451     if (!(params = physmem_copy_u32_from_vm(d->vm,txd_addr)) & M32_TXDESC_HOLD)
452     return(FALSE);
453    
454     txd->params = params;
455     txd->tdp = physmem_copy_u32_from_vm(d->vm,txd_addr+4);
456     txd->ntdp = physmem_copy_u32_from_vm(d->vm,txd_addr+8);
457     return(TRUE);
458     }
459    
460     /* Try to acquire the next TX descriptor */
461     static int m32_tx_acquire_next(struct m32_data *d,m_uint32_t *txd_addr)
462     {
463     m_uint32_t params;
464    
465     /* HOLD bit must be reset */
466     if ((params = physmem_copy_u32_from_vm(d->vm,*txd_addr)) & M32_TXDESC_HOLD)
467     return(FALSE);
468    
469     *txd_addr = physmem_copy_u32_from_vm(d->vm,(*txd_addr)+8);
470     return(TRUE);
471     }
472    
473     /* Scan a channel TX ring */
474     static inline int m32_tx_scan(struct m32_data *d,u_int chan_id)
475     {
476     struct m32_channel *chan = &d->channels[chan_id];
477     m_uint8_t pkt[M32_MAX_PKT_SIZE];
478     struct m32_tx_desc txd;
479     m_uint32_t pkt_len;
480    
481     if (!chan->tx_current)
482     return(FALSE);
483    
484     switch(chan->poll_mode) {
485     case 0:
486     m32_set_cfgw(d,M32_OFFSET_CTDA+(chan_id*4),chan->tx_current);
487    
488     /* Try to transmit data */
489     if (!m32_tx_acquire(d,chan->tx_current,&txd))
490     return(FALSE);
491    
492     printf("M32: TX scanner for channel %u (tx_current=0x%8.8x)\n",
493     chan_id,chan->tx_current);
494    
495     printf("M32: params=0x%8.8x, next=0x%8.8x.\n",txd.params,txd.ntdp);
496    
497     /* The descriptor has been acquired */
498     pkt_len = (txd.params & M32_TXDESC_NO_MASK) >> M32_TXDESC_NO_SHIFT;
499     physmem_copy_from_vm(d->vm,pkt,txd.tdp,pkt_len);
500    
501     printf("M32: data_ptr=0x%x, len=%u\n",txd.tdp,pkt_len);
502     mem_dump(stdout,pkt,pkt_len);
503    
504     /* Poll the next descriptor (wait for HOLD bit to be reset */
505     chan->poll_mode = 1;
506    
507     if (txd.params & M32_TXDESC_FE) {
508     m32_post_interrupt(d,M32_II_FI | chan_id);
509     vm_set_irq(d->vm,2);
510     }
511    
512     break;
513    
514     case 1:
515     if (!m32_tx_acquire_next(d,&chan->tx_current))
516     return(FALSE);
517    
518     printf("M32: branching on next descriptor 0x%x\n",chan->tx_current);
519     chan->poll_mode = 0;
520     break;
521     }
522    
523     return(TRUE);
524     }
525    
526     /* Scan the all channel TX rings */
527     static void m32_tx_scan_all_channels(struct m32_data *d)
528     {
529     u_int i;
530    
531     for(i=0;i<M32_NR_CHANNELS;i++)
532     m32_tx_scan(d,i);
533     }
534    
535     /*
536     * Handle an action request.
537     *
538     * IN, ICO and RES bits are mutually exclusive.
539     */
540     static int m32_action_req(struct m32_data *d,m_uint32_t action)
541     {
542     u_int chan_id;
543    
544     /* Define a new Interrupt Queue */
545     if (action & M32_AS_IA) {
546     d->iq_base_addr = d->iq_cur_addr = m32_get_cfgw(d,4);
547     d->iq_size = ((m32_get_cfgw(d,8) & 0xFF) + 1) * 16 * sizeof(m_uint32_t);
548     }
549    
550     /* Initialization Procedure */
551     if (action & M32_AS_IN) {
552     /* Fetch all timeslots assignments */
553     m32_fetch_all_ts(d);
554    
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     /* Initialize Channel Only */
565     if (action & M32_AS_ICO) {
566     /* Fetch specification of the specified channel */
567     chan_id = (action & M32_AS_CHAN_MASK) >> M32_AS_CHAN_SHIFT;
568     m32_fetch_chan_spec(d,chan_id);
569    
570     /* Generate acknowledge */
571     if (!(action & M32_AS_IM))
572     m32_post_interrupt(d,M32_II_ARACK);
573     }
574    
575     /* Reset */
576     if (action & M32_AS_RES) {
577     /* Fetch all timeslots assignments */
578     m32_fetch_all_ts(d);
579    
580     /* Fetch all channel specifications */
581     m32_fetch_all_chan_spec(d);
582    
583     /* Generate acknowledge */
584     if (!(action & M32_AS_IM))
585     m32_post_interrupt(d,M32_II_ARACK);
586     }
587    
588     return(0);
589     }
590    
591     /* Munich32 general access function */
592     static void *m32_gen_access(struct m32_data *d,cpu_mips_t *cpu,
593     m_uint32_t offset,u_int op_size,u_int op_type,
594     m_uint64_t *data)
595     {
596     u_int p;
597    
598     switch(offset) {
599     /* Action Specification */
600     case 0x0:
601     if (op_type == MTS_WRITE)
602     m32_action_req(d,*data);
603     return NULL;
604    
605     /* Configuration memory */
606     default:
607     switch(op_size) {
608     case 4:
609     if (op_type == MTS_READ)
610     *data = m32_get_cfgw(d,offset);
611     else
612     m32_set_cfgw(d,offset,*data);
613     break;
614    
615     case 1:
616     if (op_type == MTS_READ) {
617     *data = m32_get_cfgw(d,offset & ~0x03);
618     *data >>= (24 - ((offset & 0x03) << 3));
619     *data &= 0xFF;
620     } else {
621     printf("UNSUPPORTED(1)!!!!\n");
622     }
623     break;
624    
625     case 2:
626     if (op_type == MTS_READ) {
627     *data = m32_get_cfgw(d,offset & ~0x03);
628     *data >>= (16 - ((offset & 0x03) << 3));
629     *data &= 0xFFFF;
630     } else {
631     printf("UNSUPPORTED(2)!!!!\n");
632     }
633     break;
634    
635     case 8:
636     if (op_type == MTS_READ) {
637     *data = (m_uint64_t)m32_get_cfgw(d,offset) << 32;
638     *data |= m32_get_cfgw(d,offset+4);
639     } else {
640     printf("UNSUPPORTED(8)!!!!\n");
641     }
642     break;
643    
644     default:
645     printf("UNSUPPORTED (size=%u)!!!\n",op_size);
646     }
647     }
648    
649     return NULL;
650     }
651    
652     /*
653     * pa_4b_access()
654     */
655     void *pa_4b_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset,
656     u_int op_size,u_int op_type,m_uint64_t *data)
657     {
658     struct pa_4b_data *d = dev->priv_data;
659     static m_uint32_t test1,test2,test3;
660    
661     if (op_type == MTS_READ)
662     *data = 0xFFFFFFFF;
663    
664     #if DEBUG_ACCESS
665     if (offset >= MUNICH32_MEM_SIZE) {
666     if (op_type == MTS_READ) {
667     cpu_log(cpu,d->name,"read access to offset = 0x%x, pc = 0x%llx "
668     "(op_size=%u)\n",offset,cpu->pc,op_size);
669     } else {
670     cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, "
671     "val = 0x%llx (op_size=%u)\n",offset,cpu->pc,*data,op_size);
672     }
673     }
674     #endif
675    
676     /* Specific cases */
677     switch(offset) {
678     case 0x40008:
679     if (op_type == MTS_READ)
680     *data = 0xFF;
681     break;
682    
683     case 0x40030:
684     if (op_type == MTS_READ)
685     *data = 0xFF;
686     break;
687    
688     case 0x40000:
689     if (op_type == MTS_READ)
690     *data = 0xFFFF;
691     break;
692    
693     case 0x40020:
694     if (op_type == MTS_READ)
695     *data = 0xFFFFFFFF; //test2;
696     else
697     test2 = *data;
698     break;
699    
700     case 0x40021:
701     if (op_type == MTS_READ)
702     *data = 0xFF; //test3;
703     else
704     test3 = *data;
705     break;
706    
707     case 0x40023:
708     if (op_type == MTS_READ)
709     *data = 0xFF;
710     break;
711    
712     case 0x40040:
713     if (op_type == MTS_READ)
714     *data = 0x04;
715     break;
716    
717     /* Channels enabled ? */
718     case 0x40044:
719     if (op_type == MTS_READ)
720     *data = 0xFF; /* 0x02 */
721     break;
722    
723     /* SID */
724     case 0x40050:
725     if (op_type == MTS_WRITE) {
726     test1 = *data;
727     } else {
728     switch(test1) {
729     case TP3420_SID_PUP:
730     *data = TP3420_SR_AI;
731     vm_set_irq(d->vm,C7200_PA_MGMT_IRQ);
732     break;
733     case TP3420_SID_ENST:
734     *data = 0xB0;
735     break;
736     default:
737     *data = 0x03;
738     break;
739     }
740     }
741     break;
742    
743     default:
744     if (offset < MUNICH32_MEM_SIZE)
745     return(m32_gen_access(&d->m32_data,cpu,offset - d->m32_offset,
746     op_size,op_type,data));
747     }
748    
749     return NULL;
750     }
751    
752     /*
753     * pci_munich32_read()
754     */
755     static m_uint32_t pci_munich32_read(cpu_mips_t *cpu,struct pci_device *dev,
756     int reg)
757     {
758     struct pa_4b_data *d = dev->priv_data;
759    
760     #if DEBUG_ACCESS
761     BRI_LOG(d,"read PCI register 0x%x\n",reg);
762     #endif
763     switch(reg) {
764     case PCI_REG_BAR0:
765     return(d->dev->phys_addr);
766     default:
767     return(0);
768     }
769     }
770    
771     /*
772     * pci_munich32_write()
773     */
774     static void pci_munich32_write(cpu_mips_t *cpu,struct pci_device *dev,
775     int reg,m_uint32_t value)
776     {
777     struct pa_4b_data *d = dev->priv_data;
778    
779     #if DEBUG_ACCESS
780     BRI_LOG(d,"write 0x%x to PCI register 0x%x\n",value,reg);
781     #endif
782    
783     switch(reg) {
784     case PCI_REG_BAR0:
785     vm_map_device(cpu->vm,d->dev,(m_uint64_t)value);
786     BRI_LOG(d,"registers are mapped at 0x%x\n",value);
787     break;
788     }
789     }
790    
791     /*
792     * dev_c7200_bri_init()
793     *
794     * Add a PA-4B/PA-8B port adapter into specified slot.
795     */
796     int dev_c7200_pa_bri_init(c7200_t *router,char *name,u_int pa_bay)
797     {
798     struct pci_device *pci_dev;
799     struct pa_4b_data *d;
800     struct vdevice *dev;
801    
802     /* Allocate the private data structure for PA-4B chip */
803     if (!(d = malloc(sizeof(*d)))) {
804     fprintf(stderr,"%s (PA-4B): out of memory\n",name);
805     return(-1);
806     }
807    
808     memset(d,0,sizeof(*d));
809     d->m32_offset = 0x08;
810     d->m32_data.vm = router->vm;
811    
812     /* Set the EEPROM */
813     c7200_pa_set_eeprom(router,pa_bay,&eeprom_pa_4b);
814    
815     /* Add as PCI device PA-4B */
816     pci_dev = pci_dev_add(router->pa_bay[pa_bay].pci_map,name,
817     BRI_PCI_VENDOR_ID,BRI_PCI_PRODUCT_ID,
818     0,0,C7200_NETIO_IRQ,d,
819     NULL,pci_munich32_read,pci_munich32_write);
820    
821     if (!pci_dev) {
822     fprintf(stderr,"%s (PA-4B): unable to create PCI device.\n",name);
823     return(-1);
824     }
825    
826     /* Create the PA-4B structure */
827     d->name = name;
828     d->pci_dev = pci_dev;
829     d->vm = router->vm;
830    
831     /* Create the device itself */
832     if (!(dev = dev_create(name))) {
833     fprintf(stderr,"%s (PA-4B): unable to create device.\n",name);
834     return(-1);
835     }
836    
837     dev->phys_len = 0x800000;
838     dev->handler = pa_4b_access;
839    
840     /* Store device info */
841     dev->priv_data = d;
842     d->dev = dev;
843    
844     /* Map this device to the VM */
845     vm_bind_device(router->vm,dev);
846    
847     /* Store device info into the router structure */
848     return(c7200_pa_set_drvinfo(router,pa_bay,d));
849     }
850    
851     /* Remove a PA-4B from the specified slot */
852     int dev_c7200_pa_bri_shutdown(c7200_t *router,u_int pa_bay)
853     {
854     struct c7200_pa_bay *bay;
855     struct pa_4b_data *d;
856    
857     if (!(bay = c7200_pa_get_info(router,pa_bay)))
858     return(-1);
859    
860     d = bay->drv_info;
861    
862     /* Remove the PA EEPROM */
863     c7200_pa_unset_eeprom(router,pa_bay);
864    
865     /* Remove the PCI device */
866     pci_dev_remove(d->pci_dev);
867    
868     /* Remove the device from the CPU address space */
869     vm_unbind_device(router->vm,d->dev);
870     cpu_group_rebuild_mts(router->vm->cpu_group);
871    
872     /* Free the device structure itself */
873     free(d->dev);
874     free(d);
875     return(0);
876     }
877    
878     /* Bind a Network IO descriptor to a specific port */
879     int dev_c7200_pa_bri_set_nio(c7200_t *router,u_int pa_bay,u_int port_id,
880     netio_desc_t *nio)
881     {
882     struct pa_4b_data *d;
883    
884     if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay)))
885     return(-1);
886    
887     if (d->nio != NULL)
888     return(-1);
889    
890     d->nio = nio;
891    
892     /* TEST */
893     d->m32_data.tx_tid = ptask_add((ptask_callback)m32_tx_scan_all_channels,&d->m32_data,NULL);
894    
895     //netio_rxl_add(nio,(netio_rx_handler_t)dev_pa_4b_handle_rxring,d,NULL);
896     return(0);
897     }
898    
899     /* Bind a Network IO descriptor to a specific port */
900     int dev_c7200_pa_bri_unset_nio(c7200_t *router,u_int pa_bay,u_int port_id)
901     {
902     struct pa_4b_data *d;
903    
904     if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay)))
905     return(-1);
906    
907     if (d->nio) {
908     /* TEST */
909     ptask_remove(d->m32_data.tx_tid);
910    
911     //netio_rxl_remove(d->nio);
912     d->nio = NULL;
913     }
914     return(0);
915     }
916    
917     /* PA-4B driver */
918     struct c7200_pa_driver dev_c7200_pa_4b_driver = {
919     "PA-4B", 0,
920     dev_c7200_pa_bri_init,
921     dev_c7200_pa_bri_shutdown,
922     dev_c7200_pa_bri_set_nio,
923     dev_c7200_pa_bri_unset_nio,
924     };

  ViewVC Help
Powered by ViewVC 1.1.26