source: rtems/c/src/lib/libbsp/sparc/shared/tmtc/grtm.c @ 4a7d1026

4.11
Last change on this file since 4a7d1026 was 4a7d1026, checked in by Daniel Hellstrom <daniel@…>, on Apr 13, 2015 at 8:25:52 AM

sparc bsps: updated license to rtems.org

  • Property mode set to 100644
File size: 43.4 KB
Line 
1/* GRTM CCSDS Telemetry Encoder driver
2 *
3 * COPYRIGHT (c) 2007.
4 * Cobham Gaisler AB.
5 *
6 * The license and distribution terms for this file may be
7 * found in the file LICENSE in this distribution or at
8 * http://www.rtems.org/license/LICENSE.
9 */
10
11#include <bsp.h>
12#include <rtems/libio.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16#include <assert.h>
17#include <ctype.h>
18#include <malloc.h>
19#include <rtems/bspIo.h>
20
21#include <drvmgr/drvmgr.h>
22#include <ambapp.h>
23#include <drvmgr/ambapp_bus.h>
24#include <bsp/grtm.h>
25
26#ifndef IRQ_GLOBAL_PREPARE
27 #define IRQ_GLOBAL_PREPARE(level) rtems_interrupt_level level
28#endif
29
30#ifndef IRQ_GLOBAL_DISABLE
31 #define IRQ_GLOBAL_DISABLE(level) rtems_interrupt_disable(level)
32#endif
33
34#ifndef IRQ_GLOBAL_ENABLE
35 #define IRQ_GLOBAL_ENABLE(level) rtems_interrupt_enable(level)
36#endif
37
38/*
39#define DEBUG
40#define DEBUGFUNCS
41*/
42
43#include <bsp/debug_defs.h>
44
45/* GRTM register map */
46struct grtm_regs {
47        volatile unsigned int   dma_ctrl;       /* DMA Control Register (0x00) */
48        volatile unsigned int   dma_status;     /* DMA Status Register (0x04) */
49        volatile unsigned int   dma_len;        /* DMA Length Register (0x08) */       
50        volatile unsigned int   dma_bd;         /* DMA Descriptor Pointer Register (0x0c) */
51
52        volatile unsigned int   dma_cfg;        /* DMA Configuration Register (0x10) */
53        volatile unsigned int   revision;       /* GRTM Revision Register (0x14) */
54
55        int unused0[(0x80-0x18)/4];
56
57        volatile unsigned int   ctrl;           /* TM Control Register (0x80) */
58        volatile unsigned int   status;         /* TM Status Register (0x84) */
59        volatile unsigned int   cfg;            /* TM Configuration Register (0x88) */
60        volatile unsigned int   size;           /* TM Size Register (0x8c) */
61
62        volatile unsigned int   phy;            /* TM Physical Layer Register (0x90) */
63        volatile unsigned int   code;           /* TM Coding Sub-Layer Register (0x94) */
64        volatile unsigned int   asmr;           /* TM Attached Synchronization Marker Register (0x98) */
65
66        int unused1;
67
68        volatile unsigned int   all_frm;        /* TM All Frames Generation Register (0xa0) */
69        volatile unsigned int   mst_frm;        /* TM Master Channel Frame Generation Register (0xa4) */
70        volatile unsigned int   idle_frm;       /* TM Idle Frame Generation Register (0xa8) */
71
72        int unused2[(0xc0-0xac)/4];
73
74        volatile unsigned int   fsh[4];         /* TM FSH/Insert Zone Registers (0xc0..0xcc) */
75
76        volatile unsigned int   ocf;            /* TM Operational Control Field Register (0xd0) */
77};
78
79/* DMA Control Register (0x00) */
80#define GRTM_DMA_CTRL_EN_BIT    0
81#define GRTM_DMA_CTRL_IE_BIT    1
82#define GRTM_DMA_CTRL_TXRST_BIT 2
83#define GRTM_DMA_CTRL_RST_BIT   3
84#define GRTM_DMA_CTRL_TFIE_BIT  4
85
86#define GRTM_DMA_CTRL_EN        (1<<GRTM_DMA_CTRL_EN_BIT)
87#define GRTM_DMA_CTRL_IE        (1<<GRTM_DMA_CTRL_IE_BIT)
88#define GRTM_DMA_CTRL_TXRST     (1<<GRTM_DMA_CTRL_TXRST_BIT)
89#define GRTM_DMA_CTRL_RST       (1<<GRTM_DMA_CTRL_RST_BIT)
90#define GRTM_DMA_CTRL_TFIE      (1<<GRTM_DMA_CTRL_TFIE_BIT)
91
92/* DMA Status Register (0x04) */
93#define GRTM_DMA_STS_TE_BIT     0
94#define GRTM_DMA_STS_TI_BIT     1
95#define GRTM_DMA_STS_TA_BIT     2
96#define GRTM_DMA_STS_TFF_BIT    3
97#define GRTM_DMA_STS_TFS_BIT    4
98
99#define GRTM_DMA_STS_TE         (1<<GRTM_DMA_STS_TE_BIT)
100#define GRTM_DMA_STS_TI         (1<<GRTM_DMA_STS_TI_BIT)
101#define GRTM_DMA_STS_TA         (1<<GRTM_DMA_STS_TA_BIT)
102#define GRTM_DMA_STS_TFF        (1<<GRTM_DMA_STS_TFF_BIT)
103#define GRTM_DMA_STS_TFS        (1<<GRTM_DMA_STS_TFS_BIT)
104#define GRTM_DMA_STS_ALL        0x1f
105
106/* DMA Length Register (0x08) */
107#define GRTM_DMA_LEN_LEN_BIT    0
108#define GRTM_DMA_LEN_LIM_BIT    16
109
110#define GRTM_DMA_LEN_LEN        (0x7ff<<GRTM_DMA_LEN_LEN_BIT)
111#define GRTM_DMA_LEN_LIM        (0x3ff<<GRTM_DMA_LEN_LIM_BIT)
112
113/* DMA Descriptor Pointer Register (0x0c) */
114#define GRTM_DMA_BD_INDEX_BIT   0
115#define GRTM_DMA_BD_BASE_BIT    10
116
117#define GRTM_DMA_BD_INDEX       (0x3ff<<GRTM_DMA_BD_INDEX_BIT)
118#define GRTM_DMA_BD_BASE        (0xfffffc<<GRTM_DMA_BD_BASE_BIT)
119
120/* DMA Configuration Register (0x10) */
121#define GRTM_DMA_CFG_BLKSZ_BIT  0
122#define GRTM_DMA_CFG_FIFOSZ_BIT 16
123
124#define GRTM_DMA_CFG_BLKSZ      (0xffff<<GRTM_DMA_CFG_BLKSZ_BIT)
125#define GRTM_DMA_CFG_FIFOSZ     (0xffff<<GRTM_DMA_CFG_FIFOSZ_BIT)
126
127/* TM Control Register (0x80) */
128#define GRTM_CTRL_EN_BIT        0
129
130#define GRTM_CTRL_EN            (1<<GRTM_CTRL_EN_BIT)
131
132/* TM Status Register (0x84) - Unused */
133
134/* TM Configuration Register (0x88) */
135#define GRTM_CFG_SC_BIT         0
136#define GRTM_CFG_SP_BIT         1
137#define GRTM_CFG_CE_BIT         2
138#define GRTM_CFG_NRZ_BIT        3
139#define GRTM_CFG_PSR_BIT        4
140#define GRTM_CFG_TE_BIT         5
141#define GRTM_CFG_RSDEP_BIT      6
142#define GRTM_CFG_RS_BIT         9
143#define GRTM_CFG_AASM_BIT       11
144#define GRTM_CFG_FECF_BIT       12
145#define GRTM_CFG_OCF_BIT        13
146#define GRTM_CFG_EVC_BIT        14
147#define GRTM_CFG_IDLE_BIT       15
148#define GRTM_CFG_FSH_BIT        16
149#define GRTM_CFG_MCG_BIT        17
150#define GRTM_CFG_IZ_BIT         18
151#define GRTM_CFG_FHEC_BIT       19
152#define GRTM_CFG_AOS_BIT        20
153#define GRTM_CFG_CIF_BIT        21
154#define GRTM_CFG_OCFB_BIT       22
155
156#define GRTM_CFG_SC             (1<<GRTM_CFG_SC_BIT)
157#define GRTM_CFG_SP             (1<<GRTM_CFG_SP_BIT)
158#define GRTM_CFG_CE             (1<<GRTM_CFG_CE_BIT)
159#define GRTM_CFG_NRZ            (1<<GRTM_CFG_NRZ_BIT)
160#define GRTM_CFG_PSR            (1<<GRTM_CFG_PSR_BIT)
161#define GRTM_CFG_TE             (1<<GRTM_CFG_TE_BIT)
162#define GRTM_CFG_RSDEP          (0x7<<GRTM_CFG_RSDEP_BIT)
163#define GRTM_CFG_RS             (0x3<<GRTM_CFG_RS_BIT)
164#define GRTM_CFG_AASM           (1<<GRTM_CFG_AASM_BIT)
165#define GRTM_CFG_FECF           (1<<GRTM_CFG_FECF_BIT)
166#define GRTM_CFG_OCF            (1<<GRTM_CFG_OCF_BIT)
167#define GRTM_CFG_EVC            (1<<GRTM_CFG_EVC_BIT)
168#define GRTM_CFG_IDLE           (1<<GRTM_CFG_IDLE_BIT)
169#define GRTM_CFG_FSH            (1<<GRTM_CFG_FSH_BIT)
170#define GRTM_CFG_MCG            (1<<GRTM_CFG_MCG_BIT)
171#define GRTM_CFG_IZ             (1<<GRTM_CFG_IZ_BIT)
172#define GRTM_CFG_FHEC           (1<<GRTM_CFG_FHEC_BIT)
173#define GRTM_CFG_AOS            (1<<GRTM_CFG_AOS_BIT)
174#define GRTM_CFG_CIF            (1<<GRTM_CFG_CIF_BIT)
175#define GRTM_CFG_OCFB           (1<<GRTM_CFG_OCFB_BIT)
176
177/* TM Size Register (0x8c) */
178#define GRTM_SIZE_BLKSZ_BIT     0
179#define GRTM_SIZE_FIFOSZ_BIT    8
180#define GRTM_SIZE_LEN_BIT       20
181
182#define GRTM_SIZE_BLKSZ         (0xff<<GRTM_SIZE_BLKSZ_BIT)
183#define GRTM_SIZE_FIFOSZ        (0xfff<<GRTM_SIZE_FIFOSZ_BIT)
184#define GRTM_SIZE_LEN           (0xfff<<GRTM_SIZE_LEN_BIT)
185
186/* TM Physical Layer Register (0x90) */
187#define GRTM_PHY_SUB_BIT        0
188#define GRTM_PHY_SCF_BIT        15
189#define GRTM_PHY_SYM_BIT        16
190#define GRTM_PHY_SF_BIT         31
191
192#define GRTM_PHY_SUB            (0x7fff<<GRTM_PHY_SUB_BIT)
193#define GRTM_PHY_SCF            (1<<GRTM_PHY_SCF_BIT)
194#define GRTM_PHY_SYM            (0x7fff<<GRTM_PHY_SYM_BIT)
195#define GRTM_PHY_SF             (1<<GRTM_PHY_SF_BIT)
196
197/* TM Coding Sub-Layer Register (0x94) */
198#define GRTM_CODE_SC_BIT        0
199#define GRTM_CODE_SP_BIT        1
200#define GRTM_CODE_CERATE_BIT    2
201#define GRTM_CODE_CE_BIT        5
202#define GRTM_CODE_NRZ_BIT       6
203#define GRTM_CODE_PSR_BIT       7
204#define GRTM_CODE_RS8_BIT       11
205#define GRTM_CODE_RSDEP_BIT     12
206#define GRTM_CODE_RS_BIT        15
207#define GRTM_CODE_AASM_BIT      16
208#define GRTM_CODE_CSEL_BIT      17
209
210#define GRTM_CODE_SC            (1<<GRTM_CODE_SC_BIT)
211#define GRTM_CODE_SP            (1<<GRTM_CODE_SP_BIT)
212#define GRTM_CODE_CERATE        (0x7<<GRTM_CODE_CERATE_BIT)
213#define GRTM_CODE_CE            (1<<GRTM_CODE_CE_BIT)
214#define GRTM_CODE_NRZ           (1<<GRTM_CODE_NRZ_BIT)
215#define GRTM_CODE_PSR           (1<<GRTM_CODE_PSR_BIT)
216#define GRTM_CODE_RS8           (1<<GRTM_CODE_RS8_BIT)
217#define GRTM_CODE_RSDEP         (0x7<<GRTM_CODE_RSDEP_BIT)
218#define GRTM_CODE_RS            (1<<GRTM_CODE_RS_BIT)
219#define GRTM_CODE_AASM          (1<<GRTM_CODE_AASM_BIT)
220#define GRTM_CODE_CSEL          (0x3<<GRTM_CODE_CSEL_BIT)
221
222/* TM Attached Synchronization Marker Register (0x98) */
223#define GRTM_ASM_BIT            0
224
225#define GRTM_ASM                0xffffffff
226
227/* TM All Frames Generation Register (0xa0) */
228#define GRTM_ALL_LEN_BIT        0
229#define GRTM_ALL_VER_BIT        12
230#define GRTM_ALL_FHEC_BIT       14
231#define GRTM_ALL_FECF_BIT       15
232#define GRTM_ALL_IZ_BIT         16
233#define GRTM_ALL_IZLEN_BIT      17
234
235#define GRTM_ALL_LEN            (0x7ff<<GRTM_ALL_LEN_BIT)
236#define GRTM_ALL_VER            (0x3<<GRTM_ALL_VER_BIT)
237#define GRTM_ALL_FHEC           (1<<GRTM_ALL_FHEC_BIT)
238#define GRTM_ALL_FECF           (1<<GRTM_ALL_FECF_BIT)
239#define GRTM_ALL_IZ             (1<<GRTM_ALL_IZ_BIT)
240#define GRTM_ALL_IZLEN          (0x1f<<GRTM_ALL_IZLEN_BIT)
241
242/* TM Master Channel Frame Generation Register (0xa4) */
243#define GRTM_MST_OW_BIT         0
244#define GRTM_MST_OCF_BIT        1
245#define GRTM_MST_FSH_BIT        2
246#define GRTM_MST_MC_BIT         3
247#define GRTM_MST_MCCNTR_BIT     24
248
249#define GRTM_MST_OW             (1<<GRTM_MST_OW_BIT)
250#define GRTM_MST_OCF            (1<<GRTM_MST_OCF_BIT)
251#define GRTM_MST_FSH            (1<<GRTM_MST_FSH_BIT)
252#define GRTM_MST_MC             (0xff<<GRTM_MST_MC_BIT)
253
254/* TM Idle Frame Generation Register (0xa8) */
255#define GRTM_IDLE_SCID_BIT      0
256#define GRTM_IDLE_VCID_BIT      10
257#define GRTM_IDLE_MC_BIT        16
258#define GRTM_IDLE_VCC_BIT       17
259#define GRTM_IDLE_FSH_BIT       18
260#define GRTM_IDLE_EVC_BIT       19
261#define GRTM_IDLE_OCF_BIT       20
262#define GRTM_IDLE_IDLE_BIT      21
263#define GRTM_IDLE_MCCNTR_BIT    24
264
265#define GRTM_IDLE_SCID          (0x3ff<<GRTM_IDLE_SCID_BIT)
266#define GRTM_IDLE_VCID          (0x3f<<GRTM_IDLE_VCID_BIT)
267#define GRTM_IDLE_MC            (1<<GRTM_IDLE_MC_BIT)
268#define GRTM_IDLE_VCC           (1<<GRTM_IDLE_VCC_BIT)
269#define GRTM_IDLE_FSH           (1<<GRTM_IDLE_FSH_BIT)
270#define GRTM_IDLE_EVC           (1<<GRTM_IDLE_EVC_BIT)
271#define GRTM_IDLE_OCF           (1<<GRTM_IDLE_OCF_BIT)
272#define GRTM_IDLE_IDLE          (1<<GRTM_IDLE_IDLE_BIT)
273#define GRTM_IDLE_MCCNTR        (0xff<<GRTM_IDLE_MCCNTR_BIT)
274
275/* TM FSH/Insert Zone Registers (0xc0..0xcc) */
276#define GRTM_FSH_DATA_BIT       0
277
278#define GRTM_FSH_DATA           0xffffffff
279
280
281/* TM Operational Control Field Register (0xd0) */
282#define GRTM_OCF_CLCW_BIT       0
283
284#define GRTM_OCF_CLCW           0xffffffff
285
286
287/* GRTM Revision 0 */
288#define GRTM_REV0_DMA_CTRL_TXRDY_BIT    5
289#define GRTM_REV0_DMA_CTRL_TXRDY        (1<<GRTM_REV0_DMA_CTRL_TXRDY_BIT)
290
291/* GRTM Revision 1 */
292#define GRTM_REV1_DMA_STS_TXRDY_BIT     6
293#define GRTM_REV1_DMA_STS_TXSTAT_BIT    7
294#define GRTM_REV1_DMA_STS_TXRDY         (1<<GRTM_REV1_DMA_STS_TXRDY_BIT)
295#define GRTM_REV1_DMA_STS_TXSTAT        (1<<GRTM_REV1_DMA_STS_TXSTAT_BIT)
296
297#define GRTM_REV1_REV_SREV_BIT          0
298#define GRTM_REV1_REV_MREV_BIT          8
299#define GRTM_REV1_REV_TIRQ_BIT          16
300#define GRTM_REV1_REV_SREV              (0xff<<GRTM_REV1_REV_SREV_BIT)
301#define GRTM_REV1_REV_MREV              (0xff<<GRTM_REV1_REV_MREV_BIT)
302#define GRTM_REV1_REV_TIRQ              (1<<GRTM_REV1_REV_TIRQ_BIT)
303
304
305/* GRTM transmit descriptor (0x400 Alignment need) */
306struct grtm_bd {
307        volatile unsigned int   ctrl;
308        unsigned int            address;
309};
310
311#define GRTM_BD_EN_BIT          0
312#define GRTM_BD_WR_BIT          1
313#define GRTM_BD_IE_BIT          2
314#define GRTM_BD_FECFB_BIT       3
315#define GRTM_BD_IZB_BIT         4
316#define GRTM_BD_FHECB_BIT       5
317#define GRTM_BD_OCFB_BIT        6
318#define GRTM_BD_FSHB_BIT        7
319#define GRTM_BD_MCB_BIT         8
320#define GRTM_BD_VCE_BIT         9
321#define GRTM_BD_TS_BIT          14
322#define GRTM_BD_UE_BIT          15
323
324#define GRTM_BD_EN              (1<<GRTM_BD_EN_BIT)
325#define GRTM_BD_WR              (1<<GRTM_BD_WR_BIT)
326#define GRTM_BD_IE              (1<<GRTM_BD_IE_BIT)
327#define GRTM_BD_FECFB           (1<<GRTM_BD_FECFB_BIT)
328#define GRTM_BD_IZB             (1<<GRTM_BD_IZB_BIT)
329#define GRTM_BD_FHECB           (1<<GRTM_BD_FHECB_BIT)
330#define GRTM_BD_OCFB            (1<<GRTM_BD_OCFB_BIT)
331#define GRTM_BD_FSHB            (1<<GRTM_BD_FSHB_BIT)
332#define GRTM_BD_MCB             (1<<GRTM_BD_MCB_BIT)
333#define GRTM_BD_VCE             (1<<GRTM_BD_VCE_BIT)
334#define GRTM_BD_TS              (1<<GRTM_BD_TS_BIT)
335#define GRTM_BD_UE              (1<<GRTM_BD_UE_BIT)
336
337/* Load register */
338
339#define READ_REG(address)       (*(volatile unsigned int *)address)
340
341/* Driver functions */
342static rtems_device_driver grtm_initialize(rtems_device_major_number  major, rtems_device_minor_number  minor, void *arg);
343static rtems_device_driver grtm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
344static rtems_device_driver grtm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
345static rtems_device_driver grtm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
346static rtems_device_driver grtm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
347static rtems_device_driver grtm_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg);
348
349#define GRTM_DRIVER_TABLE_ENTRY { grtm_initialize, grtm_open, grtm_close, grtm_read, grtm_write, grtm_ioctl }
350
351static rtems_driver_address_table grtm_driver = GRTM_DRIVER_TABLE_ENTRY;
352
353/* Structure that connects BD with SoftWare Frame */
354struct grtm_ring {
355        struct grtm_ring        *next;
356        struct grtm_bd          *bd;
357        struct grtm_frame       *frm;
358};
359
360struct grtm_priv {
361        struct drvmgr_dev       *dev;           /* Driver manager device */
362        char                    devName[32];    /* Device Name */
363        struct grtm_regs        *regs;
364        int                     irq;
365        int                     minor;
366        int                     subrev;         /* GRTM Revision */
367
368        int                     open;
369        int                     running;
370
371        struct grtm_bd          *bds;
372        void                    *_bds;
373
374        /* Interrupt generation */
375        int                     enable_cnt_curr;/* Down counter, when 0 the interrupt bit is set for next descriptor */
376        volatile int            handling_transmission;  /* Tells ISR if user are active changing descriptors/queues */
377
378        struct grtm_ring        *_ring;         /* Root of ring */
379        struct grtm_ring        *ring;          /* Next ring to use for new frames to be transmitted */
380        struct grtm_ring        *ring_end;      /* Oldest activated ring used */
381
382        /* Collections of frames Ready to sent/ Scheduled for transmission/Sent
383         * frames waiting for the user to reclaim
384         */
385        struct grtm_list        ready;          /* Frames Waiting for free BDs */
386        struct grtm_list        scheduled;      /* Frames in BDs beeing transmitted */
387        struct grtm_list        sent;           /* Sent Frames waiting for user to reclaim and reuse */
388
389        /* Number of frames in the lists */
390        int                     ready_cnt;      /* Number of ready frames */
391        int                     scheduled_cnt;  /* Number of scheduled frames */
392        int                     sent_cnt;       /* Number of sent frames */
393
394        struct grtm_ioc_hw      hw_avail;       /* Hardware support available */
395        struct grtm_ioc_config  config;
396        struct grtm_ioc_stats   stats;
397
398        rtems_id                sem_tx;
399};
400
401/* Prototypes */
402static void *grtm_memalign(unsigned int boundary, unsigned int length, void *realbuf);
403static void grtm_hw_reset(struct grtm_priv *pDev);
404static void grtm_interrupt(void *arg);
405
406/* Common Global Variables */
407static rtems_id grtm_dev_sem;
408static int grtm_driver_io_registered = 0;
409static rtems_device_major_number grtm_driver_io_major = 0;
410
411/******************* Driver manager interface ***********************/
412
413/* Driver prototypes */
414static int grtm_register_io(rtems_device_major_number *m);
415static int grtm_device_init(struct grtm_priv *pDev);
416
417static int grtm_init2(struct drvmgr_dev *dev);
418static int grtm_init3(struct drvmgr_dev *dev);
419
420static struct drvmgr_drv_ops grtm_ops = 
421{
422        {NULL, grtm_init2, grtm_init3, NULL},
423        NULL,
424        NULL
425};
426
427static struct amba_dev_id grtm_ids[] = 
428{
429        {VENDOR_GAISLER, GAISLER_GRTM},
430        {0, 0}          /* Mark end of table */
431};
432
433static struct amba_drv_info grtm_drv_info =
434{
435        {
436                DRVMGR_OBJ_DRV,                 /* Driver */
437                NULL,                           /* Next driver */
438                NULL,                           /* Device list */
439                DRIVER_AMBAPP_GAISLER_GRTM_ID,  /* Driver ID */
440                "GRTM_DRV",                     /* Driver Name */
441                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
442                &grtm_ops,
443                NULL,                           /* Funcs */
444                0,                              /* No devices yet */
445                0,
446        },
447        &grtm_ids[0]
448};
449
450void grtm_register_drv (void)
451{
452        DBG("Registering GRTM driver\n");
453        drvmgr_drv_register(&grtm_drv_info.general);
454}
455
456static int grtm_init2(struct drvmgr_dev *dev)
457{
458        struct grtm_priv *priv;
459
460        DBG("GRTM[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
461        priv = dev->priv = malloc(sizeof(struct grtm_priv));
462        if ( !priv )
463                return DRVMGR_NOMEM;
464        memset(priv, 0, sizeof(*priv));
465        priv->dev = dev;
466
467        /* This core will not find other cores, so we wait for init2() */
468
469        return DRVMGR_OK;
470}
471
472static int grtm_init3(struct drvmgr_dev *dev)
473{
474        struct grtm_priv *priv;
475        char prefix[32];
476        rtems_status_code status;
477
478        priv = dev->priv;
479
480        /* Do initialization */
481
482        if ( grtm_driver_io_registered == 0) {
483                /* Register the I/O driver only once for all cores */
484                if ( grtm_register_io(&grtm_driver_io_major) ) {
485                        /* Failed to register I/O driver */
486                        dev->priv = NULL;
487                        return DRVMGR_FAIL;
488                }
489
490                grtm_driver_io_registered = 1;
491        }
492
493        /* I/O system registered and initialized
494         * Now we take care of device initialization.
495         */
496        if ( grtm_device_init(priv) ) {
497                return DRVMGR_FAIL;
498        }
499
500        /* Get Filesystem name prefix */
501        prefix[0] = '\0';
502        if ( drvmgr_get_dev_prefix(dev, prefix) ) {
503                /* Failed to get prefix, make sure of a unique FS name
504                 * by using the driver minor.
505                 */
506                sprintf(priv->devName, "/dev/grtm%d", dev->minor_drv);
507        } else {
508                /* Got special prefix, this means we have a bus prefix
509                 * And we should use our "bus minor"
510                 */
511                sprintf(priv->devName, "/dev/%sgrtm%d", prefix, dev->minor_bus);
512        }
513
514        /* Register Device */
515        status = rtems_io_register_name(priv->devName, grtm_driver_io_major, dev->minor_drv);
516        if (status != RTEMS_SUCCESSFUL) {
517                return DRVMGR_FAIL;
518        }
519
520        return DRVMGR_OK;
521}
522
523/******************* Driver Implementation ***********************/
524
525static int grtm_register_io(rtems_device_major_number *m)
526{
527        rtems_status_code r;
528
529        if ((r = rtems_io_register_driver(0, &grtm_driver, m)) == RTEMS_SUCCESSFUL) {
530                DBG("GRTM driver successfully registered, major: %d\n", *m);
531        } else {
532                switch(r) {
533                case RTEMS_TOO_MANY:
534                        printk("GRTM rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
535                        return -1;
536                case RTEMS_INVALID_NUMBER: 
537                        printk("GRTM rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
538                        return -1;
539                case RTEMS_RESOURCE_IN_USE:
540                        printk("GRTM rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
541                        return -1;
542                default:
543                        printk("GRTM rtems_io_register_driver failed\n");
544                        return -1;
545                }
546        }
547        return 0;
548}
549
550static int grtm_device_init(struct grtm_priv *pDev)
551{
552        struct amba_dev_info *ambadev;
553        struct ambapp_core *pnpinfo;
554        union drvmgr_key_value *value;
555
556        /* Get device information from AMBA PnP information */
557        ambadev = (struct amba_dev_info *)pDev->dev->businfo;
558        if ( ambadev == NULL ) {
559                return -1;
560        }
561        pnpinfo = &ambadev->info;
562        pDev->irq = pnpinfo->irq;
563        pDev->regs = (struct grtm_regs *)pnpinfo->apb_slv->start;
564        pDev->minor = pDev->dev->minor_drv;
565        pDev->open = 0;
566        pDev->running = 0;
567
568        /* Create Binary RX Semaphore with count = 0 */
569        if ( rtems_semaphore_create(rtems_build_name('G', 'R', 'M', '0' + pDev->minor),
570                0,
571                RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\
572                RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, 
573                0,
574                &pDev->sem_tx) != RTEMS_SUCCESSFUL ) {
575                return -1;
576        }
577
578        /* Allocate Memory for Buffer Descriptor Table, or let user provide a custom
579         * address.
580         */
581        value = drvmgr_dev_key_get(pDev->dev, "bdTabAdr", KEY_TYPE_POINTER);
582        if ( value ) {
583                pDev->bds = (struct grtm_bd *)value->ptr;
584                pDev->_bds = (void *)value->ptr;       
585        } else {
586                pDev->bds = (struct grtm_bd *)grtm_memalign(0x400, 0x400, &pDev->_bds);
587        }
588        if ( !pDev->bds ) {
589                DBG("GRTM: Failed to allocate descriptor table\n");
590                return -1;
591        }
592        memset(pDev->bds, 0, 0x400);
593
594        pDev->_ring = malloc(sizeof(struct grtm_ring) * 128);
595        if ( !pDev->_ring ) {
596                return -1;
597        }
598
599        /* Reset Hardware before attaching IRQ handler */
600        grtm_hw_reset(pDev);
601
602        /* Read SUB revision number, ignore  */
603        pDev->subrev = (READ_REG(&pDev->regs->revision) & GRTM_REV1_REV_SREV)
604                        >> GRTM_REV1_REV_SREV_BIT;
605
606        return 0;
607}
608
609
610static inline void grtm_list_clr(struct grtm_list *list)
611{
612        list->head = NULL;
613        list->tail = NULL;
614}
615
616static void grtm_hw_reset(struct grtm_priv *pDev)
617{
618        /* Reset Core */
619        pDev->regs->dma_ctrl = GRTM_DMA_CTRL_RST;
620}
621
622static void grtm_hw_get_implementation(struct grtm_priv *pDev, struct grtm_ioc_hw *hwcfg)
623{
624        unsigned int cfg = READ_REG(&pDev->regs->cfg);
625
626        hwcfg->cs       = (cfg & GRTM_CFG_SC)   ? 1:0;
627        hwcfg->sp       = (cfg & GRTM_CFG_SP)   ? 1:0;
628        hwcfg->ce       = (cfg & GRTM_CFG_CE)   ? 1:0;
629        hwcfg->nrz      = (cfg & GRTM_CFG_NRZ)  ? 1:0;
630        hwcfg->psr      = (cfg & GRTM_CFG_PSR)  ? 1:0;
631        hwcfg->te       = (cfg & GRTM_CFG_TE)   ? 1:0;
632        hwcfg->rsdep    = (cfg & GRTM_CFG_RSDEP)>>GRTM_CFG_RSDEP_BIT;
633        hwcfg->rs       = (cfg & GRTM_CFG_RS)>>GRTM_CFG_RS_BIT;
634        hwcfg->aasm     = (cfg & GRTM_CFG_AASM) ? 1:0;
635        hwcfg->fecf     = (cfg & GRTM_CFG_FECF) ? 1:0;
636        hwcfg->ocf      = (cfg & GRTM_CFG_OCF)  ? 1:0;
637        hwcfg->evc      = (cfg & GRTM_CFG_EVC)  ? 1:0;
638        hwcfg->idle     = (cfg & GRTM_CFG_IDLE) ? 1:0;
639        hwcfg->fsh      = (cfg & GRTM_CFG_FSH)  ? 1:0;
640        hwcfg->mcg      = (cfg & GRTM_CFG_MCG)  ? 1:0;
641        hwcfg->iz       = (cfg & GRTM_CFG_IZ)   ? 1:0;
642        hwcfg->fhec     = (cfg & GRTM_CFG_FHEC) ? 1:0;
643        hwcfg->aos      = (cfg & GRTM_CFG_AOS)  ? 1:0;
644        hwcfg->cif      = (cfg & GRTM_CFG_CIF)  ? 1:0;
645        hwcfg->ocfb     = (cfg & GRTM_CFG_OCFB) ? 1:0;
646
647        cfg = READ_REG(&pDev->regs->dma_cfg);
648        hwcfg->blk_size = (cfg & GRTM_DMA_CFG_BLKSZ) >> GRTM_DMA_CFG_BLKSZ_BIT;
649        hwcfg->fifo_size= (cfg & GRTM_DMA_CFG_FIFOSZ) >> GRTM_DMA_CFG_FIFOSZ_BIT;
650}
651
652
653/* TODO: Implement proper default calculation from hardware configuration */
654static void grtm_hw_get_default_modes(struct grtm_ioc_config *cfg, struct grtm_ioc_hw *hwcfg)
655{
656        cfg->mode = GRTM_MODE_TM;
657        cfg->frame_length = 223;
658        cfg->limit = 0; /* Make driver auto configure it on START, user may override with non-zero value */
659        cfg->as_marker = 0x1ACFFC1D;
660
661        /* Physical */
662        cfg->phy_subrate = 1;
663        cfg->phy_symbolrate = 1;
664        cfg->phy_opts = 0;
665
666        /* Coding Layer */
667        cfg->code_rsdep = 1;
668        cfg->code_ce_rate = 0;
669        cfg->code_csel = 0;
670        cfg->code_opts = 0;
671
672        /* All Frame Generation */
673        cfg->all_izlen = 0;
674        cfg->all_opts = GRTM_IOC_ALL_FECF;
675
676        /* Master Channel Frame Generation */
677        if ( hwcfg->mcg ) {
678                cfg->mf_opts = GRTM_IOC_MF_MC;
679        } else {
680                cfg->mf_opts = 0;
681        }
682
683        /* Idle Frame Generation */
684        cfg->idle_scid = 0;
685        cfg->idle_vcid = 0;
686        if ( hwcfg->idle ) {
687                cfg->idle_opts = GRTM_IOC_IDLE_EN;
688        } else {
689                cfg->idle_opts = 0;
690        }
691
692        /* Interrupt options */
693        cfg->blocking = 0;      /* non-blocking mode is default */
694        cfg->enable_cnt = 16;   /* generate interrupt every 16 descriptor */
695        cfg->isr_desc_proc = 1; /* Let interrupt handler do descriptor processing */
696        cfg->timeout = RTEMS_NO_TIMEOUT;
697       
698}
699
700static void *grtm_memalign(unsigned int boundary, unsigned int length, void *realbuf)
701{
702        *(int *)realbuf = (int)malloc(length+boundary);
703        DBG("GRTM: Alloced %d (0x%x) bytes, requested: %d\n",length+boundary,length+boundary,length);
704        return (void *)(((*(unsigned int *)realbuf)+boundary) & ~(boundary-1));
705}
706
707static int grtm_hw_set_config(struct grtm_priv *pDev, struct grtm_ioc_config *cfg, struct grtm_ioc_hw *hwcfg)
708{
709        struct grtm_regs *regs = pDev->regs;
710        unsigned int tmp;
711        unsigned int limit;
712
713        if ( cfg->limit == 0 ) {
714                /* Calculate Limit */
715                if ( cfg->frame_length > hwcfg->blk_size ) {
716                        limit = hwcfg->blk_size*2;
717                } else {
718                        limit = cfg->frame_length;
719                }
720        } else {
721                /* Use user configured limit */
722                limit = cfg->limit;
723        }
724
725        /* Frame Length and Limit */
726        regs->dma_len = (((limit-1) << GRTM_DMA_LEN_LIM_BIT) & GRTM_DMA_LEN_LIM)|
727                        (((cfg->frame_length-1) << GRTM_DMA_LEN_LEN_BIT) & GRTM_DMA_LEN_LEN);
728
729        /* Physical layer options */
730        tmp =   (cfg->phy_opts & (GRTM_IOC_PHY_SCF|GRTM_IOC_PHY_SF)) | 
731                (((cfg->phy_symbolrate-1)<<GRTM_PHY_SYM_BIT) & GRTM_PHY_SYM) | (((cfg->phy_subrate-1)<<GRTM_PHY_SUB_BIT) & GRTM_PHY_SUB);
732        regs->phy = tmp;
733
734        /* Coding Sub-layer Options */
735        tmp =   (cfg->code_opts & GRTM_IOC_CODE_ALL) | ((cfg->code_csel<<GRTM_CODE_CSEL_BIT) & GRTM_CODE_CSEL) |
736                (((cfg->code_rsdep-1)<<GRTM_CODE_RSDEP_BIT) & GRTM_CODE_RSDEP) | ((cfg->code_ce_rate<<GRTM_CODE_CERATE_BIT) & GRTM_CODE_CERATE);
737        regs->code = tmp;
738
739        /* Attached synchronization marker register */
740        regs->asmr = cfg->as_marker;
741
742        /* All Frames Generation */
743        tmp =   ((cfg->all_opts & GRTM_IOC_ALL_ALL)<<14) | 
744                ((cfg->all_izlen<<GRTM_ALL_IZLEN_BIT) & GRTM_ALL_IZLEN) |
745                ((cfg->mode<<GRTM_ALL_VER_BIT) & GRTM_ALL_VER);
746        regs->all_frm = tmp;
747
748        /* Master Frame Generation */
749        regs->mst_frm = cfg->mf_opts & GRTM_IOC_MF_ALL;
750
751        /* Idle frame Generation */
752        tmp =   ((cfg->idle_opts & GRTM_IOC_IDLE_ALL) << 16) |
753                ((cfg->idle_vcid << GRTM_IDLE_VCID_BIT) & GRTM_IDLE_VCID) |
754                ((cfg->idle_scid << GRTM_IDLE_SCID_BIT) & GRTM_IDLE_SCID);
755        regs->idle_frm = tmp;
756
757        return 0;
758}
759
760static int grtm_start(struct grtm_priv *pDev)
761{
762        struct grtm_regs *regs = pDev->regs;
763        int i;
764        struct grtm_ioc_config *cfg = &pDev->config;
765        unsigned int txrdy;
766
767        /* Clear Descriptors */
768        memset(pDev->bds,0,0x400);
769       
770        /* Clear stats */
771        memset(&pDev->stats,0,sizeof(struct grtm_ioc_stats));
772       
773        /* Init Descriptor Ring */
774        memset(pDev->_ring,0,sizeof(struct grtm_ring)*128);
775        for(i=0;i<127;i++){
776                pDev->_ring[i].next = &pDev->_ring[i+1];
777                pDev->_ring[i].bd = &pDev->bds[i];
778                pDev->_ring[i].frm = NULL;
779        }
780        pDev->_ring[127].next = &pDev->_ring[0];
781        pDev->_ring[127].bd = &pDev->bds[127];
782        pDev->_ring[127].frm = NULL;
783
784        pDev->ring = &pDev->_ring[0];
785        pDev->ring_end = &pDev->_ring[0];
786
787        /* Clear Scheduled, Ready and Sent list */
788        grtm_list_clr(&pDev->ready);
789        grtm_list_clr(&pDev->scheduled);
790        grtm_list_clr(&pDev->sent);
791
792        /* Software init */
793        pDev->handling_transmission = 0;
794       
795        /* Reset the transmitter */
796        regs->dma_ctrl = GRTM_DMA_CTRL_TXRST;
797        regs->dma_ctrl = 0;     /* Leave Reset */
798
799        /* Clear old interrupts */
800        regs->dma_status = GRTM_DMA_STS_ALL;
801
802        /* Set Descriptor Pointer Base register to point to first descriptor */
803        drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA, (void *)pDev->bds,
804                                (void **)&regs->dma_bd, 0x400);
805
806        /* Set hardware options as defined by config */
807        if ( grtm_hw_set_config(pDev, cfg, &pDev->hw_avail) ) {
808                return RTEMS_IO_ERROR;
809        }
810
811        /* Enable TM Transmitter */
812        regs->ctrl = GRTM_CTRL_EN;
813
814        /* Wait for TXRDY to be cleared */
815        i=1000;
816        while( i > 0 ) {
817                asm volatile ("nop"::);
818                i--;
819        }
820
821        /* Check transmitter startup OK */
822        i = 1000000;
823        do {
824                /* Location of TXRDY Bit is different for different revisions */
825                if ( pDev->subrev == 0 ) {
826                        txrdy = READ_REG(&regs->dma_ctrl) &
827                                GRTM_REV0_DMA_CTRL_TXRDY;
828                } else {
829                        txrdy = READ_REG(&regs->dma_status) &
830                                GRTM_REV1_DMA_STS_TXRDY;
831                }
832                if (txrdy != 0)
833                        break;
834
835                asm volatile ("nop"::);
836        } while ( --i > 0 );
837        if ( i == 0 ) {
838                /* Reset Failed */
839                DBG("GRTM: start: Reseting transmitter failed (%d)\n",i);
840                return RTEMS_IO_ERROR;
841        }
842        DBG("GRTM: reset time %d\n",i);
843
844        /* Everything is configured, the TM transmitter is started
845         * and idle frames has been sent.
846         */
847
848        /* Mark running before enabling the DMA transmitter */
849        pDev->running = 1;
850
851        /* Enable interrupts (Error and DMA TX) */
852        regs->dma_ctrl = GRTM_DMA_CTRL_IE;
853
854        DBG("GRTM: STARTED\n");
855
856        return RTEMS_SUCCESSFUL;
857}
858
859static void grtm_stop(struct grtm_priv *pDev)
860{
861        struct grtm_regs *regs = pDev->regs;
862
863        /* Disable the transmitter & Interrupts */
864        regs->dma_ctrl = 0;
865       
866        /* Clear any pending interrupt  */
867        regs->dma_status = GRTM_DMA_STS_ALL;
868
869        DBG("GRTM: STOPPED\n");
870
871        /* Flush semaphore in case a thread is stuck waiting for TX Interrupts */
872        rtems_semaphore_flush(pDev->sem_tx);
873}
874
875static rtems_device_driver grtm_open(
876        rtems_device_major_number major, 
877        rtems_device_minor_number minor, 
878        void *arg)
879{
880        struct grtm_priv *pDev;
881        struct drvmgr_dev *dev;
882
883        FUNCDBG();
884
885        if ( drvmgr_get_dev(&grtm_drv_info.general, minor, &dev) ) {
886                DBG("Wrong minor %d\n", minor);
887                return RTEMS_INVALID_NUMBER;
888        }
889        pDev = (struct grtm_priv *)dev->priv;
890       
891        /* Wait until we get semaphore */
892        if ( rtems_semaphore_obtain(grtm_dev_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL ){
893                return RTEMS_INTERNAL_ERROR;
894        }
895
896        /* Is device in use? */
897        if ( pDev->open ){
898                rtems_semaphore_release(grtm_dev_sem);
899                return RTEMS_RESOURCE_IN_USE;
900        }
901       
902        /* Mark device taken */
903        pDev->open = 1;
904       
905        rtems_semaphore_release(grtm_dev_sem);
906       
907        DBG("grtm_open: OPENED minor %d (pDev: 0x%x)\n",pDev->minor,(unsigned int)pDev);
908       
909        /* Set defaults */
910        pDev->config.timeout = RTEMS_NO_TIMEOUT;        /* no timeout (wait forever) */
911        pDev->config.blocking = 0;                      /* polling mode */
912       
913        pDev->running = 0;                              /* not in running mode yet */
914
915        memset(&pDev->config,0,sizeof(pDev->config));
916       
917        /* The core has been reset when we execute here, so it is possible
918         * to read out what HW is implemented from core.
919         */
920        grtm_hw_get_implementation(pDev, &pDev->hw_avail);
921
922        /* Get default modes */
923        grtm_hw_get_default_modes(&pDev->config,&pDev->hw_avail);
924       
925        return RTEMS_SUCCESSFUL;
926}
927
928static rtems_device_driver grtm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
929{
930        struct grtm_priv *pDev;
931        struct drvmgr_dev *dev;
932
933        FUNCDBG();
934
935        if ( drvmgr_get_dev(&grtm_drv_info.general, minor, &dev) ) {
936                return RTEMS_INVALID_NUMBER;
937        }
938        pDev = (struct grtm_priv *)dev->priv;
939
940        if ( pDev->running ){
941                grtm_stop(pDev);
942                pDev->running = 0;
943        }
944       
945        /* Reset core */
946        grtm_hw_reset(pDev);
947
948        /* Clear descriptor area just for sure */
949        memset(pDev->bds, 0, 0x400);
950       
951        /* Mark not open */
952        pDev->open = 0;
953
954        return RTEMS_SUCCESSFUL;
955}
956
957static rtems_device_driver grtm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
958{
959        FUNCDBG();
960        return RTEMS_NOT_IMPLEMENTED;
961}
962
963static rtems_device_driver grtm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
964{
965        FUNCDBG();
966        return RTEMS_NOT_IMPLEMENTED;
967}
968
969/* Scans the desciptor table for scheduled frames that has been sent,
970 * and moves these frames from the head of the scheduled queue to the
971 * tail of the sent queue.
972 *
973 * Also, for all frames the status is updated.
974 *
975 * Return Value
976 * Number of frames freed.
977 */
978static int grtm_free_sent(struct grtm_priv *pDev)
979{
980        struct grtm_ring *curr;
981        struct grtm_frame *last_frm, *first_frm;
982        int freed_frame_cnt=0;
983        unsigned int ctrl;
984
985        curr = pDev->ring_end;
986
987        /* Step into TX ring to find sent frames */
988        if ( !curr->frm ){
989                /* No scheduled frames, abort */
990                return 0;
991        }
992
993        /* There has been messages scheduled ==> scheduled messages may have been
994         * transmitted and needs to be collected.
995         */
996
997        first_frm = curr->frm;
998
999        /* Loop until first enabled unsent frame is found.
1000         * A unused descriptor is indicated by an unassigned frm field
1001         */
1002        while ( curr->frm && !((ctrl=READ_REG(&curr->bd->ctrl)) & GRTM_BD_EN) ){
1003                /* Handle one sent Frame */
1004               
1005                /* Remember last handled frame so that insertion/removal from
1006                 * frames lists go fast.
1007                 */
1008                last_frm = curr->frm;
1009               
1010                /* 1. Set flags to indicate error(s) and other information */
1011                last_frm->flags |= GRTM_FLAGS_SENT; /* Mark sent */
1012               
1013                /* Update Stats */
1014                pDev->stats.frames_sent++;
1015   
1016                /* Did packet encounter link error? */
1017                if ( ctrl & GRTM_BD_UE ) {
1018                        pDev->stats.err_underrun++;
1019                        last_frm->flags |= GRRM_FLAGS_ERR;
1020                }
1021
1022                curr->frm = NULL; /* Mark unused */
1023
1024                /* Increment */
1025                curr = curr->next;
1026                freed_frame_cnt++;
1027        }
1028
1029        /* 1. Remove all handled frames from scheduled queue
1030         * 2. Put all handled frames into sent queue
1031         */
1032        if ( freed_frame_cnt > 0 ){
1033
1034                /* Save TX ring posistion */
1035                pDev->ring_end = curr;
1036
1037                /* Remove all sent frames from scheduled list */
1038                if ( pDev->scheduled.tail == last_frm ){
1039                        /* All scheduled frames sent... */
1040                        pDev->scheduled.head = NULL;
1041                        pDev->scheduled.tail = NULL;
1042                }else{
1043                        pDev->scheduled.head = last_frm->next;
1044                }
1045                last_frm->next = NULL;
1046
1047                /* Put all sent frames into "Sent queue" for user to
1048                 * collect, later on.
1049                 */
1050                if ( !pDev->sent.head ){
1051                        /* Sent queue empty */
1052                        pDev->sent.head = first_frm;
1053                        pDev->sent.tail = last_frm;
1054                }else{
1055                        pDev->sent.tail->next = first_frm;
1056                        pDev->sent.tail = last_frm;
1057                }
1058        }
1059        return freed_frame_cnt;
1060}
1061
1062
1063/* Moves as many frames in the ready queue (as there are free descriptors for)
1064 * to the scheduled queue. The free descriptors are then assigned one frame
1065 * each and enabled for transmission.
1066 *
1067 * Return Value
1068 * Returns number of frames moved from ready to scheduled queue
1069 */
1070static int grtm_schedule_ready(struct grtm_priv *pDev, int ints_off)
1071{
1072        int cnt;
1073        unsigned int ctrl, dmactrl;
1074        struct grtm_ring *curr_bd;
1075        struct grtm_frame *curr_frm, *last_frm;
1076        IRQ_GLOBAL_PREPARE(oldLevel);
1077
1078        if ( !pDev->ready.head ){
1079                return 0;
1080        }
1081
1082        cnt=0;
1083        curr_frm = pDev->ready.head;
1084        curr_bd = pDev->ring;
1085        while( !curr_bd->frm ){
1086                /* Assign frame to descriptor */
1087                curr_bd->frm = curr_frm;
1088
1089                /* Prepare descriptor address. Three cases:
1090                 *  - GRTM core on same bus as CPU ==> no translation (Address used by CPU = address used by GRTM)
1091                 *  - GRTM core on remote bus, and payload address given as used by CPU ==> Translation needed
1092                 *  - GRTM core on remote bus, and payload address given as used by GRTM ==> no translation  [ USER does custom translation]
1093                 */
1094                if ( curr_frm->flags & (GRTM_FLAGS_TRANSLATE|GRTM_FLAGS_TRANSLATE_AND_REMEMBER) ) {
1095                        /* Do translation */
1096                        drvmgr_translate(pDev->dev, CPUMEM_TO_DMA, (void *)curr_frm->payload, (void **)&curr_bd->bd->address);
1097                        if ( curr_frm->flags & GRTM_FLAGS_TRANSLATE_AND_REMEMBER ) {
1098                                if ( curr_frm->payload != (unsigned int *)curr_bd->bd->address ) {
1099                                        /* Translation needed */
1100                                        curr_frm->flags &= ~GRTM_FLAGS_TRANSLATE_AND_REMEMBER;
1101                                        curr_frm->flags |= GRTM_FLAGS_TRANSLATE;
1102                                } else {
1103                                        /* No Trnaslation needed */
1104                                        curr_frm->flags &= ~(GRTM_FLAGS_TRANSLATE|GRTM_FLAGS_TRANSLATE_AND_REMEMBER);
1105                                }
1106                        }
1107                } else {
1108                        /* Custom translation or no translation needed */
1109                        curr_bd->bd->address = (unsigned int)curr_frm->payload;
1110                }
1111
1112                ctrl = GRTM_BD_EN;
1113                if ( curr_bd->next == pDev->_ring ){
1114                        ctrl |= GRTM_BD_WR; /* Wrap around */
1115                }
1116                /* Apply user options/flags */
1117                ctrl |= (curr_frm->flags & GRTM_FLAGS_MASK);
1118
1119                /* Is this Frame going to be an interrupt Frame? */
1120                if ( (--pDev->enable_cnt_curr) <= 0 ){
1121                        if ( pDev->config.enable_cnt == 0 ){
1122                                pDev->enable_cnt_curr = 0x3fffffff;
1123                        }else{
1124                                pDev->enable_cnt_curr = pDev->config.enable_cnt;
1125                                ctrl |= GRTM_BD_IE;
1126                        }
1127                }
1128
1129                /* Enable descriptor */
1130                curr_bd->bd->ctrl = ctrl;
1131
1132                last_frm = curr_frm;
1133                curr_bd = curr_bd->next;
1134                cnt++;
1135               
1136                /* Get Next Frame from Ready Queue */
1137                if ( curr_frm == pDev->ready.tail ){
1138                        /* Handled all in ready queue. */
1139                        curr_frm = NULL;
1140                        break;
1141                }
1142                curr_frm = curr_frm->next;
1143        }
1144       
1145        /* Has frames have been scheduled? */
1146        if ( cnt > 0 ){
1147                /* Make last frame mark end of chain, probably pointless... */
1148                last_frm->next = NULL;
1149
1150                /* Insert scheduled packets into scheduled queue */
1151                if ( !pDev->scheduled.head ){
1152                        /* empty scheduled queue */
1153                        pDev->scheduled.head = pDev->ready.head;
1154                        pDev->scheduled.tail = last_frm;
1155                }else{
1156                        pDev->scheduled.tail->next = pDev->ready.head;
1157                        pDev->scheduled.tail = last_frm;
1158                }
1159
1160                /* Remove scheduled packets from ready queue */
1161                pDev->ready.head = curr_frm;
1162                if ( !curr_frm ){
1163                        pDev->ready.tail = NULL;
1164                }
1165
1166                /* Update TX ring posistion */
1167                pDev->ring = curr_bd;
1168                if ( !ints_off ) {
1169                        IRQ_GLOBAL_DISABLE(oldLevel);
1170                }
1171
1172                /* Make hardware aware of the newly enabled descriptors */
1173                dmactrl = READ_REG(&pDev->regs->dma_ctrl);
1174                dmactrl &= ~(GRTM_DMA_CTRL_TXRST | GRTM_DMA_CTRL_RST);
1175                dmactrl |= GRTM_DMA_CTRL_EN;
1176                pDev->regs->dma_ctrl = dmactrl;
1177               
1178                if ( !ints_off ) {
1179                        IRQ_GLOBAL_ENABLE(oldLevel);
1180                }
1181        }
1182        return cnt;
1183}
1184
1185
1186static rtems_device_driver grtm_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
1187{
1188        struct grtm_priv *pDev;
1189        struct drvmgr_dev *dev;
1190        rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *)arg;
1191        unsigned int *data = ioarg->buffer;
1192        int status;
1193        struct grtm_ioc_config *cfg;
1194        struct grtm_ioc_hw_status *hwregs;
1195        IRQ_GLOBAL_PREPARE(oldLevel);
1196        struct grtm_list *chain;
1197        struct grtm_frame *curr;
1198        struct grtm_ioc_hw *hwimpl;
1199        struct grtm_ioc_stats *stats;
1200        int num,ret;
1201
1202        FUNCDBG();
1203
1204        if ( drvmgr_get_dev(&grtm_drv_info.general, minor, &dev) ) {
1205                return RTEMS_INVALID_NUMBER;
1206        }
1207        pDev = (struct grtm_priv *)dev->priv;
1208
1209        if (!ioarg)
1210                return RTEMS_INVALID_NAME;
1211
1212        ioarg->ioctl_return = 0;
1213        switch(ioarg->command) {
1214                case GRTM_IOC_START:
1215                if ( pDev->running ) {
1216                        return RTEMS_RESOURCE_IN_USE; /* EBUSY */
1217                }
1218                if ( (status=grtm_start(pDev)) != RTEMS_SUCCESSFUL ){
1219                        return status;
1220                }
1221                /* Register ISR & Enable interrupt */
1222                drvmgr_interrupt_register(dev, 0, "grtm", grtm_interrupt, pDev);
1223
1224                /* Read and write are now open... */
1225                break;
1226
1227                case GRTM_IOC_STOP:
1228                if ( !pDev->running ) {
1229                        return RTEMS_RESOURCE_IN_USE;
1230                }
1231
1232                /* Disable interrupts */
1233                drvmgr_interrupt_unregister(dev, 0, grtm_interrupt, pDev);
1234                grtm_stop(pDev);
1235                pDev->running = 0;
1236                break;
1237
1238                case GRTM_IOC_ISSTARTED:
1239                if ( !pDev->running ) {
1240                        return RTEMS_RESOURCE_IN_USE;
1241                }
1242                break;
1243
1244                case GRTM_IOC_SET_BLOCKING_MODE:
1245                if ( (unsigned int)data > GRTM_BLKMODE_BLK ) {
1246                        return RTEMS_INVALID_NAME;
1247                }
1248                DBG("GRTM: Set blocking mode: %d\n",(unsigned int)data);
1249                pDev->config.blocking = (unsigned int)data;
1250                break;
1251
1252                case GRTM_IOC_SET_TIMEOUT:
1253                DBG("GRTM: Timeout: %d\n",(unsigned int)data);
1254                pDev->config.timeout = (rtems_interval)data;
1255                break;
1256
1257                case GRTM_IOC_SET_CONFIG:
1258                cfg = (struct grtm_ioc_config *)data;
1259                if ( !cfg ) {
1260                        return RTEMS_INVALID_NAME;
1261                }
1262               
1263                if ( pDev->running ) {
1264                        return RTEMS_RESOURCE_IN_USE;
1265                }
1266
1267                pDev->config = *cfg;
1268                break;
1269
1270                case GRTM_IOC_GET_STATS:
1271                stats = (struct grtm_ioc_stats *)data;
1272                if ( !stats ) {
1273                        return RTEMS_INVALID_NAME;
1274                }
1275                memcpy(stats,&pDev->stats,sizeof(struct grtm_ioc_stats));
1276                break;
1277
1278                case GRTM_IOC_CLR_STATS:
1279                memset(&pDev->stats,0,sizeof(struct grtm_ioc_stats));
1280                break;
1281
1282                case GRTM_IOC_GET_CONFIG:
1283                cfg = (struct grtm_ioc_config *)data;
1284                if ( !cfg ) {
1285                        return RTEMS_INVALID_NAME;
1286                }
1287
1288                *cfg = pDev->config;
1289                break;
1290
1291                case GRTM_IOC_GET_OCFREG:
1292                if ( !pDev->hw_avail.ocf ) {
1293                        /* Hardware does not implement the OCF register */
1294                        return RTEMS_NOT_DEFINED;
1295                }
1296                if ( !data ) {
1297                        return RTEMS_INVALID_NAME;
1298                }
1299                *(unsigned int **)data = (unsigned int *)&pDev->regs->ocf;
1300                break;
1301
1302                case GRTM_IOC_GET_HW_IMPL:
1303                hwimpl = (struct grtm_ioc_hw *)data;
1304                if ( !hwimpl ) {
1305                        return RTEMS_INVALID_NAME;
1306                }
1307                *hwimpl = pDev->hw_avail;
1308                break;
1309
1310                case GRTM_IOC_GET_HW_STATUS:
1311                hwregs = (struct grtm_ioc_hw_status *)data;
1312                if ( !hwregs ) {
1313                        return RTEMS_INVALID_NAME;
1314                }
1315                /* We disable interrupt in order to get a snapshot of the registers */
1316                IRQ_GLOBAL_DISABLE(oldLevel);
1317/* TODO: implement hwregs */
1318                IRQ_GLOBAL_ENABLE(oldLevel);
1319                break;
1320
1321                /* Put a chain of frames at the back of the "Ready frames" queue. This
1322                 * triggers the driver to put frames from the Ready queue into unused
1323                 * available descriptors. (Ready -> Scheduled)
1324                 */
1325
1326                case GRTM_IOC_SEND:
1327                if ( !pDev->running ){
1328                        return RTEMS_RESOURCE_IN_USE;
1329                }
1330                num=0;
1331
1332                /* Get pointer to frame chain wished be sent */
1333                chain = (struct grtm_list *)ioarg->buffer;
1334                if ( !chain ){
1335                        /* No new frames to send ==> just trigger hardware
1336                         * to send previously made ready frames to be sent.
1337                         */
1338                        pDev->handling_transmission = 1;
1339                        goto trigger_transmission;
1340                }
1341                if ( !chain->tail || !chain->head ){
1342                        return RTEMS_INVALID_NAME;
1343                }
1344
1345                DBG("GRTM_SEND: head: 0x%x, tail: 0x%x\n",chain->head,chain->tail);
1346
1347                /* Mark ready frames unsent by clearing GRTM_FLAGS_SENT of all frames */
1348
1349                curr = chain->head;
1350                while(curr != chain->tail){
1351                        curr->flags = curr->flags & ~(GRTM_FLAGS_SENT|GRRM_FLAGS_ERR);
1352                        curr = curr->next;
1353                        num++;
1354                }
1355                curr->flags = curr->flags & ~(GRTM_FLAGS_SENT|GRRM_FLAGS_ERR);
1356                num++;
1357
1358                pDev->handling_transmission = 1;
1359                /* 1. Put frames into ready queue
1360                 *    (New Frames->READY)
1361                 */
1362                if ( pDev->ready.head ){
1363                        /* Frames already on ready queue (no free descriptors previously) ==>
1364                         * Put frames at end of ready queue
1365                         */
1366                        pDev->ready.tail->next = chain->head;
1367                        pDev->ready.tail = chain->tail;
1368                        chain->tail->next = NULL;
1369                }else{
1370                        /* All frames is put into the ready queue for later processing */
1371                        pDev->ready.head = chain->head;
1372                        pDev->ready.tail = chain->tail;
1373                        chain->tail->next = NULL;
1374                }
1375                pDev->ready_cnt += num; /* Added 'num' frames to ready queue */
1376trigger_transmission:
1377                /* 2. Free used descriptors and put the sent frame into the "Sent queue" 
1378                 *    (SCHEDULED->SENT)
1379                 */
1380                num = grtm_free_sent(pDev);
1381                pDev->scheduled_cnt -= num;
1382                pDev->sent_cnt += num;
1383
1384                /* 3. Use all available free descriptors there are frames for
1385                 *    in the ready queue.
1386                 *    (READY->SCHEDULED)
1387                 */
1388                num = grtm_schedule_ready(pDev,0);
1389                pDev->ready_cnt -= num;
1390                pDev->scheduled_cnt += num;
1391       
1392                pDev->handling_transmission = 0;
1393                break;
1394
1395                /* Take all available sent frames from the "Sent frames" queue.
1396                 * If no frames has been sent, the thread may get blocked if in blocking
1397                 * mode. The blocking mode is not available if driver is not in running mode.
1398                 *
1399                 * Note this ioctl may return success even if the driver is not in STARTED mode.
1400                 * This is because in case of a error (link error of similar) and the driver switch
1401                 * from START to STOP mode we must still be able to get our frames back.
1402                 *
1403                 * Note in case the driver fails to send a frame for some reason (link error),
1404                 * the sent flag is set to 0 indicating a failure.
1405                 *
1406                 */
1407                case GRTM_IOC_RECLAIM:
1408                /* Get pointer to were to place reaped chain */
1409                chain = (struct grtm_list *)ioarg->buffer;
1410                if ( !chain ){
1411                        return RTEMS_INVALID_NAME;
1412                }
1413
1414                /* Lock out interrupt handler */
1415                pDev->handling_transmission = 1;
1416
1417                do {
1418                        /* Move sent frames from descriptors to Sent queue. This makes more
1419                         * descriptors (BDs) available.
1420                         */
1421                        num = grtm_free_sent(pDev);
1422                        pDev->scheduled_cnt -= num;
1423                        pDev->sent_cnt += num;
1424                       
1425
1426                        if ( pDev->running ){
1427                                /* Fill descriptors with as many frames from the ready list
1428                                 * as possible.
1429                                 */
1430                                num = grtm_schedule_ready(pDev,0);
1431                                pDev->ready_cnt -= num;
1432                                pDev->scheduled_cnt += num;
1433                        }
1434
1435                        /* Are there any frames on the sent queue waiting to be
1436                         * reclaimed?
1437                         */
1438
1439                        if ( !pDev->sent.head ){
1440                                /* No frames to reclaim - no frame in sent queue.
1441                                 * Instead we block thread until frames have been sent
1442                                 * if in blocking mode.
1443                                 */
1444                                if ( pDev->running && pDev->config.blocking ){
1445                                        ret = rtems_semaphore_obtain(pDev->sem_tx,RTEMS_WAIT,pDev->config.timeout);
1446                                        if ( ret == RTEMS_TIMEOUT ) {
1447                                                pDev->handling_transmission = 0;
1448                                                return RTEMS_TIMEOUT;
1449                                        } else if ( ret == RTEMS_SUCCESSFUL ) {
1450                                                /* There might be frames available, go check */
1451                                                continue;
1452                                        } else {
1453                                                /* any error (driver closed, internal error etc.) */
1454                                                pDev->handling_transmission = 0;
1455                                                return RTEMS_UNSATISFIED;
1456                                        }
1457
1458                                }else{
1459                                        /* non-blocking mode, we quit */
1460                                        chain->head = NULL;
1461                                        chain->tail = NULL;
1462                                        /* do not lock out interrupt handler any more */
1463                                        pDev->handling_transmission = 0;
1464                                        return RTEMS_TIMEOUT;
1465                                }
1466                        }else{
1467                                /* Take all sent framess from sent queue to userspace queue */
1468                                chain->head = pDev->sent.head;
1469                                chain->tail = pDev->sent.tail;
1470                                chain->tail->next = NULL; /* Just for sure */
1471
1472                                /* Mark no Sent */
1473                                grtm_list_clr(&pDev->sent);
1474                                pDev->sent_cnt = 0;
1475
1476                                DBG("TX_RECLAIM: head: 0x%x, tail: 0x%x\n",chain->head,chain->tail);
1477                                break;
1478                        }
1479
1480                }while(1);
1481               
1482                /* do not lock out interrupt handler any more */
1483                pDev->handling_transmission = 0;
1484                break;
1485
1486                default:
1487                return RTEMS_NOT_DEFINED;
1488        }
1489        return RTEMS_SUCCESSFUL;
1490}
1491
1492static void grtm_interrupt(void *arg)
1493{
1494        struct grtm_priv *pDev = arg;
1495        struct grtm_regs *regs = pDev->regs;
1496        unsigned int status;
1497        int num;
1498
1499        /* Clear interrupt by reading it */
1500        status = READ_REG(&regs->dma_status);
1501       
1502        /* Spurious Interrupt? */
1503        if ( !pDev->running )
1504                return;
1505
1506        if ( status )
1507                regs->dma_status = status;
1508
1509        if ( status & GRTM_DMA_STS_TFF ){
1510                pDev->stats.err_transfer_frame++;
1511        }
1512
1513        if ( status & GRTM_DMA_STS_TA ){
1514                pDev->stats.err_ahb++;
1515        }
1516
1517        if ( status & GRTM_DMA_STS_TE ){
1518                pDev->stats.err_tx++;
1519        }
1520
1521        if ( status & GRTM_DMA_STS_TI ){
1522               
1523                if ( pDev->config.isr_desc_proc && !pDev->handling_transmission ) {
1524                        /* Free used descriptors and put the sent frame into the "Sent queue" 
1525                         *   (SCHEDULED->SENT)
1526                         */
1527                        num = grtm_free_sent(pDev);
1528                        pDev->scheduled_cnt -= num;
1529                        pDev->sent_cnt += num;
1530
1531                        /* Use all available free descriptors there are frames for
1532                         * in the ready queue.
1533                         *   (READY->SCHEDULED)
1534                         */
1535                        num = grtm_schedule_ready(pDev,1);
1536                        pDev->ready_cnt -= num;
1537                        pDev->scheduled_cnt += num;
1538
1539#if 0
1540                        if ( (pDev->config.blocking==GRTM_BLKMODE_COMPLETE) && pDev->timeout ){
1541                                /* Signal to thread only if enough data is available */
1542                                if ( pDev->wait_for_frames > grtm_data_avail(pDev) ){
1543                                        /* Not enough data available */
1544                                        goto procceed_processing_interrupts;
1545                                }
1546
1547                                /* Enough number of frames has been transmitted which means that
1548                                 * the waiting thread should be woken up.
1549                                 */
1550                                rtems_semaphore_release(pDev->sem_tx);
1551                        }
1552#endif
1553                }
1554
1555                if ( pDev->config.blocking == GRTM_BLKMODE_BLK ) {
1556                        /* Blocking mode */
1557
1558#if 0
1559                        /* Disable further Interrupts until handled by waiting task. */
1560                        regs->dma_ctrl = READ_REG(&regs->dma_ctrl) & ~GRTM_DMA_CTRL_IE;
1561#endif
1562               
1563                        /* Signal Semaphore to wake waiting thread in ioctl(SEND|RECLAIM) */
1564                        rtems_semaphore_release(pDev->sem_tx);
1565                }
1566
1567        }
1568#if 0
1569procceed_processing_interrupts:
1570        ;
1571#endif
1572}
1573
1574static rtems_device_driver grtm_initialize(
1575  rtems_device_major_number major, 
1576  rtems_device_minor_number unused,
1577  void *arg
1578  )
1579{
1580        /* Device Semaphore created with count = 1 */
1581        if ( rtems_semaphore_create(rtems_build_name('G', 'R', 'T', 'M'),
1582                1,
1583                RTEMS_FIFO|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING,
1584                0,
1585                &grtm_dev_sem) != RTEMS_SUCCESSFUL ) {
1586                return RTEMS_INTERNAL_ERROR;
1587        }
1588
1589        return RTEMS_SUCCESSFUL;
1590}
Note: See TracBrowser for help on using the repository browser.