/* This routine is called to send data to the hardware. It is known a-priori that there is free buffer space (dp->tx_next). */ static void dp83902a_send(unsigned char *data, int total_len, unsigned long key) { struct dp83902a_priv_data *dp = (struct dp83902a_priv_data *) &nic; cyg_uint8 *base = dp->base; int len, start_page, pkt_len, i, isr; #if DEBUG & 4 int dx; #endif DEBUG_FUNCTION(); len = pkt_len = total_len; if (pkt_len < IEEE_8023_MIN_FRAME) pkt_len = IEEE_8023_MIN_FRAME; start_page = dp->tx_next; if (dp->tx_next == dp->tx_buf1) { dp->tx1 = start_page; dp->tx1_len = pkt_len; dp->tx1_key = key; dp->tx_next = dp->tx_buf2; } else { dp->tx2 = start_page; dp->tx2_len = pkt_len; dp->tx2_key = key; dp->tx_next = dp->tx_buf1; } #if DEBUG & 5 printf("TX prep page %d len %d\n", start_page, pkt_len); #endif DP_OUT(base, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ { /* Dummy read. The manual sez something slightly different, */ /* but the code is extended a bit to do what Hitachi's monitor */ /* does (i.e., also read data). */ cyg_uint16 tmp; int len = 1; DP_OUT(base, DP_RSAL, 0x100-len); DP_OUT(base, DP_RSAH, (start_page-1) & 0xff); DP_OUT(base, DP_RBCL, len); DP_OUT(base, DP_RBCH, 0); DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START); DP_IN_DATA(dp->data, tmp); } #ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA /* Stall for a bit before continuing to work around random data */ /* corruption problems on some platforms. */ CYGACC_CALL_IF_DELAY_US(1); #endif /* Send data to device buffer(s) */ DP_OUT(base, DP_RSAL, 0); DP_OUT(base, DP_RSAH, start_page); DP_OUT(base, DP_RBCL, pkt_len & 0xFF); DP_OUT(base, DP_RBCH, pkt_len >> 8); DP_OUT(base, DP_CR, DP_CR_WDMA | DP_CR_START); /* Put data into buffer */ #if DEBUG & 4 printf(" sg buf %08lx len %08x\n ", (unsigned long) data, len); dx = 0; #endif while (len > 0) { #if DEBUG & 4 printf(" %02x", *data); if (0 == (++dx % 16)) printf("\n "); #endif DP_OUT_DATA(dp->data, *data++); len--; } #if DEBUG & 4 printf("\n"); #endif if (total_len < pkt_len) { #if DEBUG & 4 printf(" + %d bytes of padding\n", pkt_len - total_len); #endif /* Padding to 802.3 length was required */ for (i = total_len; i < pkt_len;) { i++; DP_OUT_DATA(dp->data, 0); } } #ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_TX_DMA /* After last data write, delay for a bit before accessing the */ /* device again, or we may get random data corruption in the last */ /* datum (on some platforms). */ CYGACC_CALL_IF_DELAY_US(1); #endif /* Wait for DMA to complete */ do { DP_IN(base, DP_ISR, isr); } while ((isr & DP_ISR_RDC) == 0); /* Then disable DMA */ DP_OUT(base, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); /* Start transmit if not already going */ if (!dp->tx_started) { if (start_page == dp->tx1) { dp->tx_int = 1; /* Expecting interrupt from BUF1 */ } else { dp->tx_int = 2; /* Expecting interrupt from BUF2 */ } dp83902a_start_xmit(start_page, pkt_len); } }
/* * This routine is called to send data to the hardware. It is known a-priori * that there is free buffer space (dp->tx_next). */ static void dp83902a_send(struct nic_priv_data *dp, u8 *data, int total_len, u32 key) { int len, start_page, pkt_len, i; volatile int isr; len = pkt_len = total_len; if (pkt_len < IEEE_8023_MIN_FRAME) pkt_len = IEEE_8023_MIN_FRAME; start_page = dp->tx_next; if (dp->tx_next == dp->tx_buf1) { dp->tx1 = start_page; dp->tx1_len = pkt_len; dp->tx1_key = key; dp->tx_next = dp->tx_buf2; } else { dp->tx2 = start_page; dp->tx2_len = pkt_len; dp->tx2_key = key; dp->tx_next = dp->tx_buf1; } n2k_outb(dp, DP_ISR, DP_ISR_RDC); /* Clear end of DMA */ { /* * Dummy read. The manual sez something slightly different, * but the code is extended a bit to do what Hitachi's monitor * does (i.e., also read data). */ u16 tmp; int len = 1; n2k_outb(dp, DP_RSAL, 0x100 - len); n2k_outb(dp, DP_RSAH, (start_page - 1) & 0xff); n2k_outb(dp, DP_RBCL, len); n2k_outb(dp, DP_RBCH, 0); n2k_outb(dp, DP_CR, DP_CR_PAGE0 | DP_CR_RDMA | DP_CR_START); DP_IN_DATA(dp->data, tmp); } /* Send data to device buffer(s) */ n2k_outb(dp, DP_RSAL, 0); n2k_outb(dp, DP_RSAH, start_page); n2k_outb(dp, DP_RBCL, pkt_len & 0xFF); n2k_outb(dp, DP_RBCH, pkt_len >> 8); n2k_outb(dp, DP_CR, DP_CR_WDMA | DP_CR_START); /* Put data into buffer */ while (len > 0) { DP_OUT_DATA(dp->data, *data++); len--; } if (total_len < pkt_len) { /* Padding to 802.3 length was required */ for (i = total_len; i < pkt_len;) { i++; DP_OUT_DATA(dp->data, 0); } } /* Wait for DMA to complete */ do { isr = n2k_inb(dp, DP_ISR); } while ((isr & DP_ISR_RDC) == 0); /* Then disable DMA */ n2k_outb(dp, DP_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START); /* Start transmit if not already going */ if (!dp->tx_started) { if (start_page == dp->tx1) { dp->tx_int = 1; /* Expecting interrupt from BUF1 */ } else { dp->tx_int = 2; /* Expecting interrupt from BUF2 */ } dp83902a_start_xmit(dp, start_page, pkt_len); } }