OpenCores
URL https://opencores.org/ocsvn/spacewire_light/spacewire_light/trunk

Subversion Repositories spacewire_light

[/] [spacewire_light/] [trunk/] [sw/] [rtems_driver/] [spacewirelight.h] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 jorisvr
/*
2
 * Copyright 2010 Joris van Rantwijk
3
 *
4
 * This code is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 2 of the License, or
7
 * (at your option) any later version.
8
 */
9
 
10
/**
11
 * @file    spacewirelight.h
12
 * @brief   SpaceWire Light driver for RTEMS 4.10 on LEON3.
13
 *
14
 * == Resources ==
15
 *
16
 * The driver allocates resources during the call to spwl_open_XXX() and
17
 * releases all resources in spwl_close().
18
 *
19
 * The driver allocates memory by calling malloc() and rtems_memalign().
20
 * The amount of memory required per device handle depends on the configuration
21
 * of the driver and the hardware:
22
 *   ~200 bytes for the device handle;
23
 *   (rxbufs * rxbufsize) bytes for receive buffers;
24
 *   (txbufs * txbufsize) bytes for transmit buffers;
25
 *   2 * 8 * (2**desctablesize) bytes for descriptor tables (where
26
 *   desctablesize depends on the configuration of the SpaceWire Light core).
27
 *
28
 * The driver creates a binary semaphores for internal synchronization.
29
 *
30
 * == Data flow ==
31
 *
32
 * Data delivery is packet-oriented. Although partial SpaceWire packets
33
 * may be sent/received, delivery of such data is not guaranteed until
34
 * the packet has been completed with an end-of-packet marker.
35
 *
36
 * For example, it is ok to call spwl_send() without an EOP flag to send
37
 * a partial SpaceWire packet, but in this case the data may linger in memory
38
 * for an unlimited period. Data delivery is not guaranteed until after
39
 * spwl_send() has been called again with the final part of the packet and
40
 * the EOP flag.
41
 *
42
 * Similarly, an incoming partial SpaceWire packet is not guaranteed to
43
 * be delivered to the application until after the packet's EOP marker
44
 * has been received.
45
 *
46
 * == Concurrency ==
47
 *
48
 * All API functions are reentrant, i.e. may be called concurrently
49
 * from multiple tasks for different device handles.
50
 *
51
 * Most API functions are thread-safe, i.e. may be called concurrently
52
 * for the same device handle. The exceptions are
53
 *  o spwl_close() must not be called concurrently with any other
54
 *    API function for the same device handle;
55
 *  o spwl_recv() and spwl_recv_rxbuf() must not be called concurrently
56
 *    with themselves or with eachother by multiple tasks for the same
57
 *    device handle;
58
 *  o spwl_send() and spwl_send_txbuf() must not be called concurrently
59
 *    with themselves or with eachother by multiple tasks for the same
60
 *    device handle.
61
 *
62
 * The API functions disable interrupts for limited periods of time
63
 * to ensure exclusive access to data structures and hardware registers.
64
 */
65
 
66
#ifndef _SPACEWIRELIGHT_H
67
#define _SPACEWIRELIGHT_H
68
 
69
#include <stdint.h>
70
#include <rtems.h>
71
 
72
 
73
/** Handle used to identify an open SpaceWire Light device. */
74
typedef struct spwl_context * spwl_handle;
75
 
76
 
77
/** Device ID used by SpaceWire Light in AMBA plug&play table. */
78
#define DEVICE_SPACEWIRELIGHT   0x131
79
 
80
 
81
/** Link mode. */
82
typedef enum {
83
    SPWL_LINKMODE_NOP       = 0,    /**< Leave the SpaceWire link as it is;
84
                                         don't try to (re)start or stop it. */
85
    SPWL_LINKMODE_START     = 1,    /**< Enable the SpaceWire link. */
86
    SPWL_LINKMODE_AUTOSTART = 2,    /**< Enable autostart mode. */
87
    SPWL_LINKMODE_DISABLE   = 3     /**< Disable the SpaceWire link. */
88
} spwl_linkmode;
89
 
