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

Subversion Repositories spacewire_light

[/] [spacewire_light/] [trunk/] [sw/] [rtems_driver/] [spacewirelight.h] - Rev 12

Go to most recent revision | Compare with Previous | Blame | View Log

/*
 * Copyright 2010 Joris van Rantwijk
 *
 * This code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */
 
/**
 * @file    spacewirelight.h
 * @brief   SpaceWire Light driver for RTEMS 4.10 on LEON3.
 *
 * == Resources ==
 *
 * The driver allocates resources during the call to spwl_open_XXX() and
 * releases all resources in spwl_close().
 *
 * The driver allocates memory by calling malloc() and rtems_memalign().
 * The amount of memory required per device handle depends on the configuration
 * of the driver and the hardware:
 *   ~200 bytes for the device handle;
 *   (rxbufs * rxbufsize) bytes for receive buffers;
 *   (txbufs * txbufsize) bytes for transmit buffers;
 *   2 * 8 * (2**desctablesize) bytes for descriptor tables (where
 *   desctablesize depends on the configuration of the SpaceWire Light core).
 *
 * The driver creates a binary semaphores for internal synchronization.
 *
 * == Data flow ==
 *
 * Data delivery is packet-oriented. Although partial SpaceWire packets
 * may be sent/received, delivery of such data is not guaranteed until
 * the packet has been completed with an end-of-packet marker.
 *
 * For example, it is ok to call spwl_send() without an EOP flag to send
 * a partial SpaceWire packet, but in this case the data may linger in memory
 * for an unlimited period. Data delivery is not guaranteed until after
 * spwl_send() has been called again with the final part of the packet and
 * the EOP flag.
 *
 * Similarly, an incoming partial SpaceWire packet is not guaranteed to
 * be delivered to the application until after the packet's EOP marker
 * has been received.
 *
 * == Concurrency ==
 *
 * All API functions are reentrant, i.e. may be called concurrently
 * from multiple tasks for different device handles.
 *
 * Most API functions are thread-safe, i.e. may be called concurrently
 * for the same device handle. The exceptions are
 *  o spwl_close() must not be called concurrently with any other
 *    API function for the same device handle;
 *  o spwl_recv() and spwl_recv_rxbuf() must not be called concurrently
 *    with themselves or with eachother by multiple tasks for the same
 *    device handle;
 *  o spwl_send() and spwl_send_txbuf() must not be called concurrently
 *    with themselves or with eachother by multiple tasks for the same
 *    device handle.
 *
 * The API functions disable interrupts for limited periods of time
 * to ensure exclusive access to data structures and hardware registers.
 */
 
#ifndef _SPACEWIRELIGHT_H
#define _SPACEWIRELIGHT_H
 
#include <stdint.h>
#include <rtems.h>
 
 
/** Handle used to identify an open SpaceWire Light device. */
typedef struct spwl_context * spwl_handle;
 
 
/** Device ID used by SpaceWire Light in AMBA plug&play table. */
#define DEVICE_SPACEWIRELIGHT   0x131
 
 
/** Link mode. */
typedef enum {
    SPWL_LINKMODE_NOP       = 0,    /**< Leave the SpaceWire link as it is;
                                         don't try to (re)start or stop it. */
    SPWL_LINKMODE_START     = 1,    /**< Enable the SpaceWire link. */
    SPWL_LINKMODE_AUTOSTART = 2,    /**< Enable autostart mode. */
    SPWL_LINKMODE_DISABLE   = 3     /**< Disable the SpaceWire link. */
} spwl_linkmode;
 
 
/** Link status. */
typedef enum {
    SPWL_LINK_OFF           = 0,
    SPWL_LINK_STARTED       = 1,
    SPWL_LINK_CONNECTING    = 2,
    SPWL_LINK_RUN           = 3
} spwl_linkstatus;
 
 
/* Error bits returned by spwl_get_linkstatus(). */
#define SPWL_ERR_DISCONNECT 0x04
#define SPWL_ERR_PARITY     0x08
#define SPWL_ERR_ESCAPE     0x10
#define SPWL_ERR_CREDIT     0x20
#define SPWL_ERR_AHB        0x100
 
