/************************************************************************** w89c840_poll - Wait for a frame ***************************************************************************/ static int w89c840_poll(struct nic *nic, int retrieve) { /* return true if there's an ethernet packet ready to read */ /* nic->packet should contain data on return */ /* nic->packetlen should contain length of data */ int packet_received = 0; #if defined(W89C840_DEBUG) u32 intr_status = readl(ioaddr + IntrStatus); #endif do { /* Code from netdev_rx(dev) */ int entry = w840private.cur_rx % RX_RING_SIZE; struct w840_rx_desc *desc = w840private.rx_head_desc; s32 status = desc->status; if (status & DescOwn) { /* DescOwn bit is still set, we should wait for RX to complete */ packet_received = 0; break; } if ( !retrieve ) { packet_received = 1; break; } if ((status & 0x38008300) != 0x0300) { if ((status & 0x38000300) != 0x0300) { /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { printf("winbond-840 : Oversized Ethernet frame spanned " "multiple buffers, entry %d status %X !\n", w840private.cur_rx, (unsigned int) status); } } else if (status & 0x8000) { /* There was a fatal error. */ #if defined(W89C840_DEBUG) printf("winbond-840 : Receive error, Rx status %X :", status); if (status & 0x0890) { printf(" RXLEN_ERROR"); } if (status & 0x004C) { printf(", FRAME_ERROR"); } if (status & 0x0002) { printf(", CRC_ERROR"); } printf("\n"); #endif /* Simpy do a reset now... */ w89c840_reset(nic); packet_received = 0; break; } } else { /* Omit the four octet CRC from the length. */ int pkt_len = ((status >> 16) & 0x7ff) - 4; #if defined(W89C840_DEBUG) printf(" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry, pkt_len, status); #endif nic->packetlen = pkt_len; /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ memcpy(nic->packet, le32desc_to_virt(w840private.rx_ring[entry].buffer1), pkt_len); packet_received = 1; /* Release buffer to NIC */ w840private.rx_ring[entry].status = DescOwn; #if defined(W89C840_DEBUG) /* You will want this info for the initial debug. */ printf(" Rx data %hhX:%hhX:%hhX:%hhX:%hhX:" "%hhX %hhX:%hhX:%hhX:%hhX:%hhX:%hhX %hhX%hhX " "%hhX.%hhX.%hhX.%hhX.\n", nic->packet[0], nic->packet[1], nic->packet[2], nic->packet[3], nic->packet[4], nic->packet[5], nic->packet[6], nic->packet[7], nic->packet[8], nic->packet[9], nic->packet[10], nic->packet[11], nic->packet[12], nic->packet[13], nic->packet[14], nic->packet[15], nic->packet[16], nic->packet[17]); #endif } entry = (++w840private.cur_rx) % RX_RING_SIZE; w840private.rx_head_desc = &w840private.rx_ring[entry]; } while (0); return packet_received; }
static int w89c840_poll(struct nic *nic) { int packet_received = 0; u32 intr_status = readl(ioaddr + IntrStatus); do { int entry = w840private.cur_rx % RX_RING_SIZE; struct w840_rx_desc *desc = w840private.rx_head_desc; s32 status = desc->status; if (status & DescOwn) { packet_received = 0; break; } if ((status & 0x38008300) != 0x0300) { if ((status & 0x38000300) != 0x0300) { if ((status & 0xffff) != 0x7fff) { printf("winbond-840 : Oversized Ethernet frame spanned " "multiple buffers, entry %d status %X !\n", w840private.cur_rx, status); } } else if (status & 0x8000) { #if defined(W89C840_DEBUG) printf("winbond-840 : Receive error, Rx status %X :", status); if (status & 0x0890) { printf(" RXLEN_ERROR"); } if (status & 0x004C) { printf(", FRAME_ERROR"); } if (status & 0x0002) { printf(", CRC_ERROR"); } printf("\n"); #endif w89c840_reset(nic); packet_received = 0; break; } } else { int pkt_len = ((status >> 16) & 0x7ff) - 4; #if defined(W89C840_DEBUG) printf(" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry, pkt_len, status); #endif nic->packetlen = pkt_len; memcpy(nic->packet, le32desc_to_virt(w840private.rx_ring[entry].buffer1), pkt_len); packet_received = 1; w840private.rx_ring[entry].status = DescOwn; #if defined(W89C840_DEBUG) printf(" Rx data %hhX:%hhX:%hhX:%hhX:%hhX:" "%hhX %hhX:%hhX:%hhX:%hhX:%hhX:%hhX %hhX%hhX " "%hhX.%hhX.%hhX.%hhX.\n", nic->packet[0], nic->packet[1], nic->packet[2], nic->packet[3], nic->packet[4], nic->packet[5], nic->packet[6], nic->packet[7], nic->packet[8], nic->packet[9], nic->packet[10], nic->packet[11], nic->packet[12], nic->packet[13], nic->packet[14], nic->packet[15], nic->packet[16], nic->packet[17]); #endif } entry = (++w840private.cur_rx) % RX_RING_SIZE; w840private.rx_head_desc = &w840private.rx_ring[entry]; } while (0); if (intr_status & (AbnormalIntr | TxFIFOUnderflow | IntrPCIErr |TimerInt | IntrTxStopped)) { handle_intr(intr_status); } return packet_received; }