90
 
91
/** Link status. */
92
typedef enum {
93
    SPWL_LINK_OFF           = 0,
94
    SPWL_LINK_STARTED       = 1,
95
    SPWL_LINK_CONNECTING    = 2,
96
    SPWL_LINK_RUN           = 3
97
} spwl_linkstatus;
98
 
99
 
100
/* Error bits returned by spwl_get_linkstatus(). */
101
#define SPWL_ERR_DISCONNECT 0x04
102
#define SPWL_ERR_PARITY     0x08
103
#define SPWL_ERR_ESCAPE     0x10
104
#define SPWL_ERR_CREDIT     0x20
105
#define SPWL_ERR_AHB        0x100
106
 
107
/* Flag bits used by recv/send functions. */
108
#define SPWL_WAIT           0x00    /**< Block task until call can proceed. */
109
#define SPWL_NO_WAIT        0x01    /**< Do not block task. */
110
#define SPWL_EOP            0x10    /**< Send/received EOP. */
111
#define SPWL_EEP            0x20    /**< Send/received EEP. */
112
 
113
/* Condition bits used by spwl_wait function. */
114
#define SPWL_COND_RDYRECV   0x01    /**< Received data is ready. */
115
#define SPWL_COND_RDYSEND   0x02    /**< Ready for spwl_send(). */
116
#define SPWL_COND_RDYSENDBUF 0x04   /**< Ready for spwl_send_txbuf(). */
117
#define SPWL_COND_RECLAIM   0x08    /**< Ready for spwl_reclaim_txbuf(). */
118
#define SPWL_COND_TIMECODE  0x10    /**< Timecode received after the last call to spwl_get_timecode(). */
119
#define SPWL_COND_LINKUP    0x20    /**< Link is up. */
120
#define SPWL_COND_LINKDOWN  0x40    /**< Link is down. */
121
 
122
 
123
/** Optional parameters to be passed when opening the driver. */
124
struct spwl_options {
125
 
126
    /** Number of receive buffers to allocate.
127
        (Can not be larger than the hardware descriptor table). */
128
    unsigned int    rxbufs;
129
 
130
    /** Number of transmit buffers to allocate.
131
        (Can not be larger than the hardware descriptor table). */
132
    unsigned int    txbufs;
133
 
134
    /** Size of each receive buffer in bytes (at most 65532). */
135
    unsigned int    rxbufsize;
136
 
137
    /** Size of each allocated transmit buffer in bytes (at most 65532).
138
        Does not affect the size of queued application buffers. */
139
    unsigned int    txbufsize;
140
};
141
 
142
 
143
/** Initializer for spwl_options (default values). */
144
#define SPWL_OPTIONS_DEFAULT    { 32, 16, 2048, 2048 }
145
 
146
 
147
/** Description of a buffer holding data to be transmitted. */
148
typedef struct spwl_txbuf {
149
    const void *data;               /**< Pointer to buffer, 4-byte aligned. */
150
    uint16_t    nbytes;             /**< Number of bytes to be transmitted. */
151
    uint16_t    eop;                /**< SPWL_EOP or SPWL_EEP or 0. */
152
    uint32_t    tag;                /**< Optional application-defined field. */
153
    struct spwl_txbuf *next;        /**< Used internally by library. */
154
} spwl_txbuf_t;
155
 
156
 
157
/**
158
 * Open a SpaceWire Light device.
159
 *
160
 * Open the index'th SpaceWire Light device found in the AMBA plug&play map.
161
 * Allocate receive/transmit buffers and reset the device core.
162
 *
163
 * A SpaceWire Light device which is already open, may not be opened again
164
 * until the existing handle has been closed.
165
 *
166
 * @retval RTEMS_SUCCESSFUL     Open successful.
167
 * @retval RTEMS_INVALID_NUMBER Core not found in AMBA plug&play map.
168
 * @retval RTEMS_INVALID_SIZE   Invalid option value.
169
 *
170
 * @param[out] h    Device handle supplied by the driver.
171
 * @param[in] index Index of the SpaceWire Light core to use.
172
 * @param[in] opt   Pointer to a structure of optional device parameters,
173
 *                  or NULL to use default parameters.
174
 */