/* Flag bits used by recv/send functions. */
#define SPWL_WAIT           0x00    /**< Block task until call can proceed. */
#define SPWL_NO_WAIT        0x01    /**< Do not block task. */
#define SPWL_EOP            0x10    /**< Send/received EOP. */
#define SPWL_EEP            0x20    /**< Send/received EEP. */
 
/* Condition bits used by spwl_wait function. */
#define SPWL_COND_RDYRECV   0x01    /**< Received data is ready. */
#define SPWL_COND_RDYSEND   0x02    /**< Ready for spwl_send(). */
#define SPWL_COND_RDYSENDBUF 0x04   /**< Ready for spwl_send_txbuf(). */
#define SPWL_COND_RECLAIM   0x08    /**< Ready for spwl_reclaim_txbuf(). */
#define SPWL_COND_TIMECODE  0x10    /**< Timecode received after the last call to spwl_get_timecode(). */
#define SPWL_COND_LINKUP    0x20    /**< Link is up. */
#define SPWL_COND_LINKDOWN  0x40    /**< Link is down. */
 
 
/** Optional parameters to be passed when opening the driver. */
struct spwl_options {
 
    /** Number of receive buffers to allocate.
        (Can not be larger than the hardware descriptor table). */
    unsigned int    rxbufs;
 
    /** Number of transmit buffers to allocate.
        (Can not be larger than the hardware descriptor table). */
    unsigned int    txbufs;
 
    /** Size of each receive buffer in bytes (at most 65532). */
    unsigned int    rxbufsize;
 
    /** Size of each allocated transmit buffer in bytes (at most 65532).
        Does not affect the size of queued application buffers. */
    unsigned int    txbufsize;
};
 
 
/** Initializer for spwl_options (default values). */
#define SPWL_OPTIONS_DEFAULT    { 32, 16, 2048, 2048 }
 
 
/** Description of a buffer holding data to be transmitted. */
typedef struct spwl_txbuf {
    const void *data;               /**< Pointer to buffer, 4-byte aligned. */
    uint16_t    nbytes;             /**< Number of bytes to be transmitted. */
    uint16_t    eop;                /**< SPWL_EOP or SPWL_EEP or 0. */
    uint32_t    tag;                /**< Optional application-defined field. */
    struct spwl_txbuf *next;        /**< Used internally by library. */
} spwl_txbuf_t;
 
 
/**
 * Open a SpaceWire Light device.
 *
 * Open the index'th SpaceWire Light device found in the AMBA plug&play map.
 * Allocate receive/transmit buffers and reset the device core.
 *
 * A SpaceWire Light device which is already open, may not be opened again
 * until the existing handle has been closed.
 *
 * @retval RTEMS_SUCCESSFUL     Open successful.
 * @retval RTEMS_INVALID_NUMBER Core not found in AMBA plug&play map.
 * @retval RTEMS_INVALID_SIZE   Invalid option value.
 *
 * @param[out] h    Device handle supplied by the driver.
 * @param[in] index Index of the SpaceWire Light core to use.
 * @param[in] opt   Pointer to a structure of optional device parameters,
 *                  or NULL to use default parameters.
 */
rtems_status_code spwl_open(spwl_handle *h,
                            unsigned int index,
                            const struct spwl_options *opt);
 
 
/**
 * Open a SpaceWire Light device.
 *
 * Open a SpaceWire Light device identified by its hardware base address
 * and IRQ number. Allocate receive/transmit buffers and reset the device core.
 *
 * A SpaceWire Light device which is already open, may not be opened again
 * until the existing handle has been closed.
 *
 * @retval RTEMS_SUCCESSFUL     Open successful.
 * @retval RTEMS_INVALID_SIZE   Invalid option value.
 *
 * @param[out] h    Device handle supplied by the driver.
 * @param[in] addr  Base address of the SpaceWire Light core.
 * @param[in] irq   Interrupt number of the SpaceWire Light core (hardware
 *                  IRQ number, zero-based).
 * @param[in] opt   Pointer to a structure of optional device parameters,
 *                  or NULL to use default parameters.
 */
rtems_status_code spwl_open_hwaddr(spwl_handle *h,
                                   unsigned long addr, unsigned int irq,
                                   const struct spwl_options *opt);
 
 
/**
 * Close an open SpaceWire Light device.
 * Reset the SpaceWire Light core and release all associated memory.
 *
 * This function must not be called concurrently with any other
 * API function for the same device handle.
 *
 * @param[in] h     Device handle to close; this handle will be invalid
 *                  after this call.
 */
