From 76d8262f134d41c05adda7edb27d9868ca847941 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 28 Dec 2012 17:40:45 +0000 Subject: [PATCH] Zero-copy API for the MAC driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4984 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/mac.h | 17 ++- os/hal/platforms/STM32/mac_lld.c | 176 ++++++++++++++++++++----------- os/hal/platforms/STM32/mac_lld.h | 23 +++- os/hal/src/mac.c | 4 + readme.txt | 1 + 5 files changed, 149 insertions(+), 72 deletions(-) diff --git a/os/hal/include/mac.h b/os/hal/include/mac.h index 2903bd07c..763bc373e 100644 --- a/os/hal/include/mac.h +++ b/os/hal/include/mac.h @@ -42,11 +42,18 @@ * @name MAC configuration options * @{ */ +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + /** * @brief Enables an event sources for incoming packets. */ #if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) -#define MAC_USE_EVENTS TRUE +#define MAC_USE_EVENTS TRUE #endif /** @} */ @@ -102,6 +109,7 @@ typedef struct MACDriver MACDriver; #define macGetReceiveEventSource(macp) (&(macp)->rdevent) #endif +#if !MAC_USE_ZERO_COPY || defined(__DOXYGEN__) /** * @brief Writes to a transmit descriptor's stream. * @@ -132,8 +140,9 @@ typedef struct MACDriver MACDriver; */ #define macReadReceiveDescriptor(rdp, buf, size) \ mac_lld_read_receive_descriptor(rdp, buf, size) +#endif /* !MAC_USE_ZERO_COPY */ -#if MAC_SUPPORTS_ZERO_COPY || defined(__DOXYGEN__) +#if MAC_USE_ZERO_COPY || defined(__DOXYGEN__) /** * @brief Returns a pointer to the next transmit buffer in the descriptor * chain. @@ -154,7 +163,7 @@ typedef struct MACDriver MACDriver; * @api */ #define macGetNextTransmitBuffer(tdp, size, sizep) \ - mac_lld_get_next_transmit_buffer(tdp, bufp) + mac_lld_get_next_transmit_buffer(tdp, size, sizep) /** * @brief Returns a pointer to the next receive buffer in the descriptor @@ -172,7 +181,7 @@ typedef struct MACDriver MACDriver; */ #define magGetNextReceiveBuffer(rdp, sizep) \ mac_lld_get_next_receive_buffer(rdp, sizep) -#endif /* MAC_SUPPORTS_ZERO_COPY */ +#endif /* MAC_USE_ZERO_COPY */ /** @} */ /*===========================================================================*/ diff --git a/os/hal/platforms/STM32/mac_lld.c b/os/hal/platforms/STM32/mac_lld.c index 3721670f9..25a5155ee 100644 --- a/os/hal/platforms/STM32/mac_lld.c +++ b/os/hal/platforms/STM32/mac_lld.c @@ -433,38 +433,6 @@ msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, return RDY_OK; } -/** - * @brief Writes to a transmit descriptor's stream. - * - * @param[in] tdp pointer to a @p MACTransmitDescriptor structure - * @param[in] buf pointer to the buffer containing the data to be - * written - * @param[in] size number of bytes to be written - * @return The number of bytes written into the descriptor's - * stream, this value can be less than the amount - * specified in the parameter @p size if the maximum - * frame size is reached. - * - * @notapi - */ -size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, - uint8_t *buf, - size_t size) { - - chDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), - "mac_lld_write_transmit_descriptor(), #1", - "attempt to write descriptor already owned by DMA"); - - if (size > tdp->size - tdp->offset) - size = tdp->size - tdp->offset; - - if (size > 0) { - memcpy((uint8_t *)(tdp->physdesc->tdes2) + tdp->offset, buf, size); - tdp->offset += size; - } - return size; -} - /** * @brief Releases a transmit descriptor and starts the transmission of the * enqueued data as a single frame. @@ -546,37 +514,6 @@ msg_t mac_lld_get_receive_descriptor(MACDriver *macp, return RDY_TIMEOUT; } -/** - * @brief Reads from a receive descriptor's stream. - * - * @param[in] rdp pointer to a @p MACReceiveDescriptor structure - * @param[in] buf pointer to the buffer that will receive the read data - * @param[in] size number of bytes to be read - * @return The number of bytes read from the descriptor's - * stream, this value can be less than the amount - * specified in the parameter @p size if there are - * no more bytes to read. - * - * @notapi - */ -size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, - uint8_t *buf, - size_t size) { - - chDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), - "mac_lld_read_receive_descriptor(), #1", - "attempt to read descriptor already owned by DMA"); - - if (size > rdp->size - rdp->offset) - size = rdp->size - rdp->offset; - - if (size > 0) { - memcpy(buf, (uint8_t *)(rdp->physdesc->rdes2) + rdp->offset, size); - rdp->offset += size; - } - return size; -} - /** * @brief Releases a receive descriptor. * @details The descriptor and its buffer are made available for more incoming @@ -675,6 +612,119 @@ bool_t mac_lld_poll_link_status(MACDriver *macp) { return macp->link_up = TRUE; } +#if MAC_USE_ZERO_COPY || defined(__DOXYGEN__) +/** + * @brief Returns a pointer to the next transmit buffer in the descriptor + * chain. + * @note The API guarantees that enough buffers can be requested to fill + * a whole frame. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] size size of the requested buffer. Specify the frame size + * on the first call then scale the value down subtracting + * the amount of data already copied into the previous + * buffers. + * @param[out] sizep pointer to variable receiving the real buffer size. + * The returned value can be less than the amount + * requested, this means that more buffers must be + * requested in order to fill the frame data entirely. + * @return Pointer to the returned buffer. + * + * @notapi + */ +uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp, + size_t size, + size_t *sizep) { + (void)tdp; (void)size; (void)sizep; + return NULL; +} + +/** + * @brief Returns a pointer to the next receive buffer in the descriptor + * chain. + * @note The API guarantees that the descriptor chain contains a whole + * frame. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[out] sizep pointer to variable receiving the buffer size, it is + * zero when the last buffer has already been returned. + * @return Pointer to the returned buffer. + * @retval NULL if the buffer chain has been entirely scanned. + * + * @notapi + */ +const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp, + size_t *sizep) { + (void)rdp; (void)sizep; + return NULL; +} +#endif /* MAC_USE_ZERO_COPY */ + +#if !MAC_USE_ZERO_COPY || defined(__DOXYGEN__) +/** + * @brief Writes to a transmit descriptor's stream. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] buf pointer to the buffer containing the data to be + * written + * @param[in] size number of bytes to be written + * @return The number of bytes written into the descriptor's + * stream, this value can be less than the amount + * specified in the parameter @p size if the maximum + * frame size is reached. + * + * @notapi + */ +size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, + uint8_t *buf, + size_t size) { + + chDbgAssert(!(tdp->physdesc->tdes0 & STM32_TDES0_OWN), + "mac_lld_write_transmit_descriptor(), #1", + "attempt to write descriptor already owned by DMA"); + + if (size > tdp->size - tdp->offset) + size = tdp->size - tdp->offset; + + if (size > 0) { + memcpy((uint8_t *)(tdp->physdesc->tdes2) + tdp->offset, buf, size); + tdp->offset += size; + } + return size; +} + +/** + * @brief Reads from a receive descriptor's stream. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[in] buf pointer to the buffer that will receive the read data + * @param[in] size number of bytes to be read + * @return The number of bytes read from the descriptor's + * stream, this value can be less than the amount + * specified in the parameter @p size if there are + * no more bytes to read. + * + * @notapi + */ +size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, + uint8_t *buf, + size_t size) { + + chDbgAssert(!(rdp->physdesc->rdes0 & STM32_RDES0_OWN), + "mac_lld_read_receive_descriptor(), #1", + "attempt to read descriptor already owned by DMA"); + + if (size > rdp->size - rdp->offset) + size = rdp->size - rdp->offset; + + if (size > 0) { + memcpy(buf, (uint8_t *)(rdp->physdesc->rdes2) + rdp->offset, size); + rdp->offset += size; + } + return size; +} +#endif /* !MAC_USE_ZERO_COPY */ + #endif /* HAL_USE_MAC */ /** @} */ diff --git a/os/hal/platforms/STM32/mac_lld.h b/os/hal/platforms/STM32/mac_lld.h index 76241cd52..59c39ac17 100644 --- a/os/hal/platforms/STM32/mac_lld.h +++ b/os/hal/platforms/STM32/mac_lld.h @@ -35,6 +35,11 @@ /* Driver constants. */ /*===========================================================================*/ +/** + * @brief This implementation supports the zero-copy mode API. + */ +#define MAC_SUPPORTS_ZERO_COPY TRUE + /** * @name RDES0 constants * @{ @@ -332,17 +337,25 @@ extern "C" { void mac_lld_stop(MACDriver *macp); msg_t mac_lld_get_transmit_descriptor(MACDriver *macp, MACTransmitDescriptor *tdp); - size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, - uint8_t *buf, - size_t size); void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp); msg_t mac_lld_get_receive_descriptor(MACDriver *macp, MACReceiveDescriptor *rdp); + void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp); + bool_t mac_lld_poll_link_status(MACDriver *macp); +#if MAC_USE_ZERO_COPY + uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp, + size_t size, + size_t *sizep); + const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp, + size_t *sizep); +#else /* !MAC_USE_ZERO_COPY */ + size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp, + uint8_t *buf, + size_t size); size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp, uint8_t *buf, size_t size); - void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp); - bool_t mac_lld_poll_link_status(MACDriver *macp); +#endif /* !MAC_USE_ZERO_COPY */ #ifdef __cplusplus } #endif diff --git a/os/hal/src/mac.c b/os/hal/src/mac.c index e052e0945..130c81caf 100644 --- a/os/hal/src/mac.c +++ b/os/hal/src/mac.c @@ -35,6 +35,10 @@ /* Driver local definitions. */ /*===========================================================================*/ +#if MAC_USE_ZERO_COPY && !MAC_SUPPORTS_ZERO_COPY +#error "MAC_USE_ZERO_COPY not supported by this implementation" +#endif + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ diff --git a/readme.txt b/readme.txt index e369346ff..259825234 100644 --- a/readme.txt +++ b/readme.txt @@ -90,6 +90,7 @@ (backported to 2.4.3). - FIX: Fixed wrong SPI path in platform_f105_f107.mk (bug 3598151). - FIX: Fixed PHY powerdown issues not fixed (bug 3596911). +- NEW: Added an optional zero-copy mode API to the MAC driver model. - NEW: Added EXT driver to the STM32F3xx platform. - NEW: Improved the STM32 EXT driver to support more than 32 channels. - NEW: Added support for Olimex board STM32-LCD.