175
rtems_status_code spwl_open(spwl_handle *h,
176
                            unsigned int index,
177
                            const struct spwl_options *opt);
178
 
179
 
180
/**
181
 * Open a SpaceWire Light device.
182
 *
183
 * Open a SpaceWire Light device identified by its hardware base address
184
 * and IRQ number. Allocate receive/transmit buffers and reset the device core.
185
 *
186
 * A SpaceWire Light device which is already open, may not be opened again
187
 * until the existing handle has been closed.
188
 *
189
 * @retval RTEMS_SUCCESSFUL     Open successful.
190
 * @retval RTEMS_INVALID_SIZE   Invalid option value.
191
 *
192
 * @param[out] h    Device handle supplied by the driver.
193
 * @param[in] addr  Base address of the SpaceWire Light core.
194
 * @param[in] irq   Interrupt number of the SpaceWire Light core (hardware
195
 *                  IRQ number, zero-based).
196
 * @param[in] opt   Pointer to a structure of optional device parameters,
197
 *                  or NULL to use default parameters.
198
 */
199
rtems_status_code spwl_open_hwaddr(spwl_handle *h,
200
                                   unsigned long addr, unsigned int irq,
201
                                   const struct spwl_options *opt);
202
 
203
 
204
/**
205
 * Close an open SpaceWire Light device.
206
 * Reset the SpaceWire Light core and release all associated memory.
207
 *
208
 * This function must not be called concurrently with any other
209
 * API function for the same device handle.
210
 *
211
 * @param[in] h     Device handle to close; this handle will be invalid
212
 *                  after this call.
213
 */
214
void spwl_close(spwl_handle h);
215
 
216
 
217
/**
218
 * Set the TX clock scaler for the link.
219
 *
220
 * The link bit rate defaults to 10 Mbit/s.
221
 * Link handshake is always done at 10 Mbit/s, regardless of this setting.
222
 *
223
 * This function sets the TX bit rate to
224
 *   (txclkfreq / (scaler + 1)) bits per second;
225
 *   where txclkfreq is determined by the hardware configuration of the core.
226
 *
227
 * If a link is up, this function immediately affects the current bit rate.
228
 * Future links will perform the handshake at 10 Mbit/s and then switch
229
 * to the rate programmed through this function.
230
 *
231
 * @param[in]  h        Device handle.
232
 * @param[in]  scaler   Scale factor for TX clock minus 1 (0 <= scaler <= 255).
233
 */
234
rtems_status_code spwl_set_linkspeed(spwl_handle h, unsigned int scaler);
235
 
236
 
237
/**
238
 * Return the currently configured TX clock scaler (minus 1).
239
 */
240
unsigned int spwl_get_linkspeed(spwl_handle h);
241
 
242
 
243
/**
244
 * Return the default TX scaler value (i.e. approximately 10 Mbit).
245
 */
246
unsigned int spwl_get_default_linkspeed(spwl_handle h);
247
 
248
 
249
/**
250
 * Change the mode of the SpaceWire link.
251
 *
252
 * @param[in] h         Device handle.
253
 * @param[in] mode      New mode for SpaceWire link.
254
 */
255
rtems_status_code spwl_set_linkmode(spwl_handle h, spwl_linkmode mode);
256
 
257
 
258
/**
259
 * Return the current status of the SpaceWire link.
260
 * Also return any link errors that occurred since the previous call to
261
 * this function.
262
 *
263
 * @param[in] h         Device handle.
264
 * @param[out] status   Current status of SpaceWire link.
265
 * @param[out] errors   Pending errors as OR mask of SPWL_ERR_xxx values.
266
 */
267
rtems_status_code spwl_get_linkstatus(spwl_handle h,
268
                                      spwl_linkstatus *linkstatus,
269
                                      unsigned int *errors);
270
 
271
 