void spwl_close(spwl_handle h);
 
 
/**
 * Set the TX clock scaler for the link.
 *
 * The link bit rate defaults to 10 Mbit/s.
 * Link handshake is always done at 10 Mbit/s, regardless of this setting.
 *
 * This function sets the TX bit rate to
 *   (txclkfreq / (scaler + 1)) bits per second;
 *   where txclkfreq is determined by the hardware configuration of the core.
 *
 * If a link is up, this function immediately affects the current bit rate.
 * Future links will perform the handshake at 10 Mbit/s and then switch
 * to the rate programmed through this function.
 *
 * @param[in]  h        Device handle.
 * @param[in]  scaler   Scale factor for TX clock minus 1 (0 <= scaler <= 255).
 */
rtems_status_code spwl_set_linkspeed(spwl_handle h, unsigned int scaler);
 
 
/**
 * Return the currently configured TX clock scaler (minus 1).
 */
unsigned int spwl_get_linkspeed(spwl_handle h);
 
 
/**
 * Return the default TX scaler value (i.e. approximately 10 Mbit).
 */
unsigned int spwl_get_default_linkspeed(spwl_handle h);
 
 
/**
 * Change the mode of the SpaceWire link.
 *
 * @param[in] h         Device handle.
 * @param[in] mode      New mode for SpaceWire link.
 */
rtems_status_code spwl_set_linkmode(spwl_handle h, spwl_linkmode mode);
 
 
/**
 * Return the current status of the SpaceWire link.
 * Also return any link errors that occurred since the previous call to
 * this function.
 *
 * @param[in] h         Device handle.
 * @param[out] status   Current status of SpaceWire link.
 * @param[out] errors   Pending errors as OR mask of SPWL_ERR_xxx values.
 */
rtems_status_code spwl_get_linkstatus(spwl_handle h,
                                      spwl_linkstatus *linkstatus,
                                      unsigned int *errors);
 
 
/**
 * Wait for specified condition with timeout.
 *
 * Block the task until at least one of the specified conditions occurs
 * or the specified timeout elapses.
 *
 * Wait conditions are specified as a bitwise OR of SPWL_COND_xxx constants:
 *   SPWL_COND_RDYRECV :    return when data is ready to be received;
 *   SPWL_COND_RDYSEND :    return when spwl_send() can proceed;
 *   SPWL_COND_RDYSENDBUF : return when spwl_send_txbuf() can proceed;
 *   SPWL_COND_RECLAIM :    return when a tx buffer is ready to be reclaimed.
 *   SPWL_COND_TIMECODE :   return when a timecode has been received after
 *                          the last call to spwl_get_timecode;
 *   SPWL_COND_LINKUP :     return when the link is up;
 *   SPWL_COND_LINKDOWN :   return when the link is down.
 *
 * @retval RTEMS_SUCCESSFUL At least one of the specified conditions satisfied.
 * @retval RTEMS_TIMEOUT    Timeout elapsed before any condition is satisfied.
 *
 * @param[in]  h        Device handle.
 * @param[in]  cond     Conditions to wait for (OR mask of SPWL_COND_xxx bits).
 * @param[out] cond     Conditions satisfied (OR mask of SPWL_COND_xxx bits).
 * @param[in]  timeout  Maximum time to wait as a number of RTEMS clock ticks,
 *                      or 0 to wait forever.
 */
rtems_status_code spwl_wait(spwl_handle h,
                            unsigned int *cond, rtems_interval timeout);
 
 
