source: rtems/bsps/sparc/shared/tmtc/grtm.c @ 11f3b9a

5
Last change on this file since 11f3b9a was 11f3b9a, checked in by Sebastian Huber <sebastian.huber@…>, on 11/26/18 at 14:55:38

bsps/sparc: Add grlib_malloc(), grlib_calloc()

This avoids a dependency to errno in device driver code.

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