272
/**
273
 * Wait for specified condition with timeout.
274
 *
275
 * Block the task until at least one of the specified conditions occurs
276
 * or the specified timeout elapses.
277
 *
278
 * Wait conditions are specified as a bitwise OR of SPWL_COND_xxx constants:
279
 *   SPWL_COND_RDYRECV :    return when data is ready to be received;
280
 *   SPWL_COND_RDYSEND :    return when spwl_send() can proceed;
281
 *   SPWL_COND_RDYSENDBUF : return when spwl_send_txbuf() can proceed;
282
 *   SPWL_COND_RECLAIM :    return when a tx buffer is ready to be reclaimed.
283
 *   SPWL_COND_TIMECODE :   return when a timecode has been received after
284
 *                          the last call to spwl_get_timecode;
285
 *   SPWL_COND_LINKUP :     return when the link is up;
286
 *   SPWL_COND_LINKDOWN :   return when the link is down.
287
 *
288
 * @retval RTEMS_SUCCESSFUL At least one of the specified conditions satisfied.
289
 * @retval RTEMS_TIMEOUT    Timeout elapsed before any condition is satisfied.
290
 *
291
 * @param[in]  h        Device handle.
292
 * @param[in]  cond     Conditions to wait for (OR mask of SPWL_COND_xxx bits).
293
 * @param[out] cond     Conditions satisfied (OR mask of SPWL_COND_xxx bits).
294
 * @param[in]  timeout  Maximum time to wait as a number of RTEMS clock ticks,
295
 *                      or 0 to wait forever.
296
 */
297
rtems_status_code spwl_wait(spwl_handle h,
298
                            unsigned int *cond, rtems_interval timeout);
299
 
300
 
301
/**
302
 * Transfer received data to the specified application buffer.
303
 *
304
 * If the end of a SpaceWire packet is reached, stop the transfer and
305
 * report the end-of-packet marker in *eop.
306
 *
307
 * Stop the transfer when maxlen bytes have been transfered without
308
 * reaching the end of a SpaceWire packet. The remainder of the packet
309
 * will be transfered during the next call to spwl_recv().
310
 *
311
 * If SPWL_NO_WAIT is specified and there is not enough data available
312
 * to satisfy the request, transfer as much data as is currently available.
313
 * If SPWL_WAIT is specified, block the task until either maxlen bytes
314
 * have been received or the end of a SpaceWire packet is reached.
315
 *
316
 * @retval RTEMS_SUCCESSFUL     Request was at least partially successful.
317
 * @retval RTEMS_UNSATISFIED    No data available and SPWL_NO_WAIT specified.
318
 *
319
 * This function is more efficient if the application buffer is 4-byte aligned.
320
 *
321
 * This function must not be called concurrently with itself or with
322
 * spwl_recv_rxbuf() from multiple tasks for the same device handle.
323
 *
324
 * @param[in]  h        Device handle.
325
 * @param[out] buf      Pointer to application buffer.
326
 * @param[in]  maxlen   Maximum number of bytes to transfer.
327
 * @param[out] ntrans   Actual number of bytes transfered.
328
 * @param[out] eop      End-of-packet marker; either SPWL_EOP or SPWL_EEP or 0.
329
 * @param[in]  flags    Blocking mode, either SPWL_WAIT or SPWL_NO_WAIT.
330
 */
331
rtems_status_code spwl_recv(spwl_handle h,
332
                            void *buf, size_t maxlen, size_t *ntrans,
333
                            unsigned int *eop, unsigned int flags);
334
 
335
 