/**
 * Transfer received data to the specified application buffer.
 *
 * If the end of a SpaceWire packet is reached, stop the transfer and
 * report the end-of-packet marker in *eop.
 *
 * Stop the transfer when maxlen bytes have been transfered without
 * reaching the end of a SpaceWire packet. The remainder of the packet
 * will be transfered during the next call to spwl_recv().
 *
 * If SPWL_NO_WAIT is specified and there is not enough data available
 * to satisfy the request, transfer as much data as is currently available.
 * If SPWL_WAIT is specified, block the task until either maxlen bytes
 * have been received or the end of a SpaceWire packet is reached.
 *
 * @retval RTEMS_SUCCESSFUL     Request was at least partially successful.
 * @retval RTEMS_UNSATISFIED    No data available and SPWL_NO_WAIT specified.
 *
 * This function is more efficient if the application buffer is 4-byte aligned.
 *
 * This function must not be called concurrently with itself or with
 * spwl_recv_rxbuf() from multiple tasks for the same device handle.
 *
 * @param[in]  h        Device handle.
 * @param[out] buf      Pointer to application buffer.
 * @param[in]  maxlen   Maximum number of bytes to transfer.
 * @param[out] ntrans   Actual number of bytes transfered.
 * @param[out] eop      End-of-packet marker; either SPWL_EOP or SPWL_EEP or 0.
 * @param[in]  flags    Blocking mode, either SPWL_WAIT or SPWL_NO_WAIT.
 */
rtems_status_code spwl_recv(spwl_handle h,
                            void *buf, size_t maxlen, size_t *ntrans,
                            unsigned int *eop, unsigned int flags);
 
 
/**
 * Send data to the SpaceWire link.
 *
 * Send maxlen bytes from the application buffer to the SpaceWire link,
 * optionally followed by an end-of-packet marker. If an end-of-packet
 * marker is not specified, the following call to spwl_send() will
 * add more data to the same packet.
 *
 * If SPWL_NO_WAIT is specified and there is not enough room in the
 * transmit queue to satisfy the request, transfer as much data as can
 * be immediately stored.
 * If SPWL_WAIT is specified, block the task until exactly maxlen bytes
 * have been transfered.
 *
 * @retval RTEMS_SUCCESSFUL     Request at least partially succesful.
 * @retval RTEMS_UNSATISFIED    No data could be transfered (SPWL_NO_WAIT).
 *
 * This function is more efficient if the application buffer is 4-byte aligned.
 *
 * This function must not be called concurrently with itself or with
 * spwl_send_txbuf() from multiple tasks for the same device handle.
 *
 * @param[in]  h        Device handle.
 * @param[in]  buf      Pointer to application buffer.
 * @param[in]  maxlen   Maximum number of bytes to transfer.
 * @param[out] ntrans   Actual number of bytes transferred.
 * @param[in]  flags    Bitwise OR of blocking flags (SPWL_WAIT or SPWL_NO_WAIT)
 *                      and end-of-packet marker (SPWL_EOP or SPWL_EEP or 0).
 */
rtems_status_code spwl_send(spwl_handle h,
                            const void *buf, size_t maxlen, size_t *ntrans,
                            unsigned int flags);
 
 
/**
 * Receive data from the SpaceWire link without copying.
 *
 * Take one frame from the tail of the receive queue and pass
 * its data pointer to the application.
 *
 * If SPWL_NO_WAIT is specified and the receive queue is empty, return
 * RTEMS_UNSATISFIED. If SPWL_WAIT is specified an the receive queue
 * is empty, block the task until a received frame becomes available.
 *
 * Data buffers returned by this function are still owned by the driver.
 * When the application has finished processing the data, it must release
 * the buffers back to the driver by calling spwl_release_rxbuf().
 *
 * @retval RTEMS_SUCCESS        Request successful.
 * @retval RTEMS_UNSATISFIED    No received buffer available (SPWL_NO_WAIT).
 *
 * The driver owns a limited number of receive buffers (configurable through
 * spwl_options.rxbufs). If the application holds on to too many received
 * buffers, the driver may run out of buffers to work with.
 *
 * This function is more efficient than spwl_recv() because it does not
 * copy received data. Depending on the hardware configuration, the contents
 * of DMA buffers returned by this function may not be coherent with the
 * data cache of the CPU. The LEON3 provides transparent cache coherency
 * only when cache snooping is enabled in the CPU configuration. Otherwise
 * the application must explicitly deal with cache coherency issues, either
 * by using cache bypass instructions when accessing the data or by flushing
 * the data cache before accessing the buffer.
 *
 * Mixing calls to spwl_recv() and spwl_recv_rxbuf() is not recommended.
 * This function must not be called concurrently with itself or with
 * spwl_recv() from multiple tasks for the same device handle.
 *
 * @param[in]  h        Device handle.
 * @param[out] buf      Pointer to data buffer.
 * @param[out] nbytes   Number of data bytes in returned data buffer.
 * @param[out] eop      End-of-packet flags associated with returned buffer.
 * @param[in]  flags    Blocking mode, either SPWL_WAIT or SPWL_NO_WAIT.
 */
