Example #1
0
/*
 * unix_history_back
 *
 * Copy last available string to str, if possible.  Return 1 if successful.
 * Only lines of at most maxlen characters will be considered.  In addition
 * the first searchlen characters of the history entry must match those of str.
 */
static int unix_history_back(zchar *str, int searchlen, int maxlen)
{
    char **prev = history_view;

    do {
	RING_DEC( history_view, history_buffer, history_end);
	if ((history_view == history_next)
	    || (*history_view == NULL)) {
	    os_beep(BEEP_HIGH);
	    history_view = prev;
	    return 0;
	}
    } while (strlen( *history_view) > maxlen
	     || (searchlen != 0 && strncmp( (char *)str, *history_view, searchlen)));
    strcpy((char *)str + searchlen, *history_view + searchlen);
    return 1;
}
Example #2
0
/**
 * \brief Send a frame splitted into buffers. If the frame size is larger than transfer buffer size
 * error returned. If frame transfer status is monitored, specify callback for each frame.
 *  \param gmacd Pointer to GMAC Driver instance.
 *  \param sgl Pointer to a scatter-gather list describing the buffers of the ethernet frame.
 *  \param fTxCb Pointer to callback function.
 */
uint8_t gmacd_send_sg(struct _gmacd* gmacd, uint8_t queue,
		const struct _gmac_sg_list* sgl, gmacd_callback_t callback)
{
	Gmac* gmac = gmacd->gmac;
	struct _gmacd_queue* q = &gmacd->queues[queue];
	struct _gmac_desc* desc;
	uint16_t idx, tx_head;
	int i;

	if (callback && !q->tx_callbacks) {
		trace_error("Cannot set send callback, no tx_callbacks "\
				"buffer configured for queue %u", queue);
	}

	/* Check parameter */
	if (!sgl->size) {
		trace_error("gmacd_send_sg: ethernet frame is empty.\r\n");
		return GMACD_PARAM;
	}
	if (sgl->size >= q->tx_size) {
		trace_error("gmacd_send_sg: ethernet frame has too many buffers.\r\n");
		return GMACD_PARAM;
	}

	/* Check available space */
	if (RING_SPACE(q->tx_head, q->tx_tail, q->tx_size) < sgl->size) {
		trace_error("gmacd_send_sg: not enough free buffers in TX queue.\r\n");
		return GMACD_TX_BUSY;
	}

	/* Tag end of TX queue */
	tx_head = fixed_mod(q->tx_head + sgl->size, q->tx_size);
	idx = tx_head;
	if (q->tx_callbacks)
		q->tx_callbacks[idx] = NULL;
	desc = &q->tx_desc[idx];
	desc->status |= GMAC_TX_STATUS_USED;

	/* Update buffer descriptors in reverse order to avoid a race
	 * condition with hardware.
	 */
	for (i = sgl->size - 1; i >= 0; i--) {
		const struct _gmac_sg *sg = &sgl->entries[i];
		uint32_t status;

		if (sg->size > GMAC_TX_UNITSIZE) {
			trace_error("gmacd_send_sg: buffer size is too big.\r\n");
			return GMACD_PARAM;
		}

		RING_DEC(idx, q->tx_size);

		/* Reset TX callback */
		if (q->tx_callbacks)
			q->tx_callbacks[idx] = NULL;

		desc = &q->tx_desc[idx];

		/* Copy data into transmittion buffer */
		if (sg->buffer && sg->size) {
			memcpy((void*)desc->addr, sg->buffer, sg->size);
			l2cc_clean_region(desc->addr, desc->addr + sg->size);
		}

		/* Compute buffer descriptor status word */
		status = sg->size & GMAC_RX_STATUS_LENGTH_MASK;
		if (i == (sgl->size - 1)) {
			status |= GMAC_TX_STATUS_LASTBUF;
			if (q->tx_callbacks)
				q->tx_callbacks[idx] = callback;
		}
		if (idx == (q->tx_size - 1)) {
			status |= GMAC_TX_STATUS_WRAP;
		}

		/* Update buffer descriptor status word: clear USED bit */
		desc->status = status;
		DSB();
	}

	/* Update TX ring buffer pointers */
	q->tx_head = tx_head;

	/* Now start to transmit if it is not already done */
	gmac_start_transmission(gmac);

	return GMACD_OK;
}