336
/**
337
 * Send data to the SpaceWire link.
338
 *
339
 * Send maxlen bytes from the application buffer to the SpaceWire link,
340
 * optionally followed by an end-of-packet marker. If an end-of-packet
341
 * marker is not specified, the following call to spwl_send() will
342
 * add more data to the same packet.
343
 *
344
 * If SPWL_NO_WAIT is specified and there is not enough room in the
345
 * transmit queue to satisfy the request, transfer as much data as can
346
 * be immediately stored.
347
 * If SPWL_WAIT is specified, block the task until exactly maxlen bytes
348
 * have been transfered.
349
 *
350
 * @retval RTEMS_SUCCESSFUL     Request at least partially succesful.
351
 * @retval RTEMS_UNSATISFIED    No data could be transfered (SPWL_NO_WAIT).
352
 *
353
 * This function is more efficient if the application buffer is 4-byte aligned.
354
 *
355
 * This function must not be called concurrently with itself or with
356
 * spwl_send_txbuf() from multiple tasks for the same device handle.
357
 *
358
 * @param[in]  h        Device handle.
359
 * @param[in]  buf      Pointer to application buffer.
360
 * @param[in]  maxlen   Maximum number of bytes to transfer.
361
 * @param[out] ntrans   Actual number of bytes transferred.
362
 * @param[in]  flags    Bitwise OR of blocking flags (SPWL_WAIT or SPWL_NO_WAIT)
363
 *                      and end-of-packet marker (SPWL_EOP or SPWL_EEP or 0).
364
 */
365
rtems_status_code spwl_send(spwl_handle h,
366
                            const void *buf, size_t maxlen, size_t *ntrans,
367
                            unsigned int flags);
368
 
369
 
370
/**
371
 * Receive data from the SpaceWire link without copying.
372
 *
373
 * Take one frame from the tail of the receive queue and pass
374
 * its data pointer to the application.
375
 *
376
 * If SPWL_NO_WAIT is specified and the receive queue is empty, return
377
 * RTEMS_UNSATISFIED. If SPWL_WAIT is specified an the receive queue
378
 * is empty, block the task until a received frame becomes available.
379
 *
380
 * Data buffers returned by this function are still owned by the driver.
381
 * When the application has finished processing the data, it must release
382
 * the buffers back to the driver by calling spwl_release_rxbuf().
383
 *
384
 * @retval RTEMS_SUCCESS        Request successful.
385
 * @retval RTEMS_UNSATISFIED    No received buffer available (SPWL_NO_WAIT).
386
 *
387
 * The driver owns a limited number of receive buffers (configurable through
388
 * spwl_options.rxbufs). If the application holds on to too many received
389
 * buffers, the driver may run out of buffers to work with.
390
 *
391
 * This function is more efficient than spwl_recv() because it does not
392
 * copy received data. Depending on the hardware configuration, the contents
393
 * of DMA buffers returned by this function may not be coherent with the
394
 * data cache of the CPU. The LEON3 provides transparent cache coherency
395
 * only when cache snooping is enabled in the CPU configuration. Otherwise
396
 * the application must explicitly deal with cache coherency issues, either
397
 * by using cache bypass instructions when accessing the data or by flushing
398
 * the data cache before accessing the buffer.
399
 *
400
 * Mixing calls to spwl_recv() and spwl_recv_rxbuf() is not recommended.
401
 * This function must not be called concurrently with itself or with
402
 * spwl_recv() from multiple tasks for the same device handle.
403
 *
404
 * @param[in]  h        Device handle.
405
 * @param[out] buf      Pointer to data buffer.
406
 * @param[out] nbytes   Number of data bytes in returned data buffer.
407
 * @param[out] eop      End-of-packet flags associated with returned buffer.
408
 * @param[in]  flags    Blocking mode, either SPWL_WAIT or SPWL_NO_WAIT.
409
 */
410
rtems_status_code spwl_recv_rxbuf(spwl_handle h,
411
                                  void **buf,
412
                                  uint16_t *nbytes, unsigned int *eop,
413
                                  unsigned int flags);
414
 
415
 
416
/**
417
 * Release a receive buffer back to the driver.
418
 *
419
 * Buffers obtained through spwl_recv_rxbuf() must be released to the
420
 * driver through this function. The order in which buffers are released
421
 * is not important.
422
 *
423
 * Each time a pointer is obtained through spwl_recv_rxbuf(), there must be
424
 * exactly one release of that pointer through this function. Total chaos
425
 * will ensue if other pointers than those obtained through spwl_recv_rxbuf()
426
 * are passed to this function, or if a pointer acquired once is released
427
 * multiple times.
428
 *
429
 * @param[in]  h        Device handle.
430
 * @param[in]  buf      Data buffer to be returned to the driver.
431
 */
