Esempio n. 1
0
static void init_ring(void)
{
    int i;
    char * p;

    w840private.tx_full = 0;
    w840private.tx_q_bytes = w840private.cur_rx = w840private.cur_tx = 0;
    w840private.dirty_rx = w840private.dirty_tx = 0;

    w840private.rx_buf_sz = PKT_BUF_SZ;
    w840private.rx_head_desc = &w840private.rx_ring[0];

    

    p = &rx_packet[0];

    for (i = 0; i < RX_RING_SIZE; i++) {
        w840private.rx_ring[i].length = w840private.rx_buf_sz;
        w840private.rx_ring[i].status = 0;
        w840private.rx_ring[i].next_desc = virt_to_le32desc(&w840private.rx_ring[i+1]);

        w840private.rx_ring[i].buffer1 = virt_to_le32desc(p + (PKT_BUF_SZ * i));
        w840private.rx_ring[i].status = DescOwn | DescIntr;
    }

    
    w840private.rx_ring[i-1].length |= DescEndRing;
    w840private.rx_ring[i-1].next_desc = virt_to_le32desc(&w840private.rx_ring[0]);

    w840private.dirty_rx = (unsigned int)(i - RX_RING_SIZE);

    for (i = 0; i < TX_RING_SIZE; i++) {
        w840private.tx_ring[i].status = 0;
    }
    return;
}
Esempio n. 2
0
static void w89c840_transmit(
    struct nic *nic,
    const char *d,            /* Destination */
    unsigned int t,            /* Type */
    unsigned int s,            /* size */
    const char *p)            /* Packet */
{
    /* send the packet to destination */
    unsigned entry;
    int transmit_status;
    unsigned long ct;

    /* Caution: the write order is important here, set the field
       with the "ownership" bits last. */

    /* Fill in our transmit buffer */
    entry = w840private.cur_tx % TX_RING_SIZE;

    memcpy (w89c840_buf.tx_packet, d, ETH_ALEN);    /* dst */
    memcpy (w89c840_buf.tx_packet + ETH_ALEN, nic->node_addr, ETH_ALEN);/*src*/

    *((char *) w89c840_buf.tx_packet + 12) = t >> 8;    /* type */
    *((char *) w89c840_buf.tx_packet + 13) = t;

    memcpy (w89c840_buf.tx_packet + ETH_HLEN, p, s);
    s += ETH_HLEN;

    while (s < ETH_ZLEN)
    *((char *) w89c840_buf.tx_packet + ETH_HLEN + (s++)) = 0;

    w840private.tx_ring[entry].buffer1
	    = virt_to_le32desc(w89c840_buf.tx_packet);

    w840private.tx_ring[entry].length = (DescWholePkt | (u32) s);
    if (entry >= TX_RING_SIZE-1)         /* Wrap ring */
        w840private.tx_ring[entry].length |= (DescIntr | DescEndRing);
    w840private.tx_ring[entry].status = (DescOwn);
    w840private.cur_tx++;

    w840private.tx_q_bytes = (u16) s;
    writel(0, ioaddr + TxStartDemand);

    /* Work around horrible bug in the chip by marking the queue as full
       when we do not have FIFO room for a maximum sized packet. */

    if ((w840private.drv_flags & HasBrokenTx) && w840private.tx_q_bytes > TX_BUG_FIFO_LIMIT) {
        /* Actually this is left to help finding error tails later in debugging...
         * See Linux kernel driver in winbond-840.c for details.
         */
        w840private.tx_full = 1;
    }

#if defined(W89C840_DEBUG)
    printf("winbond-840 : Transmit frame # %d size %d queued in slot %d.\n", w840private.cur_tx, s, entry);
#endif

    /* Now wait for TX to complete. */
    transmit_status = w840private.tx_ring[entry].status;

    ct = currticks();
    {
#if defined W89C840_DEBUG
        u32 intr_stat = 0;
#endif
        while (1) {

#if defined(W89C840_DEBUG)
	      decode_interrupt(intr_stat);
#endif

                while ( (transmit_status & DescOwn) && ct + TX_TIMEOUT < currticks()) {

                    transmit_status = w840private.tx_ring[entry].status;
                }

                break;
        }
    }

    if ((transmit_status & DescOwn) == 0) {

#if defined(W89C840_DEBUG)
        printf("winbond-840 : transmission complete after wait loop iterations, status %X\n",
                w840private.tx_ring[entry].status);
#endif

        return;
    }

    /* Transmit timed out... */

    printf("winbond-840 : transmission TIMEOUT : status %X\n", 
	   (unsigned int) w840private.tx_ring[entry].status);

    return;
}
Esempio n. 3
0
static void w89c840_transmit(
    struct nic *nic,
    const char *d,            
    unsigned int t,            
    unsigned int s,            
    const char *p)            
{
    
    unsigned entry;
    int transmit_status;


    
    entry = w840private.cur_tx % TX_RING_SIZE;

    memcpy (tx_packet, d, ETH_ALEN);    
    memcpy (tx_packet + ETH_ALEN, nic->node_addr, ETH_ALEN);

    *((char *) tx_packet + 12) = t >> 8;    
    *((char *) tx_packet + 13) = t;

    memcpy (tx_packet + ETH_HLEN, p, s);
    s += ETH_HLEN;

    while (s < ETH_ZLEN)
    *((char *) tx_packet + ETH_HLEN + (s++)) = 0;

    w840private.tx_ring[entry].buffer1 = virt_to_le32desc(tx_packet);

    w840private.tx_ring[entry].length = (DescWholePkt | s);
    if (entry >= TX_RING_SIZE-1)         
        w840private.tx_ring[entry].length |= (DescIntr | DescEndRing);
    w840private.tx_ring[entry].status = (DescOwn);
    w840private.cur_tx++;

    w840private.tx_q_bytes += s;
    writel(0, ioaddr + TxStartDemand);


    if ((w840private.drv_flags & HasBrokenTx) && w840private.tx_q_bytes > TX_BUG_FIFO_LIMIT) {
        w840private.tx_full = 1;
    }

#if defined(W89C840_DEBUG)
    printf("winbond-840 : Transmit frame # %d size %d queued in slot %d.\n", w840private.cur_tx, s, entry);
#endif

    
    transmit_status = w840private.tx_ring[entry].status;

    load_timer2(TX_TIMEOUT);

    {
        u32 intr_stat = 0;

        while (1) {

            intr_stat = readl(ioaddr + IntrStatus);
#if defined(W89C840_DEBUG)
            decode_interrupt(intr_stat);
#endif

            if (intr_stat & (NormalIntr | IntrTxDone)) {

                while ( (transmit_status & DescOwn) && timer2_running()) {

                    transmit_status = w840private.tx_ring[entry].status;
                }

                writel(intr_stat & 0x0001ffff, ioaddr + IntrStatus);
                break;
            }
        }
    }

    if ((transmit_status & DescOwn) == 0) {

#if defined(W89C840_DEBUG)
        printf("winbond-840 : transmission complete after %d wait loop iterations, status %X\n",
               TX_LOOP_COUNT - transmit_loop_counter, w840private.tx_ring[entry].status);
#endif

        return;
    }

    

    printf("winbond-840 : transmission TIMEOUT : status %X\n", w840private.tx_ring[entry].status);

    return;
}