/* * Should do the actual transmission of the packet. The packet is * contained in the pbuf that is passed to the function. This buf * might be chained. */ bool_t slip_output (slip_t *u, buf_t *p, small_uint_t prio) { debug_printf ("slip_output: transmit %d bytes\n", p->tot_len); mutex_lock (&u->transmitter); if (u->out) { /* Занято, ставим в очередь. */ if (buf_queue_is_full (&u->outq)) { ++u->netif.out_discards; mutex_unlock (&u->transmitter); debug_printf ("slip_output: overflow\n"); buf_free (p); return 0; } buf_queue_put (&u->outq, p); } else { u->out = p; u->outseg = p; u->out_first = u->outseg->payload; u->out_limit = u->outseg->payload + u->outseg->len; u->out_flag = 1; slip_transmit_start (u); } mutex_unlock (&u->transmitter); return 1; }
portBASE_TYPE transceiver::force_done(void) { if (static_cast<int8>(-1) == buf_queue_put(&m_buf_queue, m_rx_buf, m_rx_index)){ buf_queue_pop(&m_buf_queue); buf_queue_put(&m_buf_queue, m_rx_buf, m_rx_index); } if (m_duplex == HALF_DUPLEX){ m_rx_index = 0; rx_status_set(RX_STAT_DONE); }else { recv_init(); } //initiative call device handle cpu_pendsv_trig(); return 0; }
/* * Receive interrupt task. */ static void slip_receiver (void *arg) { slip_t *u = arg; unsigned short len; /* Start receiver. */ mutex_lock_irq (&u->netif.lock, RECEIVE_IRQ (u->port), (handler_t) slip_receive_data, u); enable_receiver (u->port); enable_receive_interrupt (u->port); for (;;) { if (! u->in_ptr) { /* Allocate buffer for receive data. */ u->in = buf_alloc (u->pool, u->netif.mtu, 16); if (u->in) { u->in_ptr = u->in->payload; u->in_limit = u->in_ptr + u->netif.mtu; } else { /* No buffer - ignore input. */ debug_printf ("slip_receiver: out of memory\n"); ++u->netif.in_discards; } } /* Wait for the receive interrupt. */ mutex_wait (&u->netif.lock); /* Process all available received data. */ if (u->in_ptr && u->in_ptr > u->in->payload) { len = u->in_ptr - u->in->payload; debug_printf ("slip_receiver(%ld): received %d bytes\n", u->netif.in_packets, len); buf_truncate (u->in, len); ++u->netif.in_packets; if (buf_queue_is_full (&u->inq)) { debug_printf ("slip_receiver: input overflow\n"); ++u->netif.in_discards; /* Reuse the packet. */ u->in_ptr = u->in->payload; u->in_limit = u->in_ptr + u->netif.mtu; } else { /* Enqueue the received packet. */ buf_queue_put (&u->inq, u->in); u->in_ptr = 0; } } #ifndef TRANSMIT_IRQ if (u->out_free) slip_out_next (u); #endif } }
/* * Send the packet. Blocks the task until the packet is enqueued. */ bool_t slip_send (slip_t *u, buf_t *p) { mutex_lock (&u->transmitter); while (u->out && buf_queue_is_full (&u->outq)) mutex_wait (&u->transmitter); if (u->out) { /* Занято, ставим в очередь. */ buf_queue_put (&u->outq, p); } else { u->out = p; u->outseg = p; u->out_first = u->outseg->payload; u->out_limit = u->outseg->payload + u->outseg->len; u->out_flag = 1; slip_transmit_start (u); } mutex_unlock (&u->transmitter); return 1; }
/* * Do the actual transmission of the packet. The packet is contained * in the pbuf that is passed to the function. This pbuf might be chained. * Return 1 when the packet is succesfully queued for transmission. * Or return 0 if the packet is lost. */ static bool_t eth_output(eth_t *u, buf_t *p, small_uint_t prio) { mutex_lock(&u->netif.lock); /* debug_printf("From tcp out\n"); */ /* Exit if link has failed */ if (p->tot_len < 4 || p->tot_len > ETH_MTU /*|| ! (phy_read (u, PHY_STS) & PHY_STS_LINK)*/) { ++u->netif.out_errors; mutex_unlock(&u->netif.lock); /*debug_printf ("output: transmit %d bytes, link failed\n", p->tot_len);*/ netif_free_buf (&u->netif, p); return 0; } /*debug_printf ("output: transmit %d bytes\n", p->tot_len);*/ if (ARM_ETH->STAT & ARM_ETH_X_EMPTY) { /* Смело отсылаем. */ transmit_packet(u, p); mutex_unlock(&u->netif.lock); netif_free_buf (&u->netif, p); return 1; } /* Занято, ставим в очередь. */ /*if (buf_queue_is_full(&u->outq)) { // Нет места в очереди: теряем пакет. ++u->netif.out_discards; ++u->out_full_buf; mutex_unlock(&u->netif.lock); buf_free(p); return 0; }*/ while (buf_queue_is_full(&u->outq)) asm volatile ("nop;"); buf_queue_put(&u->outq, p); mutex_unlock(&u->netif.lock); return 1; }
static void receive_packet(eth_t *u) { #ifdef ETH_FIFO unsigned *dst = (unsigned *) u->rxbuf_physaddr; // буфер для приёма uint32_t Rx_Stat, sizeBytes, sizeWords, i; Rx_Stat = ARM_ETH_RX_FIFO; /* Прочитать состояние приёмника */ sizeBytes = ARM_ETH_PKT_LENGTH(Rx_Stat); if (sizeBytes - 4 > ETH_MTU) { ++u->netif.in_errors; ++u->in_discards_len_packet; ARM_ETH->STAT = 0; return; } sizeWords = (sizeBytes + 3) / 4; for (i = 0; i < sizeWords; i++) { *dst++ = ARM_ETH_RX_FIFO; } ARM_ETH->STAT = 0; if (Rx_Stat & (ARM_ETH_PKT_SMB_ERR | ARM_ETH_PKT_CRC_ERR | ARM_ETH_PKT_DN_ERR | ARM_ETH_PKT_LF_ERR)) { ++u->netif.in_errors; return; } ++u->netif.in_packets; u->netif.in_bytes += sizeBytes; if (buf_queue_is_full(&u->inq)) { ++u->netif.in_discards; ++u->in_discards_full_buff; return; } buf_t *p = buf_alloc(u->pool, sizeBytes, 4); /* выделить фактически места */ if (!p) { ++u->netif.in_discards; ++u->in_discards_full_buff; return; } memcpy(p->payload, u->rxbuf, sizeBytes); buf_queue_put(&u->inq, p); #else uint16_t space_end = 0, tail, head; unsigned *src, *dst; uint32_t size, i, buf; uint16_t tmp[2], len; tail = ARM_ETH->R_TAIL; head = ARM_ETH->R_HEAD; if (tail > head) { space_end = tail - head; } else { space_end = ARM_ETH->DELIMITER - head; } src = (uint32_t*) (ARM_ETH_BUF_BASE + head); *((uint32_t*) tmp) = *src++; len = tmp[0]; //debug_printf("Recive packet \tRx_stat = 0x%08x; \tbytes = %d\n", // *((uint32_t*) tmp), tmp[0]); if ((len - 4) > ETH_MTU) { /*debug_printf("receive_data: len > MTU <%d>\n", len);*/ ++u->netif.in_discards; ++u->in_discards_len_packet; ARM_ETH->R_HEAD = ARM_ETH->R_TAIL; ARM_ETH->STAT -= 0x20; return; } if ((tmp[1] << 16) & (ARM_ETH_PKT_SMB_ERR | ARM_ETH_PKT_CRC_ERR | ARM_ETH_PKT_DN_ERR /*| ARM_ETH_PKT_LEN_ERR | ARM_ETH_PKT_SF_ERR */ | ARM_ETH_PKT_LF_ERR)) { debug_printf("Error <0x%08X>\tsize = %d\n", tmp[1] << 16, tmp[0]); ++u->netif.in_errors; ARM_ETH->R_HEAD = ARM_ETH->R_TAIL; ARM_ETH->STAT = 0; return; } u->netif.in_bytes += len; ++u->netif.in_packets; space_end -= 4; if ((uint16_t) src > (ARM_ETH->DELIMITER - 1)) src = (uint32_t*) ARM_ETH_BUF_BASE; if (buf_queue_is_full(&u->inq)) { /*debug_printf("receive_data: input overflow\n");*/ ++u->netif.in_discards; ++u->in_discards_full_buff; ARM_ETH->R_HEAD = ARM_ETH->R_TAIL; ARM_ETH->STAT -= 0x20; return; } buf_t *p = buf_alloc(u->pool, len, 4); /* выделить фактически места */ if (!p) { /* debug_printf("receive_data: ignore packet - out of memory\n"); */ ++u->netif.in_discards; ++u->in_discards_full_buff; ARM_ETH->R_HEAD = ARM_ETH->R_TAIL; ARM_ETH->STAT -= 0x20; return; } dst = (unsigned *) &p->payload[0]; //debug_printf("Rx frame, len = %d\tdst=0x%08X\n", len + 4, dst); size = (tmp[0] + 3) / 4; if (tmp[0] <= space_end) { for (i = 0; i < (size - 1); i++) *dst++ = *src++; buf = *src++; } else { size = size - space_end / 4; for (i = 0; i < (space_end / 4); i++) *dst++ = *src++; src = (uint32_t*) ARM_ETH_BUF_BASE; for (i = 0; i < (size - 1); i++) *dst++ = *src++; buf = *src++; } if ((uint16_t) src > (ARM_ETH->DELIMITER - 1)) src = (uint32_t*) ARM_ETH_BUF_BASE; ARM_ETH->R_HEAD = (uint16_t) src; /* printf(&debug, "R_HEAD = <%04X> \tR_TAIL = <%04X>\n", ARM_ETH->R_HEAD, ARM_ETH->R_TAIL); */ ARM_ETH->STAT = 0; buf_queue_put(&u->inq, p); #endif //ETH_FIFO }