rtems_status_code spwl_recv_rxbuf(spwl_handle h,
                                  void **buf,
                                  uint16_t *nbytes, unsigned int *eop,
                                  unsigned int flags);
 
 
/**
 * Release a receive buffer back to the driver.
 *
 * Buffers obtained through spwl_recv_rxbuf() must be released to the
 * driver through this function. The order in which buffers are released
 * is not important.
 *
 * Each time a pointer is obtained through spwl_recv_rxbuf(), there must be
 * exactly one release of that pointer through this function. Total chaos
 * will ensue if other pointers than those obtained through spwl_recv_rxbuf()
 * are passed to this function, or if a pointer acquired once is released
 * multiple times.
 *
 * @param[in]  h        Device handle.
 * @param[in]  buf      Data buffer to be returned to the driver.
 */
rtems_status_code spwl_release_rxbuf(spwl_handle h, void *buf);
 
 
/**
 * Submit data for transmission to the SpaceWire link without copying.
 *
 * Add the buffer to the tail of the transmit queue. This function is more
 * efficient than spwl_send() because it does not copy data.
 *
 * The data buffer pointer (buf->data) must be 4-byte aligned.
 *
 * If SPWL_NO_WAIT is specified and the transmit queue is full, return
 * RTEMS_UNSATISFIED. If SPWL_WAIT is specified and the transmit queue
 * is full, block the task until the buffer can be queued.
 *
 * The driver internally keeps a pointers to the submitted spwl_txbuf
 * structure. The application must guarantee that this structure, and
 * the buffer it points to, remain valid and unchanged after this call.
 * After the driver finishes processing of the data, the buffer structure
 * is returned to the application through spwl_reclaim_txbuf().
 *
 * @retval RTEMS_SUCCESSFUL     Buffer queued for transmission.
 * @retval RTEMS_UNSATISFIED    No room in TX queue (SPWL_NO_WAIT).
 *
 * Mixing calls to spwl_send() and spwl_send_txbuf() is not recommended.
 * This function must not be called concurrently with itself or with
 * spwl_send() from multiple tasks for the same device handle.
 *
 * @param[in]  h        Device handle.
 * @param[in]  buf      Structure describing frame to be queued.
 * @param[in]  flags    Blocking mode, either SPWL_WAIT or SPWL_NO_WAIT.
 */
rtems_status_code spwl_send_txbuf(spwl_handle h,
                                  struct spwl_txbuf *buf, unsigned int flags);
 
 
/**
 * Reclaim transmit buffer after completion of transmission.
 *
 * Buffers queued through spwl_send_txbuf() are eventually passed back
 * to the application through this function. The driver returns the same
 * spwl_txbuf pointers that were originally submitted by the application.
 * Buffers are passed back in the same order in which they were submitted
 * by the application.
 *
 * Except for the "next" field, the contents of the spwl_txbuf structures
 * is not changed by the driver. The "next" field is used internally by the
 * driver and is set to NULL when the buffer is returned.
 *
 * If SPWL_NO_WAIT is specified and there are no buffers ready to be reclaimed,
 * return RTEMS_UNSATISFIED. If SPWL_WAIT is specified, block the task until
 * a buffer can be reclaimed.
 *
 * @retval RTEMS_SUCCESSFUL     Successfully reclaimed a buffer.
 * @retval RTEMS_UNSATISFIED    No reclaimable buffer (SPWL_NO_WAIT).
 *
 * @param[in]  h        Device handle.
 * @param[out] buf      Completed spwl_txbuf structure.
 * @param[in]  flags    Blocking mode, either SPWL_WAIT or SPWL_NO_WAIT.
 */
rtems_status_code spwl_reclaim_txbuf(spwl_handle h,
                                     struct spwl_txbuf **buf,
                                     unsigned int flags);
 
 
/**
 * Return last received timecode.
 */
uint8_t spwl_get_timecode(spwl_handle h);
 
 
/**
 * Send a timecode to the SpaceWire link.
 *
 * @param[in]  h        Device handle.
 * @param[in]  timecode Time code to transmit.
 */
rtems_status_code spwl_send_timecode(spwl_handle h, uint8_t timecode);
 
#endif
/* end */
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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