432
rtems_status_code spwl_release_rxbuf(spwl_handle h, void *buf);
433
 
434
 
435
/**
436
 * Submit data for transmission to the SpaceWire link without copying.
437
 *
438
 * Add the buffer to the tail of the transmit queue. This function is more
439
 * efficient than spwl_send() because it does not copy data.
440
 *
441
 * The data buffer pointer (buf->data) must be 4-byte aligned.
442
 *
443
 * If SPWL_NO_WAIT is specified and the transmit queue is full, return
444
 * RTEMS_UNSATISFIED. If SPWL_WAIT is specified and the transmit queue
445
 * is full, block the task until the buffer can be queued.
446
 *
447
 * The driver internally keeps a pointers to the submitted spwl_txbuf
448
 * structure. The application must guarantee that this structure, and
449
 * the buffer it points to, remain valid and unchanged after this call.
450
 * After the driver finishes processing of the data, the buffer structure
451
 * is returned to the application through spwl_reclaim_txbuf().
452
 *
453
 * @retval RTEMS_SUCCESSFUL     Buffer queued for transmission.
454
 * @retval RTEMS_UNSATISFIED    No room in TX queue (SPWL_NO_WAIT).
455
 *
456
 * Mixing calls to spwl_send() and spwl_send_txbuf() is not recommended.
457
 * This function must not be called concurrently with itself or with
458
 * spwl_send() from multiple tasks for the same device handle.
459
 *
460
 * @param[in]  h        Device handle.
461
 * @param[in]  buf      Structure describing frame to be queued.
462
 * @param[in]  flags    Blocking mode, either SPWL_WAIT or SPWL_NO_WAIT.
463
 */
464
rtems_status_code spwl_send_txbuf(spwl_handle h,
465
                                  struct spwl_txbuf *buf, unsigned int flags);
466
 
467
 
468
/**
469
 * Reclaim transmit buffer after completion of transmission.
470
 *
471
 * Buffers queued through spwl_send_txbuf() are eventually passed back
472
 * to the application through this function. The driver returns the same
473
 * spwl_txbuf pointers that were originally submitted by the application.
474
 * Buffers are passed back in the same order in which they were submitted
475
 * by the application.
476
 *
477
 * Except for the "next" field, the contents of the spwl_txbuf structures
478
 * is not changed by the driver. The "next" field is used internally by the
479
 * driver and is set to NULL when the buffer is returned.
480
 *
481
 * If SPWL_NO_WAIT is specified and there are no buffers ready to be reclaimed,
482
 * return RTEMS_UNSATISFIED. If SPWL_WAIT is specified, block the task until
483
 * a buffer can be reclaimed.
484
 *
485
 * @retval RTEMS_SUCCESSFUL     Successfully reclaimed a buffer.
486
 * @retval RTEMS_UNSATISFIED    No reclaimable buffer (SPWL_NO_WAIT).
487
 *
488
 * @param[in]  h        Device handle.
489
 * @param[out] buf      Completed spwl_txbuf structure.
490
 * @param[in]  flags    Blocking mode, either SPWL_WAIT or SPWL_NO_WAIT.
491
 */
492
rtems_status_code spwl_reclaim_txbuf(spwl_handle h,
493
                                     struct spwl_txbuf **buf,
494
                                     unsigned int flags);
495
 
496
 
497
/**
498
 * Return last received timecode.
499
 */
500
uint8_t spwl_get_timecode(spwl_handle h);
501
 
502
 
503
/**
504
 * Send a timecode to the SpaceWire link.
505
 *
506
 * @param[in]  h        Device handle.
507
 * @param[in]  timecode Time code to transmit.
508
 */
509
rtems_status_code spwl_send_timecode(spwl_handle h, uint8_t timecode);
510
 
511
#endif
512
/* end */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.