summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/mvme3100/include/bsp/if_tsec_pub.h
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/powerpc/mvme3100/include/bsp/if_tsec_pub.h')
-rw-r--r--bsps/powerpc/mvme3100/include/bsp/if_tsec_pub.h475
1 files changed, 475 insertions, 0 deletions
diff --git a/bsps/powerpc/mvme3100/include/bsp/if_tsec_pub.h b/bsps/powerpc/mvme3100/include/bsp/if_tsec_pub.h
new file mode 100644
index 0000000000..7eb0358eae
--- /dev/null
+++ b/bsps/powerpc/mvme3100/include/bsp/if_tsec_pub.h
@@ -0,0 +1,475 @@
+/**
+ * @file
+ *
+ * @ingroup powerpc_iftsecpub
+ *
+ * @brief IF_TSEC_PUB Support
+ */
+
+#ifndef IF_TSEC_PUBLIC_INTERFACE_H
+#define IF_TSEC_PUBLIC_INTERFACE_H
+
+/*
+ * Authorship
+ * ----------
+ * This software ('mvme3100' RTEMS BSP) was created by
+ *
+ * Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
+ * Stanford Linear Accelerator Center, Stanford University.
+ *
+ * Acknowledgement of sponsorship
+ * ------------------------------
+ * The 'mvme3100' BSP was produced by
+ * the Stanford Linear Accelerator Center, Stanford University,
+ * under Contract DE-AC03-76SFO0515 with the Department of Energy.
+ *
+ * Government disclaimer of liability
+ * ----------------------------------
+ * Neither the United States nor the United States Department of Energy,
+ * nor any of their employees, makes any warranty, express or implied, or
+ * assumes any legal liability or responsibility for the accuracy,
+ * completeness, or usefulness of any data, apparatus, product, or process
+ * disclosed, or represents that its use would not infringe privately owned
+ * rights.
+ *
+ * Stanford disclaimer of liability
+ * --------------------------------
+ * Stanford University makes no representations or warranties, express or
+ * implied, nor assumes any liability for the use of this software.
+ *
+ * Stanford disclaimer of copyright
+ * --------------------------------
+ * Stanford University, owner of the copyright, hereby disclaims its
+ * copyright and all other rights in this software. Hence, anyone may
+ * freely use it for any purpose without restriction.
+ *
+ * Maintenance of notices
+ * ----------------------
+ * In the interest of clarity regarding the origin and status of this
+ * SLAC software, this and all the preceding Stanford University notices
+ * are to remain affixed to any copy or derivative of this software made
+ * or distributed by the recipient and are to be affixed to any copy of
+ * software made or distributed by the recipient that contains a copy or
+ * derivative of this software.
+ *
+ * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
+ */
+
+#include <rtems.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Opaque driver handle */
+struct tsec_private;
+
+/********** Low-level Driver API ****************/
+
+/**
+ * @defgroup powerpc_iftsecpub Low-level Driver API
+ *
+ * @ingroup powerpc_mvme3100
+ *
+ * @brief This API provides driver access to applications that
+ * want to use e.g., the second ethernet interface
+ * independently from the BSD TCP/IP stack. E.g., for
+ * raw ethernet packet communication...
+ */
+
+#define TSEC_TXIRQ ( (1<<(31-9)) | (1<<(31-11)) )
+#define TSEC_RXIRQ ( (1<<(31-0)) | (1<<(31- 3)) | (1<<(31-24)) )
+#define TSEC_LKIRQ ( 1<<(31- 4) )
+/*
+ * Setup an interface.
+ * Allocates resources for descriptor rings and sets up the driver software structure.
+ *
+ * Arguments:
+ * unit:
+ * interface # (1..2). The interface must not be attached to BSD already.
+ *
+ * driver_tid:
+ * ISR posts RTEMS event # ('unit' - 1) to task with ID 'driver_tid' and disables interrupts
+ * from this interface.
+ *
+ * void (*cleanup_txbuf)(void *user_buf, void *cleanup_txbuf_arg, int error_on_tx_occurred):
+ * Pointer to user-supplied callback to release a buffer that had been sent
+ * by BSP_tsec_send_buf() earlier. The callback is passed 'cleanup_txbuf_arg'
+ * and a flag indicating whether the send had been successful.
+ * The driver no longer accesses 'user_buf' after invoking this callback.
+ * CONTEXT: This callback is executed either by BSP_tsec_swipe_tx() or
+ * BSP_tsec_send_buf(), BSP_tsec_init_hw(), BSP_tsec_stop_hw() (the latter
+ * ones calling BSP_tsec_swipe_tx()).
+ * void *cleanup_txbuf_arg:
+ * Closure argument that is passed on to 'cleanup_txbuf()' callback;
+ *
+ * void *(*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
+ * Pointer to user-supplied callback to allocate a buffer for subsequent
+ * insertion into the RX ring by the driver.
+ * RETURNS: opaque handle to the buffer (which may be a more complex object
+ * such as an 'mbuf'). The handle is not used by the driver directly
+ * but passed back to the 'consume_rxbuf()' callback.
+ * Size of the available data area and pointer to buffer's data area
+ * in '*psize' and '*p_data_area', respectively.
+ * If no buffer is available, this routine should return NULL in which
+ * case the driver drops the last packet and re-uses the last buffer
+ * instead of handing it out to 'consume_rxbuf()'.
+ * CONTEXT: Called when initializing the RX ring (BSP_tsec_init_hw()) or when
+ * swiping it (BSP_tsec_swipe_rx()).
+ *
+ *
+ * void (*consume_rxbuf)(void *user_buf, void *consume_rxbuf_arg, int len);
+ * Pointer to user-supplied callback to pass a received buffer back to
+ * the user. The driver no longer accesses the buffer after invoking this
+ * callback (with 'len'>0, see below). 'user_buf' is the buffer handle
+ * previously generated by 'alloc_rxbuf()'.
+ * The callback is passed 'cleanup_rxbuf_arg' and a 'len'
+ * argument giving the number of bytes that were received.
+ * 'len' may be <=0 in which case the 'user_buf' argument is NULL.
+ * 'len' == 0 means that the last 'alloc_rxbuf()' had failed,
+ * 'len' < 0 indicates a receiver error. In both cases, the last packet
+ * was dropped/missed and the last buffer will be re-used by the driver.
+ * NOTE: the data are 'prefixed' with two bytes, i.e., the ethernet packet header
+ * is stored at offset 2 in the buffer's data area. Also, the FCS (4 bytes)
+ * is appended. 'len' accounts for both.
+ * CONTEXT: Called from BSP_tsec_swipe_rx().
+ * void *cleanup_rxbuf_arg:
+ * Closure argument that is passed on to 'consume_rxbuf()' callback;
+ *
+ * rx_ring_size, tx_ring_size:
+ * How many big to make the RX and TX descriptor rings. Note that the sizes
+ * may be 0 in which case a reasonable default will be used.
+ * If either ring size is < 0 then the RX or TX will be disabled.
+ * Note that it is illegal in this case to use BSP_tsec_swipe_rx() or
+ * BSP_tsec_swipe_tx(), respectively.
+ *
+ * irq_mask:
+ * Interrupts to enable. OR of flags from above.
+ *
+ */
+struct tsec_private *
+BSP_tsec_setup(
+ int unit,
+ rtems_id driver_tid,
+ void (*cleanup_txbuf)(void *user_buf, void *cleanup_txbuf_arg, int error_on_tx_occurred),
+ void * cleanup_txbuf_arg,
+ void * (*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
+ void (*consume_rxbuf)(void *user_buf, void *consume_rxbuf_arg, int len),
+ void * consume_rxbuf_arg,
+ int rx_ring_size,
+ int tx_ring_size,
+ int irq_mask
+);
+
+/*
+ * Alternate 'setup' routine allowing the user to install an ISR rather
+ * than a task ID.
+ * All parameters (other than 'isr' / 'isr_arg') and the return value
+ * are identical to the BSP_tsec_setup() entry point.
+ */
+struct tsec_private *
+BSP_tsec_setup_1(
+ int unit,
+ void (*isr)(void *isr_arg),
+ void * isr_arg,
+ void (*cleanup_txbuf)(void *user_buf, void *cleanup_txbuf_arg, int error_on_tx_occurred),
+ void * cleanup_txbuf_arg,
+ void * (*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
+ void (*consume_rxbuf)(void *user_buf, void *consume_rxbuf_arg, int len),
+ void * consume_rxbuf_arg,
+ int rx_ring_size,
+ int tx_ring_size,
+ int irq_mask
+);
+
+
+/*
+ * Descriptor scavenger; cleanup the TX ring, passing all buffers
+ * that have been sent to the cleanup_tx() callback.
+ * This routine is called from BSP_tsec_send_buf(), BSP_tsec_init_hw(),
+ * BSP_tsec_stop_hw().
+ *
+ * RETURNS: number of buffers processed.
+ */
+
+int
+BSP_tsec_swipe_tx(struct tsec_private *mp);
+
+
+/*
+ * Reset statistics counters.
+ */
+void
+BSP_tsec_reset_stats(struct tsec_private *mp);
+
+/*
+ * Initialize interface hardware
+ *
+ * 'mp' handle obtained by from BSP_tsec_setup().
+ * 'promisc' whether to set promiscuous flag.
+ * 'enaddr' pointer to six bytes with MAC address. Read
+ * from the device if NULL.
+ * NOTE: multicast filter is cleared by this routine.
+ */
+void
+BSP_tsec_init_hw(struct tsec_private *mp, int promisc, unsigned char *enaddr);
+
+/*
+ * Clear multicast hash filter. No multicast frames are accepted
+ * after executing this routine (unless the hardware was initialized
+ * in 'promiscuous' mode).
+ *
+ * Reset reference count for all hash-table entries
+ * to zero (see BSP_tsec_mcast_filter_accept_del()).
+ */
+void
+BSP_tsec_mcast_filter_clear(struct tsec_private *mp);
+
+/*
+ * Program multicast filter to accept all multicast frames.
+ *
+ * Increment reference count for all hash-table entries
+ * by one (see BSP_tsec_mcast_filter_accept_del()).
+ */
+void
+BSP_tsec_mcast_filter_accept_all(struct tsec_private *mp);
+
+/*
+ * Add a MAC address to the multicast filter and increment
+ * the reference count for the matching hash-table entry
+ * (see BSP_tsec_mcast_filter_accept_del()).
+ *
+ * Existing entries are not changed but note that
+ * the filter is imperfect, i.e., multiple MAC addresses
+ * may alias to a single filter entry. Hence software
+ * filtering must still be performed.
+ *
+ */
+void
+BSP_tsec_mcast_filter_accept_add(struct tsec_private *mp, unsigned char *enaddr);
+
+/*
+ * Remove a MAC address from the (imperfec) multicast
+ * filter.
+ * Note that the driver maintains an internal reference
+ * counter for each multicast hash. The hash-table
+ * entry is only cleared when the reference count
+ * reaches zero ('del' has been called the same
+ * amount of times as 'add' for an address (or
+ * any alias) that matches a given table entry.
+ * BSP_tsec_mcast_filter_clear() resets all reference
+ * counters to zero.
+ */
+void
+BSP_tsec_mcast_filter_accept_del(struct tsec_private *mp, unsigned char *enaddr);
+
+/*
+ * Dump statistics to FILE 'f'. If NULL, stdout is used.
+ */
+void
+BSP_tsec_dump_stats(struct tsec_private *mp, FILE *f);
+
+/*
+ * Shutdown hardware and clean out the rings
+ */
+void
+BSP_tsec_stop_hw(struct tsec_private *mp);
+
+/*
+ * calls BSP_tsec_stop_hw(), releases all resources and marks the interface
+ * as unused.
+ * RETURNS 0 on success, nonzero on failure.
+ * NOTE: the handle MUST NOT be used after successful execution of this
+ * routine.
+ */
+int
+BSP_tsec_detach(struct tsec_private *mp);
+
+/*
+ * Enqueue a mbuf chain or a raw data buffer for transmission;
+ * RETURN: #bytes sent or -1 if there are not enough free descriptors
+ *
+ * If 'len' is <=0 then 'm_head' is assumed to point to a mbuf chain.
+ * OTOH, a raw data packet (or a different type of buffer)
+ * may be sent (non-BSD driver) by pointing data_p to the start of
+ * the data and passing 'len' > 0.
+ * 'm_head' is passed back to the 'cleanup_txbuf()' callback.
+ *
+ * Comments: software cache-flushing incurs a penalty if the
+ * packet cannot be queued since it is flushed anyways.
+ * The algorithm is slightly more efficient in the normal
+ * case, though.
+ *
+ * RETURNS: # bytes enqueued to device for transmission or -1 if no
+ * space in the TX ring was available.
+ */
+
+int
+BSP_tsec_send_buf(struct tsec_private *mp, void *m_head, void *data_p, int len);
+
+/*
+ * Retrieve all received buffers from the RX ring, replacing them
+ * by fresh ones (obtained from the alloc_rxbuf() callback). The
+ * received buffers are passed to consume_rxbuf().
+ *
+ * RETURNS: number of buffers processed.
+ */
+int
+BSP_tsec_swipe_rx(struct tsec_private *mp);
+
+/* read ethernet address from hw to buffer */
+void
+BSP_tsec_read_eaddr(struct tsec_private *mp, unsigned char *eaddr);
+
+/* Read MII register */
+uint32_t
+BSP_tsec_mdio_rd(struct tsec_private *mp, unsigned reg);
+
+/* Write MII register */
+int
+BSP_tsec_mdio_wr(struct tsec_private *mp, unsigned reg, uint32_t val);
+
+/*
+ * read/write media word.
+ * 'cmd': can be SIOCGIFMEDIA, SIOCSIFMEDIA, 0 or 1. The latter
+ * are aliased to the former for convenience.
+ * 'parg': pointer to media word.
+ *
+ * RETURNS: 0 on success, nonzero on error
+ */
+int
+BSP_tsec_media_ioctl(struct tsec_private *mp, int cmd, int *parg);
+
+/* Interrupt related routines */
+
+/*
+ * When it comes to interrupts the chip has two rather
+ * annoying features:
+ * 1 once an IRQ is pending, clearing the IMASK does not
+ * de-assert the interrupt line.
+ * 2 the chip has three physical interrupt lines even though
+ * all events are reported in a single register. Rather
+ * useless; we must hook 3 ISRs w/o any real benefit.
+ * In fact, it makes our life a bit more difficult:
+ *
+ * Hence, for (1) we would have to mask interrupts at the PIC
+ * but to re-enable them we would have to do that three times
+ * because of (2).
+ *
+ * Therefore, we take the following approach:
+ *
+ * ISR masks all interrupts on the TSEC, acks/clears them
+ * and stores the acked irqs in the device struct where
+ * it is picked up by BSP_tsec_ack_irqs().
+ * Since all interrupts are disabled until the daemon
+ * re-enables them after calling BSP_tsec_ack_irqs()
+ * no interrupts are lost.
+ *
+ * BUT: NO isr (including PHY isrs) MUST INTERRUPT ANY
+ * OTHER ONE, i.e., they all must have the same
+ * priority. Otherwise, integrity of the cached
+ * irq_pending variable may be compromised.
+ */
+
+/* Note: the BSP_tsec_enable/disable/ack_irqs() entry points
+ * are deprecated.
+ * The newer API where the user passes a mask allows
+ * for more selective control.
+ */
+
+/* Enable interrupts at device */
+void
+BSP_tsec_enable_irqs(struct tsec_private *mp);
+
+/* Disable interrupts at device */
+void
+BSP_tsec_disable_irqs(struct tsec_private *mp);
+
+/*
+ * Acknowledge (and clear) interrupts.
+ * RETURNS: interrupts that were raised.
+ */
+uint32_t
+BSP_tsec_ack_irqs(struct tsec_private *mp);
+
+/* Enable interrupts included in 'mask' (leaving
+ * already enabled interrupts on). If the mask includes
+ * bits that were not passed to the 'setup' routine then
+ * the behavior is undefined.
+ */
+void
+BSP_tsec_enable_irq_mask(struct tsec_private *mp, uint32_t irq_mask);
+
+/* Disable interrupts included in 'mask' (leaving
+ * other ones that are currently enabled on). If the mask
+ * includes bits that were not passed to the 'setup' routine
+ * then the behavior is undefined.
+
+ * RETURNS: Bitmask of interrupts that were enabled upon entry
+ * into this routine. This can be used to restore the previous
+ * state.
+ */
+uint32_t
+BSP_tsec_disable_irq_mask(struct tsec_private *mp, uint32_t irq_mask);
+
+/* Acknowledge and clear selected interrupts.
+ *
+ * RETURNS: All pending interrupts.
+ *
+ * NOTE: Only pending interrupts contained in 'mask'
+ * are cleared. Others are left pending.
+ *
+ * This routine can be used to check for pending
+ * interrupts (pass mask == 0) or to clear all
+ * interrupts (pass mask == -1).
+ */
+uint32_t
+BSP_tsec_ack_irq_mask(struct tsec_private *mp, uint32_t mask);
+
+
+/* Retrieve the driver daemon TID that was passed to
+ * BSP_tsec_setup().
+ */
+
+rtems_id
+BSP_tsec_get_tid(struct tsec_private *mp);
+
+struct tsec_private *
+BSP_tsec_getp(unsigned index);
+
+/*
+ *
+ * Example driver task loop (note: no synchronization of
+ * buffer access shown!).
+ * RTEMS_EVENTx = 0,1 or 2 depending on IF unit.
+ *
+ * / * setup (obtain handle) and initialize hw here * /
+ *
+ * do {
+ * / * ISR disables IRQs and posts event * /
+ * rtems_event_receive( RTEMS_EVENTx, RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &evs );
+ * irqs = BSP_tsec_ack_irqs(handle);
+ * if ( irqs & BSP_TSEC_IRQ_TX ) {
+ * BSP_tsec_swipe_tx(handle); / * cleanup_txbuf() callback executed * /
+ * }
+ * if ( irqs & BSP_TSEC_IRQ_RX ) {
+ * BSP_tsec_swipe_rx(handle); / * alloc_rxbuf() and consume_rxbuf() executed * /
+ * }
+ * BSP_tsec_enable_irqs(handle);
+ * } while (1);
+ *
+ */
+
+/* PUBLIC RTEMS BSDNET ATTACH FUNCTION */
+struct rtems_bsdnet_ifconfig;
+
+int
+rtems_tsec_attach(struct rtems_bsdnet_ifconfig *ifcfg, int attaching);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif