source: rtems/c/src/lib/libbsp/sparc/shared/include/grspw_pkt.h @ 94fb377b

5
Last change on this file since 94fb377b was 94fb377b, checked in by Daniel Hellstrom <daniel@…>, on 01/22/17 at 14:58:18

leon, grspw_pkt: ISR RX/TX DMA interrupt source disable configurable

This patch introduces some new options to let the user control when

the ISR shall disable DMA RX/TX interrupt. The ISR can be set in three
modes when a RX/TX DMA interrupt is asserted:

1) ISR will always clear both RX/TX DMA interrupt enable. (DEFAULT).
2) ISR will never never RX or TX DMA interrupt enable, ISR will

leave RX/TX DMA interrupt enable untouched.

3) ISR will clear the interrupt enable(s) causing the interrupt,

this allows separate RX and TX IRQ handling.

This patch is backwards compatible since default mode 1) is activated
when the grspw_dma_config.flags DMAFLAGS2_IRQD field is 0.

  • Property mode set to 100644
File size: 29.0 KB
Line 
1/*
2 *  GRSPW/GRSPW2 SpaceWire Kernel Library Interface
3 *
4 *  COPYRIGHT (c) 2011
5 *  Cobham Gaisler AB
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.org/license/LICENSE.
10 */
11
12#ifndef __GRSPW_PKT_H__
13#define __GRSPW_PKT_H__
14
15struct grspw_pkt;
16
17/* Maximum number of GRSPW devices supported by driver */
18#define GRSPW_MAX 32
19
20/* Weak overridable variable the user can use to define the worker-task
21 * priority (0..255) or to disable (-1) the creation of the worker-task
22 * and the message queue to save space */
23extern int grspw_work_task_priority;
24
25#ifndef GRSPW_PKT_FLAGS
26#define GRSPW_PKT_FLAGS
27/*** TX Packet flags ***/
28
29/* Enable IRQ generation */
30#define TXPKT_FLAG_IE 0x0040
31
32/* Enable Header CRC generation (if CRC is available in HW)
33 * Header CRC will be appended (one byte at end of header)
34 */
35#define TXPKT_FLAG_HCRC 0x0100
36
37/* Enable Data CRC generation (if CRC is available in HW)
38 * Data CRC will be appended (one byte at end of packet)
39 */
40#define TXPKT_FLAG_DCRC 0x0200
41
42/* Control how many bytes the beginning of the Header
43 * the CRC should not be calculated for */
44#define TXPKT_FLAG_NOCRC_MASK 0x0000000f
45#define TXPKT_FLAG_NOCRC_LEN0 0x00000000
46#define TXPKT_FLAG_NOCRC_LEN1 0x00000001
47#define TXPKT_FLAG_NOCRC_LEN2 0x00000002
48#define TXPKT_FLAG_NOCRC_LEN3 0x00000003
49#define TXPKT_FLAG_NOCRC_LEN4 0x00000004
50#define TXPKT_FLAG_NOCRC_LEN5 0x00000005
51#define TXPKT_FLAG_NOCRC_LEN6 0x00000006
52#define TXPKT_FLAG_NOCRC_LEN7 0x00000007
53#define TXPKT_FLAG_NOCRC_LEN8 0x00000008
54#define TXPKT_FLAG_NOCRC_LEN9 0x00000009
55#define TXPKT_FLAG_NOCRC_LENa 0x0000000a
56#define TXPKT_FLAG_NOCRC_LENb 0x0000000b
57#define TXPKT_FLAG_NOCRC_LENc 0x0000000c
58#define TXPKT_FLAG_NOCRC_LENd 0x0000000d
59#define TXPKT_FLAG_NOCRC_LENe 0x0000000e
60#define TXPKT_FLAG_NOCRC_LENf 0x0000000f
61
62#define TXPKT_FLAG_INPUT_MASK (TXPKT_FLAG_NOCRC_MASK | TXPKT_FLAG_IE | \
63                                TXPKT_FLAG_HCRC | TXPKT_FLAG_DCRC)
64
65/* Marks if packet was transmitted or not */
66#define TXPKT_FLAG_TX 0x4000
67
68/* Link Error */
69#define TXPKT_FLAG_LINKERR 0x8000
70
71#define TXPKT_FLAG_OUTPUT_MASK (TXPKT_FLAG_TX | TXPKT_FLAG_LINKERR)
72
73/*** RX Packet Flags ***/
74
75/* Enable IRQ generation */
76#define RXPKT_FLAG_IE 0x0010
77
78#define RXPKT_FLAG_INPUT_MASK (RXPKT_FLAG_IE)
79
80/* Packet was truncated */
81#define RXPKT_FLAG_TRUNK 0x0800
82/* Data CRC error (only valid if RMAP CRC is enabled) */
83#define RXPKT_FLAG_DCRC 0x0400
84/* Header CRC error (only valid if RMAP CRC is enabled) */
85#define RXPKT_FLAG_HCRC 0x0200
86/* Error in End-of-Packet */
87#define RXPKT_FLAG_EEOP 0x0100
88/* Marks if packet was recevied or not */
89#define RXPKT_FLAG_RX 0x8000
90
91#define RXPKT_FLAG_OUTPUT_MASK (RXPKT_FLAG_TRUNK | RXPKT_FLAG_DCRC | \
92                                RXPKT_FLAG_HCRC | RXPKT_FLAG_EEOP)
93
94/*** General packet flag options ***/
95
96/* Translate Hdr and/or Payload address */
97#define PKT_FLAG_TR_DATA 0x1000
98#define PKT_FLAG_TR_HDR 0x2000
99/* All General options */
100#define PKT_FLAG_MASK 0x3000
101
102#endif
103/* GRSPW RX/TX Packet structure.
104 *
105 * - For RX the 'hdr' and 'hlen' fields are not used, they are not written
106 *   by driver.
107 *
108 * - The 'pkt_id' field is untouched by driver, it is intended for packet
109 *   numbering or user-custom data.
110 *
111 * - The last packet in a list must have 'next' set to NULL.
112 *
113 * - data and hdr pointers are written without modification to hardware,
114 *   this means that caller must do address translation to hardware
115 *   address itself.
116 *
117 * - the 'flags' field are interpreted differently depending on transfer
118 *   type (RX/TX). See XXPKT_FLAG_* options above.
119 */
120struct grspw_pkt {
121        struct grspw_pkt *next; /* Next packet in list. NULL if last packet */
122        unsigned int pkt_id;    /* User assigned ID (not touched by driver) */
123        unsigned short flags;   /* RX/TX Options and status */
124        unsigned char reserved; /* Reserved, must be zero */
125        unsigned char hlen;     /* Length of Header Buffer (only TX) */
126        unsigned int dlen;      /* Length of Data Buffer */
127        void *data;     /* 4-byte or byte aligned depends on HW */
128        void *hdr;      /* 4-byte or byte aligned depends on HW (only TX) */
129};
130
131/* GRSPW SpaceWire Packet List */
132struct grspw_list {
133        struct grspw_pkt *head;
134        struct grspw_pkt *tail;
135};
136
137/* SpaceWire Link State */
138typedef enum {
139        SPW_LS_ERRRST = 0,
140        SPW_LS_ERRWAIT = 1,
141        SPW_LS_READY = 2,
142        SPW_LS_CONNECTING = 3,
143        SPW_LS_STARTED = 4,
144        SPW_LS_RUN = 5
145} spw_link_state_t;
146
147/* Address Configuration */
148struct grspw_addr_config {
149        /* Ignore address field and put all received packets to first
150         * DMA channel.
151         */
152        int promiscuous;
153
154        /* Default Node Address and Mask */
155        unsigned char def_addr;
156        unsigned char def_mask;
157        /* DMA Channel custom Node Address and Mask */
158        struct {
159                char node_en;                   /* Enable Separate Addr */
160                unsigned char node_addr;        /* Node address */
161                unsigned char node_mask;        /* Node address mask */
162        } dma_nacfg[4];
163};
164
165/* Hardware Support in GRSPW Core */
166struct grspw_hw_sup {
167        char    rmap;           /* If RMAP in HW is available */
168        char    rmap_crc;       /* If RMAP CRC is available */
169        char    rx_unalign;     /* RX unaligned (byte boundary) access allowed*/
170        char    nports;         /* Number of Ports (1 or 2) */
171        char    ndma_chans;     /* Number of DMA Channels (1..4) */
172        char    strip_adr;      /* Hardware can strip ADR from packet data */
173        char    strip_pid;      /* Hardware can strip PID from packet data */
174        int     hw_version;     /* GRSPW Hardware Version */
175        char    reserved[2];
176        char    irq;            /* SpW Distributed Interrupt available if 1 */
177        char    irq_num;        /* Number of interrupts that can be generated */
178        char    itmr_width;     /* SpW Intr. ISR timers bit width. 0=no timer */
179};
180
181struct grspw_core_stats {
182        int irq_cnt;
183        int err_credit;
184        int err_eeop;
185        int err_addr;
186        int err_parity;
187        int err_disconnect;
188        int err_escape;
189        int err_wsync; /* only in GRSPW1 */
190};
191
192/* grspw_link_ctrl() options */
193#define LINKOPTS_ENABLE         0x0000
194#define LINKOPTS_DISABLE        0x0001
195#define LINKOPTS_START          0x0002
196#define LINKOPTS_AUTOSTART      0x0004
197#define LINKOPTS_DIS_ONERR      0x0008  /* Disable DMA transmitter on link error
198                                         * Controls LE bit in DMACTRL register.
199                                         */
200#define LINKOPTS_DIS_ON_CE      0x0020000/* Disable Link on Credit error */
201#define LINKOPTS_DIS_ON_ER      0x0040000/* Disable Link on Escape error */
202#define LINKOPTS_DIS_ON_DE      0x0080000/* Disable Link on Disconnect error */
203#define LINKOPTS_DIS_ON_PE      0x0100000/* Disable Link on Parity error */
204#define LINKOPTS_DIS_ON_WE      0x0400000/* Disable Link on write synchonization
205                                          * error (GRSPW1 only)
206                                          */
207#define LINKOPTS_DIS_ON_EE      0x1000000/* Disable Link on Early EOP/EEP error*/
208
209/*#define LINKOPTS_TICK_OUT_IRQ 0x0100*//* Enable Tick-out IRQ */
210#define LINKOPTS_EIRQ           0x0200  /* Enable Error Link IRQ */
211
212#define LINKOPTS_MASK           0x15e020f/* All above options */
213#define LINKOPTS_MASK_DIS_ON    0x15e0000/* All disable link on error options
214                                          * On a certain error the link disable
215                                          * bit will be written and the work
216                                          * task will call dma_stop() for all
217                                          * channels.
218                                          */
219
220#define LINKSTS_CE              0x002   /* Credit error */
221#define LINKSTS_ER              0x004   /* Escape error */
222#define LINKSTS_DE              0x008   /* Disconnect error */
223#define LINKSTS_PE              0x010   /* Parity error */
224#define LINKSTS_WE              0x040   /* Write synchonization error (GRSPW1 only) */
225#define LINKSTS_IA              0x080   /* Invalid address */
226#define LINKSTS_EE              0x100   /* Early EOP/EEP */
227#define LINKSTS_MASK            0x1de
228
229/* grspw_tc_ctrl() options */
230#define TCOPTS_EN_RXIRQ 0x0001  /* Tick-Out IRQ */
231#define TCOPTS_EN_TX    0x0004
232#define TCOPTS_EN_RX    0x0008
233
234/* grspw_ic_ctrl() options:
235 * Corresponds code duplicatingly to GRSPW_CTRL_XX_BIT defines
236 */
237#define ICOPTS_INTNUM           (0x1f << 27)
238#define ICOPTS_EN_SPWIRQ_ON_EE  (1 << 24)
239#define ICOPTS_EN_SPWIRQ_ON_IA  (1 << 23)
240#define ICOPTS_EN_PRIO          (1 << 22)
241#define ICOPTS_EN_TIMEOUTIRQ    (1 << 20)
242#define ICOPTS_EN_ACKIRQ        (1 << 19)
243#define ICOPTS_EN_TICKOUTIRQ    (1 << 18)
244#define ICOPTS_EN_RX            (1 << 17)
245#define ICOPTS_EN_TX            (1 << 16)
246#define ICOPTS_BASEIRQ          (0x1f << 8)
247#define ICOPTS_EN_FLAGFILTER    (1 << 0) /* NOTE: Not in icctrl. CTRL.bit12 */
248
249/* grspw_ic_rlisr() and grspw_ic_rlintack()  */
250#define ICRELOAD_EN             (1 << 31)
251#define ICRELOAD_MASK           0x7fffffff
252
253/* grspw_rmap_ctrl() options */
254#define RMAPOPTS_EN_RMAP        0x0001
255#define RMAPOPTS_EN_BUF         0x0002
256
257/* grspw_dma_config.flags options */
258#define DMAFLAG_NO_SPILL        0x0001  /* See HW doc DMA-CTRL NS bit */
259#define DMAFLAG_RESV1           0x0002  /* HAS NO EFFECT */
260#define DMAFLAG_STRIP_ADR       0x0004  /* See HW doc DMA-CTRL SA bit */
261#define DMAFLAG_STRIP_PID       0x0008  /* See HW doc DMA-CTRL SP bit */
262#define DMAFLAG_RESV2           0x0010  /* HAS NO EFFECT */
263#define DMAFLAG_MASK    (DMAFLAG_NO_SPILL|DMAFLAG_STRIP_ADR|DMAFLAG_STRIP_PID)
264/* grspw_dma_config.flags misc options (not shifted internally) */
265#define DMAFLAG2_TXIE   0x00100000      /* See HW doc DMA-CTRL TI bit.
266                                         * Used to enable TX DMA interrupt
267                                         * when tx_irq_en_cnt=0.
268                                         */
269#define DMAFLAG2_RXIE   0x00200000      /* See HW doc DMA-CTRL RI bit.
270                                         * Used to enable RX DMA interrupt
271                                         * when rx_irq_en_cnt=0.
272                                         */
273/* Defines how the ISR will disable RX/TX DMA interrupt source when a DMA RX/TX
274 * interrupt has happended. DMA Error Interrupt always disables both RX/TX DMA
275 * interrupt. By default both RX/TX IRQs are disabled when either a RX, TX or
276 * both RX/TX DMA interrupt has been requested. The work-task, custom
277 * application handler or custom ISR handler is responsible to re-enable
278 * DMA interrupts.
279 */
280#define DMAFLAG2_IRQD_SRC  0x01000000   /* Disable triggering RX/TX source */
281#define DMAFLAG2_IRQD_NONE 0x00c00000   /* Never disable RX/TX IRQ in ISR */
282#define DMAFLAG2_IRQD_BOTH 0x00000000   /* Always disable both RX/TX sources */
283#define DMAFLAG2_IRQD_MASK 0x01c00000   /* Mask of options */
284#define DMAFLAG2_IRQD_BIT  22
285
286#define DMAFLAG2_MASK   (DMAFLAG2_TXIE | DMAFLAG2_RXIE | DMAFLAG2_IRQD_MASK)
287
288struct grspw_dma_config {
289        int flags;              /* DMA config flags, see DMAFLAG1&2_* options */
290        int rxmaxlen;           /* RX Max Packet Length */
291        int rx_irq_en_cnt;      /* Enable RX IRQ every cnt descriptors */
292        int tx_irq_en_cnt;      /* Enable TX IRQ every cnt descriptors */
293};
294
295/* Statistics per DMA channel */
296struct grspw_dma_stats {
297        /* IRQ Statistics */
298        int irq_cnt;            /* Number of DMA IRQs generated by channel */
299
300        /* Descriptor Statistics */
301        int tx_pkts;            /* Number of Transmitted packets */
302        int tx_err_link;        /* Number of Transmitted packets with Link Error*/
303        int rx_pkts;            /* Number of Received packets */
304        int rx_err_trunk;       /* Number of Received Truncated packets */
305        int rx_err_endpkt;      /* Number of Received packets with bad ending */
306
307        /* Diagnostics to help developers sizing their number buffers to avoid
308         * out-of-buffers or other phenomenons.
309         */
310        int send_cnt_min;       /* Minimum number of packets in TX SEND Q */
311        int send_cnt_max;       /* Maximum number of packets in TX SEND Q */
312        int tx_sched_cnt_min;   /* Minimum number of packets in TX SCHED Q */
313        int tx_sched_cnt_max;   /* Maximum number of packets in TX SCHED Q */
314        int sent_cnt_max;       /* Maximum number of packets in TX SENT Q */
315        int tx_work_cnt;        /* Times the work thread processed TX BDs */
316        int tx_work_enabled;    /* No. RX BDs enabled by work thread */
317
318        int ready_cnt_min;      /* Minimum number of packets in RX READY Q */
319        int ready_cnt_max;      /* Maximum number of packets in RX READY Q */
320        int rx_sched_cnt_min;   /* Minimum number of packets in RX SCHED Q */
321        int rx_sched_cnt_max;   /* Maximum number of packets in RX SCHED Q */
322        int recv_cnt_max;       /* Maximum number of packets in RX RECV Q */
323        int rx_work_cnt;        /* Times the work thread processed RX BDs */
324        int rx_work_enabled;    /* No. RX BDs enabled by work thread */
325};
326
327/* ISR message sending call back. Compatible with rtems_message_queue_send().
328 * The 'buf' parameter has a pointer to a WORK-TASK message defined by the
329 * WORK_* macros below. The message indicates what GRSPW device operations
330 * are pending, thus what caused the interrupt.
331 *
332 * \param data   defined by grspw_work_config.msgisr_arg, default a rtems_id.
333 * \param buf    Pointer to a 32-bit message word
334 * \param n      Always 4 (byte size of buf).
335 */
336typedef int (*grspw_msgqisr_t)(void *data, unsigned int *buf, unsigned int n);
337
338/* Work message definitions, the int sent to *buf
339 * Bits 31..24: reserved.
340 * Bits 23..16: GRSPW device number message is associated with.
341 * Bit  15:     reserved.
342 * Bit  14:     work-task shall delete message queue on exit.
343 * Bit  13:     work-task shall exit and delete itself.
344 * Bit  12:     link error - shut down all DMA operations (stop DMA channels).
345 * Bit  11..8:  Indicats DMA error on DMA channel 3..0.
346 * Bit  7..0:   Indicats RX and/or TX packets completed on channel 3..0.
347 */
348#define WORK_NONE         0
349#define WORK_SHUTDOWN     0x1000 /* Signal shut down */
350#define WORK_QUIT_TASK    0x2000 /* Work task shall exit (delete itself) */
351#define WORK_FREE_MSGQ    0x4000 /* Delete MsgQ (valid when WORK_QUIT_TASK) */
352#define WORK_DMA(chan, rxtx) (((rxtx) & 0x3) << ((chan) * 2))
353#define WORK_DMA_TX(chan) WORK_DMA(chan, 1)
354#define WORK_DMA_RX(chan) WORK_DMA(chan, 2)
355#define WORK_DMA_ER(chan) (0x1 << ((chan) + 8))
356#define WORK_DMA_MASK     0xfff /* max 4 channels all work */
357#define WORK_DMA_TX_MASK  0x055 /* max 4 channels TX work */
358#define WORK_DMA_RX_MASK  0x0aa /* max 4 channels RX work */
359#define WORK_DMA_ER_MASK  0xf00 /* max 4 channels Error work */
360#define WORK_DMA_CHAN_MASK(chan) (WORK_DMA_ER(chan) | WORK_DMA(chan, 0x3))
361#define WORK_CORE_BIT     16
362#define WORK_CORE_MASK    0x00ff0000
363#define WORK_CORE(device) ((device) << WORK_CORE_BIT)
364
365/* Message Q used to send messages to work task */
366struct grspw_work_config {
367        grspw_msgqisr_t msgisr;
368        void *msgisr_arg; /* example: rtems_id to Msg Q */
369};
370
371extern void grspw_initialize_user(
372        /* Callback every time a GRSPW device is found. Args: DeviceIndex */
373        void *(*devfound)(int),
374        /* Callback every time a GRSPW device is removed. Args:
375         * int   = DeviceIndex
376         * void* = Return Value from devfound()
377         */
378        void (*devremove)(int,void*)
379        );
380
381/* Creates a MsgQ (optional) and spawns a worker task associated with the
382 * message Q. The task can also be associated with a custom msgQ if *msgQ.
383 * is non-zero.
384 *
385 * \param prio     Task priority, set to -1 for default.
386 * \param stack    Task stack size, set to 0 for default.
387 * \param msgQ     pMsgQ=NULL: illegal,
388 *                 pMsqQ==0: create new MsgQ with task and place in *pMsgQ,
389 *                 *pmsqQ!=0: pointer to MsgQ used for task.
390 * \param msgMax   Maximum number of messages, set to 0 for default.
391 * \return         0 on failure, task id on success.
392 */
393extern rtems_id grspw_work_spawn(int prio, int stack, rtems_id *pMsgQ, int msgMax);
394
395/* Free task associated with message queue and optionally also the message
396 * queue itself. The message queue is deleted by the work task and is therefore
397 * delayed until it the work task resumes its execution.
398 */
399extern rtems_status_code grspw_work_free(rtems_id msgQ, int freeMsgQ);
400
401/* Configure a GRSPW device Work task and Message Q set up.
402 * This affects messages to:
403 *  - DMA AHB error interrupt handling (mandatory)
404 *  - Link status interrupt handling (optional)
405 *  - RX DMA, defaults to common msgQ (configured per DMA channel)
406 */
407extern void grspw_work_cfg(void *d, struct grspw_work_config *wc);
408
409/* Work-task function, called only from the work task. The function is provided
410 * as a way for the user to create its own work tasks.
411 * The argument determines which message queue the task shall read its
412 * work jobs from.
413 *
414 * The messages are always 32-bit words and follows the format defined by the
415 * WORK_* macros above.
416 */
417extern void grspw_work_func(rtems_id msgQ);
418
419enum grspw_worktask_ev {
420        WORKTASK_EV_NONE = 0,
421        WORKTASK_EV_QUIT = 1,
422        WORKTASK_EV_SHUTDOWN = 2,
423        WORKTASK_EV_DMA_STOP = 3,
424};
425
426/* Weak function to let user override. Function called every time one of the
427 * events above is handled by the work-task. The message 'msg' is the current
428 * message being processed by the work-task.
429 * The user can for example add custom code to invoke on a DMA error, link
430 * error or monitor when the work-task exits after a call to grspw_work_free().
431 */
432extern void grspw_work_event(enum grspw_worktask_ev ev, unsigned int msg);
433
434extern int grspw_dev_count(void);
435extern void *grspw_open(int dev_no);
436extern int grspw_close(void *d);
437extern void grspw_hw_support(void *d, struct grspw_hw_sup *hw);
438extern void grspw_stats_read(void *d, struct grspw_core_stats *sts);
439extern void grspw_stats_clr(void *d);
440
441/* Set and Read current node address configuration. The dma_nacfg[N] field
442 * represents the configuration for DMA Channel N.
443 *
444 * Set cfg->promiscous to -1 in order to only read current configuration.
445 */
446extern void grspw_addr_ctrl(void *d, struct grspw_addr_config *cfg);
447
448/*** Link Control interface ***/
449/* Read Link State */
450extern spw_link_state_t grspw_link_state(void *d);
451/* options [in/out]: set to -1 to only read current config
452 *
453 * CLKDIV register contain:
454 *  bits 7..0  : Clock Div RUN (only run-state)
455 *  bits 15..8 : Clock Div During Startup (all link states except run-state)
456 */
457extern void grspw_link_ctrl(void *d, int *options, int *stscfg, int *clkdiv);
458/* Read the current value of the status register */
459extern unsigned int grspw_link_status(void *d);
460/* Clear bits in the status register */
461extern void grspw_link_status_clr(void *d, unsigned int clearmask);
462
463/*** Time Code Interface ***/
464/* Generate Tick-In (increment Time Counter, Send Time Code) */
465extern void grspw_tc_tx(void *d);
466/* Control Timcode settings of core */
467extern void grspw_tc_ctrl(void *d, int *options);
468/* Assign ISR Function to TimeCode RX IRQ */
469extern void grspw_tc_isr(void *d, void (*tcisr)(void *data, int tc), void *data);
470/* Read/Write TCTRL and TIMECNT. Write if not -1, always read current value
471 * TCTRL   = bits 7 and 6
472 * TIMECNT = bits 5 to 0
473 */
474extern void grspw_tc_time(void *d, int *time);
475
476/*** Interrupt-code Interface ***/
477struct spwpkt_ic_config {
478        unsigned int tomask;
479        unsigned int aamask;
480        unsigned int scaler;
481        unsigned int isr_reload;
482        unsigned int ack_reload;
483};
484/* Function Interrupt-Code ISR callback prototype. Called when respective
485 * interrupt handling option has been enabled by grspw_ic_ctrl(), the
486 * arguments rxirq, rxack and intto are read from the registers of the
487 * GRSPW core read by the GRSPW ISR, they are individually valid only when
488 * repective handling been turned on.
489 *
490 * data    - Custom data provided by user
491 * rxirq   - Interrupt-Code Recevie register of the GRSPW core read by ISR
492 *           (only defined if IQ bit enabled through grspw_ic_ctrl())
493 * rxack   - Interrupt-Ack-Code Recevie register of the GRSPW core read by ISR
494 *           (only defined if AQ bit enabled through grspw_ic_ctrl())
495 * intto   - Interrupt Tick-out Recevie register of the GRSPW core read by ISR
496 *           (only defined if TQ bit enabled through grspw_ic_ctrl())
497 */
498typedef void (*spwpkt_ic_isr_t)(void *data, unsigned int rxirq,
499                                unsigned int rxack, unsigned int intto);
500/* Control Interrupt-code settings of core
501 * Write if 'options' not pointing to -1, always read current value
502 */
503extern void grspw_ic_ctrl(void *d, unsigned int *options);
504/* Write (rw&1 == 1) configuration parameters to registers and/or,
505 * Read  (rw&2 == 1) configuration parameters from registers, in that sequence.
506 */
507extern void grspw_ic_config(void *d, int rw, struct spwpkt_ic_config *cfg);
508/* Read or Write Interrupt-code status registers.
509 * If pointer argument *ptr == 0 then only read, if *ptr != 0 then only write.
510 * If *ptr is NULL no operation.
511 */
512extern void grspw_ic_sts(void *d, unsigned int *rxirq, unsigned int *rxack,
513                        unsigned int *intto);
514/* Generate Tick-In for the given Interrupt-code
515 * Returns zero on success and non-zero on failure
516 *
517 * Interrupt code bits (ic):
518 * Bit 5 - ACK if 1
519 * Bits 4-0 Interrupt-code number
520 */
521extern int grspw_ic_tickin(void *d, int ic);
522/* Assign handler function to Interrupt-code timeout IRQ */
523extern void grspw_ic_isr(void *d, spwpkt_ic_isr_t handler, void *data);
524
525/*** RMAP Control Interface ***/
526/* Set (not -1) and/or read RMAP options. */
527extern int grspw_rmap_ctrl(void *d, int *options, int *dstkey);
528extern void grspw_rmap_support(void *d, char *rmap, char *rmap_crc);
529
530/*** SpW Port Control Interface ***/
531
532/* Select port, if
533 * -1=The current selected port is returned
534 * 0=Port 0
535 * 1=Port 1
536 * Other positive values=Both Port0 and Port1
537 */
538extern int grspw_port_ctrl(void *d, int *port);
539/* Returns Number ports available in hardware */
540extern int grspw_port_count(void *d);
541/* Returns the current active port */
542extern int grspw_port_active(void *d);
543
544/*** DMA Interface ***/
545extern void *grspw_dma_open(void *d, int chan_no);
546extern int grspw_dma_close(void *c);
547
548extern int grspw_dma_start(void *c);
549extern void grspw_dma_stop(void *c);
550
551/* Enable interrupt manually */
552extern unsigned int grspw_dma_enable_int(void *c, int rxtx, int force);
553
554/* Return Current DMA Control & Status Register */
555extern unsigned int grspw_dma_ctrlsts(void *c);
556
557/* Schedule List of packets for transmission at some point in
558 * future.
559 *
560 * 1. Move transmitted packets to SENT List (SCHED->SENT)
561 * 2. Add the requested packets to the SEND List (USER->SEND)
562 * 3. Schedule as many packets as possible for transmission (SEND->SCHED)
563 *
564 * Call this function with pkts=NULL to just do step 1 and 3. This may be
565 * required in Polling-mode.
566 *
567 * The above steps 1 and 3 may be skipped by setting 'opts':
568 *  bit0 = 1: Skip Step 1.
569 *  bit1 = 1: Skip Step 3.
570 * Skipping both step 1 and 3 may be usefull when IRQ is enabled, then
571 * the work queue will be totaly responsible for handling descriptors.
572 *
573 * The fastest solution in retreiving sent TX packets and sending new frames
574 * is to call:
575 *  A. grspw_dma_tx_reclaim(opts=0)
576 *  B. grspw_dma_tx_send(opts=1)
577 *
578 * NOTE: the TXPKT_FLAG_TX flag must not be set.
579 *
580 * Return Code
581 *  -1   Error
582 *  0    Successfully added pkts to send/sched list
583 *  1    DMA stopped. No operation.
584 */
585extern int grspw_dma_tx_send(void *c, int opts, struct grspw_list *pkts, int count);
586
587/* Reclaim TX packet buffers that has previously been scheduled for transmission
588 * with grspw_dma_tx_send().
589 *
590 * 1. Move transmitted packets to SENT List (SCHED->SENT)
591 * 2. Move all SENT List to pkts list (SENT->USER)
592 * 3. Schedule as many packets as possible for transmission (SEND->SCHED)
593 *
594 * The above steps 1 may be skipped by setting 'opts':
595 *  bit0 = 1: Skip Step 1.
596 *  bit1 = 1: Skip Step 3.
597 *
598 * The fastest solution in retreiving sent TX packets and sending new frames
599 * is to call:
600 *  A. grspw_dma_tx_reclaim(opts=2) (Skip step 3)
601 *  B. grspw_dma_tx_send(opts=1) (Skip step 1)
602 *
603 * Return Code
604 *  -1   Error
605 *  0    Successful. pkts list filled with all packets from sent list
606 *  1    Same as 0, but indicates that DMA stopped
607 */
608extern int grspw_dma_tx_reclaim(void *c, int opts, struct grspw_list *pkts, int *count);
609
610/* Get current number of Packets in respective TX Queue. */
611extern void grspw_dma_tx_count(void *c, int *send, int *sched, int *sent, int *hw);
612
613#define GRSPW_OP_AND 0
614#define GRSPW_OP_OR 1
615/* Block until send_cnt or fewer packets are Queued in "Send and Scheduled" Q,
616 * op (AND or OR), sent_cnt or more packet "have been sent" (Sent Q) condition
617 * is met.
618 * If a link error occurs and the Stop on Link error is defined, this function
619 * will also return to caller.
620 * The timeout argument is used to return after timeout ticks, regardless of
621 * the other conditions. If timeout is zero, the function will wait forever
622 * until the condition is satisfied.
623 *
624 * NOTE: if IRQ of TX descriptors are not enabled conditions are never
625 *       checked, this may hang infinitely unless a timeout has been specified
626 *
627 * Return Code
628 *  -1   Error
629 *  0    Returing to caller because specified conditions are now fullfilled
630 *  1    DMA stopped
631 *  2    Timeout, conditions are not met
632 *  3    Another task is already waiting. Service is Busy.
633 */
634extern int grspw_dma_tx_wait(void *c, int send_cnt, int op, int sent_cnt, int timeout);
635
636/* Get received RX packet buffers that has previously been scheduled for
637 * reception with grspw_dma_rx_prepare().
638 *
639 * 1. Move Scheduled packets to RECV List (SCHED->RECV)
640 * 2. Move all RECV packet to the callers list (RECV->USER)
641 * 3. Schedule as many free packet buffers as possible (READY->SCHED)
642 *
643 * The above steps 1 may be skipped by setting 'opts':
644 *  bit0 = 1: Skip Step 1.
645 *  bit1 = 1: Skip Step 3.
646 *
647 * The fastest solution in retreiving received RX packets and preparing new
648 * packet buffers for future receive, is to call:
649 *  A. grspw_dma_rx_recv(opts=2, &recvlist) (Skip step 3)
650 *  B. grspw_dma_rx_prepare(opts=1, &freelist) (Skip step 1)
651 *
652 * Return Code
653 *  -1   Error
654 *  0    Successfully filled pkts list with packets from recv list.
655 *  1    DMA stopped
656 */
657extern int grspw_dma_rx_recv(void *c, int opts, struct grspw_list *pkts, int *count);
658
659/* Add more RX packet buffers for future for reception. The received packets
660 * can later be read out with grspw_dma_rx_recv().
661 *
662 * 1. Move Received packets to RECV List (SCHED->RECV)
663 * 2. Add the "free/ready" packet buffers to the READY List (USER->READY)
664 * 3. Schedule as many packets as possible (READY->SCHED)
665 *
666 * The above steps 1 may be skipped by setting 'opts':
667 *  bit0 = 1: Skip Step 1.
668 *  bit1 = 1: Skip Step 3.
669 *
670 * The fastest solution in retreiving received RX packets and preparing new
671 * packet buffers for future receive, is to call:
672 *  A. grspw_dma_rx_recv(opts=2, &recvlist) (Skip step 3)
673 *  B. grspw_dma_rx_prepare(opts=1, &freelist) (Skip step 1)
674 *
675 * Return Code
676 *  -1   Error
677 *  0    Successfully added packet buffers from pkt list into the ready queue
678 *  1    DMA stopped
679 */
680extern int grspw_dma_rx_prepare(void *c, int opts, struct grspw_list *pkts, int count);
681
682/* Get current number of Packets in respective RX Queue. */
683extern void grspw_dma_rx_count(void *c, int *ready, int *sched, int *recv, int *hw);
684
685/* Block until recv_cnt or more packets are Queued in RECV Q, op (AND or OR),
686 * ready_cnt or fewer packet buffers are available in the "READY and Scheduled" Q,
687 * condition is met.
688 * If a link error occurs and the Stop on Link error is defined, this function
689 * will also return to caller, however with an error.
690 * The timeout argument is used to return after timeout ticks, regardless of
691 * the other conditions. If timeout is zero, the function will wait forever
692 * until the condition is satisfied.
693 *
694 * NOTE: if IRQ of RX descriptors are not enabled conditions are never
695 *       checked, this may hang infinitely unless a timeout has been specified
696 *
697 * Return Code
698 *  -1   Error
699 *  0    Returing to caller because specified conditions are now fullfilled
700 *  1    DMA stopped
701 *  2    Timeout, conditions are not met
702 *  3    Another task is already waiting. Service is Busy.
703 */
704extern int grspw_dma_rx_wait(void *c, int recv_cnt, int op, int ready_cnt, int timeout);
705
706extern int grspw_dma_config(void *c, struct grspw_dma_config *cfg);
707extern void grspw_dma_config_read(void *c, struct grspw_dma_config *cfg);
708
709extern void grspw_dma_stats_read(void *c, struct grspw_dma_stats *sts);
710extern void grspw_dma_stats_clr(void *c);
711
712/* Register GRSPW packet driver to Driver Manager */
713void grspw2_register_drv (void);
714
715/*** GRSPW SpaceWire Packet List Handling Routines ***/
716
717static inline void grspw_list_clr(struct grspw_list *list)
718{
719        list->head = NULL;
720        list->tail = NULL;
721}
722
723static inline int grspw_list_is_empty(struct grspw_list *list)
724{
725        return (list->head == NULL);
726}
727
728/* Return Number of entries in list */
729static inline int grspw_list_cnt(struct grspw_list *list)
730{
731        struct grspw_pkt *lastpkt = NULL, *pkt = list->head;
732        int cnt = 0;
733        while ( pkt ) {
734                cnt++;
735                lastpkt = pkt;
736                pkt = pkt->next;
737        }
738        if ( lastpkt && (list->tail != lastpkt) )
739                return -1;
740        return cnt;
741}
742
743static inline void
744grspw_list_append(struct grspw_list *list, struct grspw_pkt *pkt)
745{
746        pkt->next = NULL;
747        if ( list->tail == NULL ) {
748                list->head = pkt;
749        } else {
750                list->tail->next = pkt;
751        }
752        list->tail = pkt;
753}
754
755static inline void
756grspw_list_prepend(struct grspw_list *list, struct grspw_pkt *pkt)
757{
758        pkt->next = list->head;
759        if ( list->head == NULL ) {
760                list->tail = pkt;
761        }
762        list->head = pkt;
763}
764
765static inline void
766grspw_list_append_list(struct grspw_list *list, struct grspw_list *alist)
767{
768        if (grspw_list_is_empty(alist)) {
769                return;
770        }
771        alist->tail->next = NULL;
772        if ( list->tail == NULL ) {
773                list->head = alist->head;
774        } else {
775                list->tail->next = alist->head;
776        }
777        list->tail = alist->tail;
778}
779
780static inline void
781grspw_list_prepend_list(struct grspw_list *list, struct grspw_list *alist)
782{
783        if (grspw_list_is_empty(alist)) {
784                return;
785        }
786        if ( list->head == NULL ) {
787                list->tail = alist->tail;
788                alist->tail->next = NULL;
789        } else {
790                alist->tail->next = list->head;
791        }
792        list->head = alist->head;
793}
794
795/* Remove dlist (delete-list) from head of list */
796static inline void
797grspw_list_remove_head_list(struct grspw_list *list, struct grspw_list *dlist)
798{
799        if (grspw_list_is_empty(dlist)) {
800                return;
801        }
802        list->head = dlist->tail->next;
803        if ( list->head == NULL ) {
804                list->tail = NULL;
805        }
806        dlist->tail->next = NULL;
807}
808
809/* Take A number of entries from head of list 'list' and put the entires
810 * to rlist (result list).
811 */
812static inline int
813grspw_list_take_head_list(struct grspw_list *list, struct grspw_list *rlist, int max)
814{
815        int cnt;
816        struct grspw_pkt *pkt, *last;
817
818        pkt = list->head;
819
820        if ( (max < 1) || (pkt == NULL) ) {
821                grspw_list_clr(rlist);
822                return 0;
823        }
824
825        cnt = 0;
826        rlist->head = pkt;
827        last = pkt;
828        while ((cnt < max) && pkt) {
829                last = pkt;
830                pkt = pkt->next;
831                cnt++;
832        }
833        rlist->tail = last;
834        grspw_list_remove_head_list(list, rlist);
835        return cnt;
836}
837
838#endif
Note: See TracBrowser for help on using the repository browser.