Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:56

0001 /**
0002  *  @file
0003  *
0004  *  @ingroup powerpc_iftsecpub
0005  *
0006  *  @brief IF_TSEC_PUB Support
0007  */
0008 
0009 #ifndef IF_TSEC_PUBLIC_INTERFACE_H
0010 #define IF_TSEC_PUBLIC_INTERFACE_H
0011 
0012 /*
0013  * Authorship
0014  * ----------
0015  * This software ('mvme3100' RTEMS BSP) was created by
0016  *
0017  *     Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
0018  *     Stanford Linear Accelerator Center, Stanford University.
0019  *
0020  * Acknowledgement of sponsorship
0021  * ------------------------------
0022  * The 'mvme3100' BSP was produced by
0023  *     the Stanford Linear Accelerator Center, Stanford University,
0024  *     under Contract DE-AC03-76SFO0515 with the Department of Energy.
0025  *
0026  * Government disclaimer of liability
0027  * ----------------------------------
0028  * Neither the United States nor the United States Department of Energy,
0029  * nor any of their employees, makes any warranty, express or implied, or
0030  * assumes any legal liability or responsibility for the accuracy,
0031  * completeness, or usefulness of any data, apparatus, product, or process
0032  * disclosed, or represents that its use would not infringe privately owned
0033  * rights.
0034  *
0035  * Stanford disclaimer of liability
0036  * --------------------------------
0037  * Stanford University makes no representations or warranties, express or
0038  * implied, nor assumes any liability for the use of this software.
0039  *
0040  * Stanford disclaimer of copyright
0041  * --------------------------------
0042  * Stanford University, owner of the copyright, hereby disclaims its
0043  * copyright and all other rights in this software.  Hence, anyone may
0044  * freely use it for any purpose without restriction.
0045  *
0046  * Maintenance of notices
0047  * ----------------------
0048  * In the interest of clarity regarding the origin and status of this
0049  * SLAC software, this and all the preceding Stanford University notices
0050  * are to remain affixed to any copy or derivative of this software made
0051  * or distributed by the recipient and are to be affixed to any copy of
0052  * software made or distributed by the recipient that contains a copy or
0053  * derivative of this software.
0054  *
0055  * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
0056  */
0057 
0058 #include <rtems.h>
0059 #include <stdio.h>
0060 #include <stdint.h>
0061 
0062 #ifdef __cplusplus
0063 extern "C" {
0064 #endif
0065 
0066 /* Opaque driver handle */
0067 struct tsec_private;
0068 
0069 /********** Low-level Driver API ****************/
0070 
0071 /**
0072  *  @defgroup powerpc_iftsecpub Low-level Driver API
0073  *
0074  *  @ingroup RTEMSBSPsPowerPCMVME3100
0075  *
0076  *  @brief This API provides driver access to applications that
0077  * want to use e.g., the second ethernet interface
0078  * independently from the BSD TCP/IP stack. E.g., for
0079  * raw ethernet packet communication...
0080  */
0081 
0082 #define TSEC_TXIRQ ( (1<<(31-9)) | (1<<(31-11))                )
0083 #define TSEC_RXIRQ ( (1<<(31-0)) | (1<<(31- 3)) | (1<<(31-24)) )
0084 #define TSEC_LKIRQ (  1<<(31- 4)                               )
0085 /*
0086  * Setup an interface.
0087  * Allocates resources for descriptor rings and sets up the driver software structure.
0088  *
0089  * Arguments:
0090  *  unit:
0091  *      interface # (1..2). The interface must not be attached to BSD already.
0092  *
0093  *  driver_tid:
0094  *      ISR posts RTEMS event # ('unit' - 1) to task with ID 'driver_tid' and disables interrupts
0095  *      from this interface.
0096  *
0097  *  void (*cleanup_txbuf)(void *user_buf, void *cleanup_txbuf_arg, int error_on_tx_occurred):
0098  *      Pointer to user-supplied callback to release a buffer that had been sent
0099  *      by BSP_tsec_send_buf() earlier. The callback is passed 'cleanup_txbuf_arg'
0100  *      and a flag indicating whether the send had been successful.
0101  *      The driver no longer accesses 'user_buf' after invoking this callback.
0102  *      CONTEXT: This callback is executed either by BSP_tsec_swipe_tx() or
0103  *      BSP_tsec_send_buf(), BSP_tsec_init_hw(), BSP_tsec_stop_hw() (the latter
0104  *      ones calling BSP_tsec_swipe_tx()).
0105  *  void *cleanup_txbuf_arg:
0106  *      Closure argument that is passed on to 'cleanup_txbuf()' callback;
0107  *
0108  *  void *(*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
0109  *      Pointer to user-supplied callback to allocate a buffer for subsequent
0110  *      insertion into the RX ring by the driver.
0111  *      RETURNS: opaque handle to the buffer (which may be a more complex object
0112  *               such as an 'mbuf'). The handle is not used by the driver directly
0113  *               but passed back to the 'consume_rxbuf()' callback.
0114  *               Size of the available data area and pointer to buffer's data area
0115  *               in '*psize' and '*p_data_area', respectively.
0116  *               If no buffer is available, this routine should return NULL in which
0117  *               case the driver drops the last packet and re-uses the last buffer
0118  *               instead of handing it out to 'consume_rxbuf()'.
0119  *      CONTEXT: Called when initializing the RX ring (BSP_tsec_init_hw()) or when
0120  *               swiping it (BSP_tsec_swipe_rx()).
0121  *
0122  *
0123  *  void (*consume_rxbuf)(void *user_buf, void *consume_rxbuf_arg, int len);
0124  *      Pointer to user-supplied callback to pass a received buffer back to
0125  *      the user. The driver no longer accesses the buffer after invoking this
0126  *      callback (with 'len'>0, see below). 'user_buf' is the buffer handle
0127  *      previously generated by 'alloc_rxbuf()'.
0128  *      The callback is passed 'cleanup_rxbuf_arg' and a 'len'
0129  *      argument giving the number of bytes that were received.
0130  *      'len' may be <=0 in which case the 'user_buf' argument is NULL.
0131  *      'len' == 0 means that the last 'alloc_rxbuf()' had failed,
0132  *      'len' < 0 indicates a receiver error. In both cases, the last packet
0133  *      was dropped/missed and the last buffer will be re-used by the driver.
0134  *      NOTE: the data are 'prefixed' with two bytes, i.e., the ethernet packet header
0135  *            is stored at offset 2 in the buffer's data area. Also, the FCS (4 bytes)
0136  *            is appended. 'len' accounts for both.
0137  *      CONTEXT: Called from BSP_tsec_swipe_rx().
0138  *  void *cleanup_rxbuf_arg:
0139  *      Closure argument that is passed on to 'consume_rxbuf()' callback;
0140  *
0141  *  rx_ring_size, tx_ring_size:
0142  *      How many big to make the RX and TX descriptor rings. Note that the sizes
0143  *      may be 0 in which case a reasonable default will be used.
0144  *      If either ring size is < 0 then the RX or TX will be disabled.
0145  *      Note that it is illegal in this case to use BSP_tsec_swipe_rx() or
0146  *      BSP_tsec_swipe_tx(), respectively.
0147  *
0148  *  irq_mask:
0149  *      Interrupts to enable. OR of flags from above.
0150  *
0151  */
0152 struct tsec_private *
0153 BSP_tsec_setup(
0154     int      unit,
0155     rtems_id driver_tid,
0156     void     (*cleanup_txbuf)(void *user_buf, void *cleanup_txbuf_arg, int error_on_tx_occurred),
0157     void *   cleanup_txbuf_arg,
0158     void *   (*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
0159     void     (*consume_rxbuf)(void *user_buf, void *consume_rxbuf_arg, int len),
0160     void *   consume_rxbuf_arg,
0161     int      rx_ring_size,
0162     int      tx_ring_size,
0163     int      irq_mask
0164 );
0165 
0166 /*
0167  * Alternate 'setup' routine allowing the user to install an ISR rather
0168  * than a task ID.
0169  * All parameters (other than 'isr' / 'isr_arg') and the return value
0170  * are identical to the BSP_tsec_setup() entry point.
0171  */
0172 struct tsec_private *
0173 BSP_tsec_setup_1(
0174     int      unit,
0175     void     (*isr)(void *isr_arg),
0176     void *   isr_arg,
0177     void     (*cleanup_txbuf)(void *user_buf, void *cleanup_txbuf_arg, int error_on_tx_occurred),
0178     void *   cleanup_txbuf_arg,
0179     void *   (*alloc_rxbuf)(int *p_size, uintptr_t *p_data_addr),
0180     void     (*consume_rxbuf)(void *user_buf, void *consume_rxbuf_arg, int len),
0181     void *   consume_rxbuf_arg,
0182     int      rx_ring_size,
0183     int      tx_ring_size,
0184     int      irq_mask
0185 );
0186 
0187 
0188 /*
0189  * Descriptor scavenger; cleanup the TX ring, passing all buffers
0190  * that have been sent to the cleanup_tx() callback.
0191  * This routine is called from BSP_tsec_send_buf(), BSP_tsec_init_hw(),
0192  * BSP_tsec_stop_hw().
0193  *
0194  * RETURNS: number of buffers processed.
0195  */
0196 
0197 int
0198 BSP_tsec_swipe_tx(struct tsec_private *mp);
0199 
0200 
0201 /*
0202  * Reset statistics counters.
0203  */
0204 void
0205 BSP_tsec_reset_stats(struct tsec_private *mp);
0206 
0207 /*
0208  * Initialize interface hardware
0209  *
0210  * 'mp'         handle obtained by from BSP_tsec_setup().
0211  * 'promisc'    whether to set promiscuous flag.
0212  * 'enaddr'     pointer to six bytes with MAC address. Read
0213  *              from the device if NULL.
0214  * NOTE:        multicast filter is cleared by this routine.
0215  */
0216 void
0217 BSP_tsec_init_hw(struct tsec_private *mp, int promisc, unsigned char *enaddr);
0218 
0219 /*
0220  * Clear multicast hash filter. No multicast frames are accepted
0221  * after executing this routine (unless the hardware was initialized
0222  * in 'promiscuous' mode).
0223  *
0224  * Reset reference count for all hash-table entries
0225  * to zero (see BSP_tsec_mcast_filter_accept_del()).
0226  */
0227 void
0228 BSP_tsec_mcast_filter_clear(struct tsec_private *mp);
0229 
0230 /*
0231  * Program multicast filter to accept all multicast frames.
0232  *
0233  * Increment reference count for all hash-table entries
0234  * by one (see BSP_tsec_mcast_filter_accept_del()).
0235  */
0236 void
0237 BSP_tsec_mcast_filter_accept_all(struct tsec_private *mp);
0238 
0239 /*
0240  * Add a MAC address to the multicast filter and increment
0241  * the reference count for the matching hash-table entry
0242  * (see BSP_tsec_mcast_filter_accept_del()).
0243  *
0244  * Existing entries are not changed but note that
0245  * the filter is imperfect, i.e., multiple MAC addresses
0246  * may alias to a single filter entry. Hence software
0247  * filtering must still be performed.
0248  *
0249  */
0250 void
0251 BSP_tsec_mcast_filter_accept_add(struct tsec_private *mp, unsigned char *enaddr);
0252 
0253 /*
0254  * Remove a MAC address from the (imperfec) multicast
0255  * filter.
0256  * Note that the driver maintains an internal reference
0257  * counter for each multicast hash. The hash-table
0258  * entry is only cleared when the reference count
0259  * reaches zero ('del' has been called the same
0260  * amount of times as 'add' for an address (or
0261  * any alias) that matches a given table entry.
0262  * BSP_tsec_mcast_filter_clear() resets all reference
0263  * counters to zero.
0264  */
0265 void
0266 BSP_tsec_mcast_filter_accept_del(struct tsec_private *mp, unsigned char *enaddr);
0267 
0268 /*
0269  * Dump statistics to FILE 'f'. If NULL, stdout is used.
0270  */
0271 void
0272 BSP_tsec_dump_stats(struct tsec_private *mp, FILE *f);
0273 
0274 /*
0275  * Shutdown hardware and clean out the rings
0276  */
0277 void
0278 BSP_tsec_stop_hw(struct tsec_private *mp);
0279 
0280 /*
0281  * calls BSP_tsec_stop_hw(), releases all resources and marks the interface
0282  * as unused.
0283  * RETURNS 0 on success, nonzero on failure.
0284  * NOTE:   the handle MUST NOT be used after successful execution of this
0285  *         routine.
0286  */
0287 int
0288 BSP_tsec_detach(struct tsec_private *mp);
0289 
0290 /*
0291  * Enqueue a mbuf chain or a raw data buffer for transmission;
0292  * RETURN: #bytes sent or -1 if there are not enough free descriptors
0293  *
0294  * If 'len' is <=0 then 'm_head' is assumed to point to a mbuf chain.
0295  * OTOH, a raw data packet (or a different type of buffer)
0296  * may be sent (non-BSD driver) by pointing data_p to the start of
0297  * the data and passing 'len' > 0.
0298  * 'm_head' is passed back to the 'cleanup_txbuf()' callback.
0299  *
0300  * Comments: software cache-flushing incurs a penalty if the
0301  *           packet cannot be queued since it is flushed anyways.
0302  *           The algorithm is slightly more efficient in the normal
0303  *           case, though.
0304  *
0305  * RETURNS: # bytes enqueued to device for transmission or -1 if no
0306  *          space in the TX ring was available.
0307  */
0308 
0309 int
0310 BSP_tsec_send_buf(struct tsec_private *mp, void *m_head, void *data_p, int len);
0311 
0312 /*
0313  * Retrieve all received buffers from the RX ring, replacing them
0314  * by fresh ones (obtained from the alloc_rxbuf() callback). The
0315  * received buffers are passed to consume_rxbuf().
0316  *
0317  * RETURNS: number of buffers processed.
0318  */
0319 int
0320 BSP_tsec_swipe_rx(struct tsec_private *mp);
0321 
0322 /* read ethernet address from hw to buffer */
0323 void
0324 BSP_tsec_read_eaddr(struct tsec_private *mp, unsigned char *eaddr);
0325 
0326 /* Read MII register */
0327 uint32_t
0328 BSP_tsec_mdio_rd(struct tsec_private *mp, unsigned reg);
0329 
0330 /* Write MII register */
0331 int
0332 BSP_tsec_mdio_wr(struct tsec_private *mp, unsigned reg, uint32_t val);
0333 
0334 /*
0335  * read/write media word.
0336  *   'cmd': can be SIOCGIFMEDIA, SIOCSIFMEDIA, 0 or 1. The latter
0337  *          are aliased to the former for convenience.
0338  *  'parg': pointer to media word.
0339  *
0340  * RETURNS: 0 on success, nonzero on error
0341  */
0342 int
0343 BSP_tsec_media_ioctl(struct tsec_private *mp, int cmd, int *parg);
0344 
0345 /* Interrupt related routines */
0346 
0347 /*
0348  * When it comes to interrupts the chip has two rather
0349  * annoying features:
0350  *   1 once an IRQ is pending, clearing the IMASK does not
0351  *     de-assert the interrupt line.
0352  *   2 the chip has three physical interrupt lines even though
0353  *     all events are reported in a single register. Rather
0354  *     useless; we must hook 3 ISRs w/o any real benefit.
0355  *     In fact, it makes our life a bit more difficult:
0356  *
0357  * Hence, for (1) we would have to mask interrupts at the PIC
0358  * but to re-enable them we would have to do that three times
0359  * because of (2).
0360  *
0361  * Therefore, we take the following approach:
0362  *
0363  *   ISR masks all interrupts on the TSEC, acks/clears them
0364  *   and stores the acked irqs in the device struct where
0365  *   it is picked up by BSP_tsec_ack_irqs().
0366  *   Since all interrupts are disabled until the daemon
0367  *   re-enables them after calling BSP_tsec_ack_irqs()
0368  *   no interrupts are lost.
0369  *
0370  * BUT:  NO isr (including PHY isrs) MUST INTERRUPT ANY
0371  *       OTHER ONE, i.e., they all must have the same
0372  *       priority. Otherwise, integrity of the cached
0373  *       irq_pending variable may be compromised.
0374  */
0375 
0376 /* Note: the BSP_tsec_enable/disable/ack_irqs() entry points
0377  *       are deprecated.
0378  *       The newer API where the user passes a mask allows
0379  *       for more selective control.
0380  */
0381 
0382 /* Enable interrupts at device */
0383 void
0384 BSP_tsec_enable_irqs(struct tsec_private *mp);
0385 
0386 /* Disable interrupts at device */
0387 void
0388 BSP_tsec_disable_irqs(struct tsec_private *mp);
0389 
0390 /*
0391  * Acknowledge (and clear) interrupts.
0392  * RETURNS: interrupts that were raised.
0393  */
0394 uint32_t
0395 BSP_tsec_ack_irqs(struct tsec_private *mp);
0396 
0397 /* Enable interrupts included in 'mask' (leaving
0398  * already enabled interrupts on). If the mask includes
0399  * bits that were not passed to the 'setup' routine then
0400  * the behavior is undefined.
0401  */
0402 void
0403 BSP_tsec_enable_irq_mask(struct tsec_private *mp, uint32_t irq_mask);
0404 
0405 /* Disable interrupts included in 'mask' (leaving
0406  * other ones that are currently enabled on). If the mask
0407  * includes bits that were not passed to the 'setup' routine
0408  * then the behavior is undefined.
0409 
0410  * RETURNS: Bitmask of interrupts that were enabled upon entry
0411  *          into this routine. This can be used to restore the previous
0412  *          state.
0413  */
0414 uint32_t
0415 BSP_tsec_disable_irq_mask(struct tsec_private *mp, uint32_t irq_mask);
0416 
0417 /* Acknowledge and clear selected interrupts.
0418  *
0419  * RETURNS: All pending interrupts.
0420  *
0421  * NOTE:    Only pending interrupts contained in 'mask'
0422  *          are cleared. Others are left pending.
0423  *
0424  *          This routine can be used to check for pending
0425  *          interrupts (pass mask ==  0) or to clear all
0426  *          interrupts (pass mask == -1).
0427  */
0428 uint32_t
0429 BSP_tsec_ack_irq_mask(struct tsec_private *mp, uint32_t mask);
0430 
0431 
0432 /* Retrieve the driver daemon TID that was passed to
0433  * BSP_tsec_setup().
0434  */
0435 
0436 rtems_id
0437 BSP_tsec_get_tid(struct tsec_private *mp);
0438 
0439 struct tsec_private *
0440 BSP_tsec_getp(unsigned index);
0441 
0442 /*
0443  *
0444  * Example driver task loop (note: no synchronization of
0445  * buffer access shown!).
0446  * RTEMS_EVENTx = 0,1 or 2 depending on IF unit.
0447  *
0448  *    / * setup (obtain handle) and initialize hw here * /
0449  *
0450  *    do {
0451  *      / * ISR disables IRQs and posts event * /
0452  *      rtems_event_receive( RTEMS_EVENTx, RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &evs );
0453  *      irqs = BSP_tsec_ack_irqs(handle);
0454  *      if ( irqs & BSP_TSEC_IRQ_TX ) {
0455  *          BSP_tsec_swipe_tx(handle); / * cleanup_txbuf() callback executed * /
0456  *      }
0457  *      if ( irqs & BSP_TSEC_IRQ_RX ) {
0458  *          BSP_tsec_swipe_rx(handle); / * alloc_rxbuf() and consume_rxbuf() executed * /
0459  *      }
0460  *      BSP_tsec_enable_irqs(handle);
0461  *    } while (1);
0462  *
0463  */
0464 
0465 /* PUBLIC RTEMS BSDNET ATTACH FUNCTION */
0466 struct rtems_bsdnet_ifconfig;
0467 
0468 int
0469 rtems_tsec_attach(struct rtems_bsdnet_ifconfig *ifcfg, int attaching);
0470 
0471 #ifdef __cplusplus
0472 }
0473 #endif
0474 
0475 #endif