static void wd_trs( struct device *dev ) { unsigned char errors; if( wd_debug ) printk("\nwd_trs() - TX complete, status = x%x", inb_p(TSR)); if( ( errors = inb_p( TSR ) & PTXOK ) || tx_aborted ){ if( (errors&~0x02) == 0 ){ stats.tx_packets++; tx_aborted = 0; } dev->tbusy = 0; mark_bh (INET_BH); #if 0 /* attempt to start a new transmission. */ len = dev_tint( (unsigned char *)dev->mem_start, dev ); if( len != 0 ){ len=max(len, ETHER_MIN_LEN); cmd=inb_p(WD_COMM); outb_p(len&0xff,WD_TB0); outb_p(len>>8,WD_TB1); cmd |= CTRANS; outb_p(cmd,WD_COMM); interrupt_mask |= TRANS_MASK; } else {
static int net_send_packet(struct sk_buff *skb, struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; if (dev->tbusy) { /* If we get here, some higher level has decided we are broken. There should really be a "kick me" function call instead. */ int tickssofar = jiffies - dev->trans_start; if (tickssofar < 5) return 1; printk("%s: transmit timed out, %s?\n", dev->name, tx_done(dev) ? "IRQ conflict" : "network cable problem"); /* Try to restart the adaptor. */ chipset_init(dev, 1); dev->tbusy=0; dev->trans_start = jiffies; } /* If some higher layer thinks we've missed an tx-done interrupt we are passed NULL. Caution: dev_tint() handles the cli()/sti() itself. */ if (skb == NULL) { dev_tint(dev); return 0; } /* For ethernet, fill in the header. This should really be done by a higher level, rather than duplicated for each ethernet adaptor. */ if (!skb->arp && dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; } skb->arp=1; /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = skb->data; hardware_send_packet(ioaddr, buf, length); dev->trans_start = jiffies; } if (skb->free) kfree_skb (skb, FREE_WRITE); /* You might need to clean up and record Tx statistics here. */ if (inw(ioaddr) == /*RU*/81) lp->stats.tx_aborted_errors++; return 0; }
/* * traversal the net_device and send some data */ void dev_transmit(void) { struct net_device *dev; for(dev = dev_base;dev != NULL; dev = dev->next) { if(dev->flags != 0 && dev->tbusy) dev_tint(dev); } }
void dev_transmit(void) { struct device *dev; for (dev = dev_base; dev != NULL; dev = dev->next) { if (dev->flags != 0 && !dev->tbusy) { /* * Kick the device */ dev_tint(dev); } } }
/* * Copy a buffer to the adapter transmit page memory. * Start sending. */ static int de600_start_xmit(struct sk_buff *skb, struct device *dev) { int transmit_from; int len; int tickssofar; byte *buffer = skb->data; /* * If some higher layer thinks we've missed a * tx-done interrupt we are passed NULL. * Caution: dev_tint() handles the cli()/sti() itself. */ if (skb == NULL) { dev_tint(dev); return 0; } if (free_tx_pages <= 0) { /* Do timeouts, to avoid hangs. */ tickssofar = jiffies - dev->trans_start; if (tickssofar < 5) return 1; /* else */ printk("%s: transmit timed out (%d), %s?\n", dev->name, tickssofar, "network cable problem" ); /* Restart the adapter. */ if (adapter_init(dev)) { return 1; } } /* Start real output */ PRINTK(("de600_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages)); if ((len = skb->len) < RUNT) len = RUNT; cli(); select_nic(); tx_fifo[tx_fifo_in] = transmit_from = tx_page_adr(tx_fifo_in) - len; tx_fifo_in = (tx_fifo_in + 1) % TX_PAGES; /* Next free tx page */ #ifdef CHECK_LOST_DE600 /* This costs about 40 instructions per packet... */ de600_setup_address(NODE_ADDRESS, RW_ADDR); de600_read_byte(READ_DATA, dev); if (was_down || (de600_read_byte(READ_DATA, dev) != 0xde)) { if (adapter_init(dev)) { sti(); return 1; } } #endif de600_setup_address(transmit_from, RW_ADDR); for ( ; len > 0; --len, ++buffer) de600_put_byte(*buffer); if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */ dev->trans_start = jiffies; dev->tbusy = 0; /* allow more packets into adapter */ /* Send page and generate a faked interrupt */ de600_setup_address(transmit_from, TX_ADDR); de600_put_command(TX_ENABLE); } else { dev->tbusy = !free_tx_pages; select_prn(); } sti(); /* interrupts back on */ #ifdef FAKE_SMALL_MAX /* This will "patch" the socket TCP proto at an early moment */ if (skb->sk && (skb->sk->protocol == IPPROTO_TCP) && (skb->sk->prot->rspace != &de600_rspace)) skb->sk->prot->rspace = de600_rspace; /* Ugh! */ #endif dev_kfree_skb (skb, FREE_WRITE); return 0; }
static int el_start_xmit(struct sk_buff *skb, struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; unsigned long flags; if(dev->interrupt) /* May be unloading, don't stamp on */ return 1; /* the packet buffer this time */ if (dev->tbusy) { if (jiffies - dev->trans_start < 20) { if (el_debug > 2) printk(" transmitter busy, deferred.\n"); return 1; } if (el_debug) printk ("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n", dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS)); lp->stats.tx_errors++; outb(TX_NORM, TX_CMD); outb(RX_NORM, RX_CMD); outb(AX_OFF, AX_CMD); /* Just trigger a false interrupt. */ outb(AX_RX, AX_CMD); /* Aux control, irq and receive enabled */ dev->tbusy = 0; dev->trans_start = jiffies; } if (skb == NULL) { dev_tint(dev); return 0; } save_flags(flags); /* * Avoid incoming interrupts between us flipping tbusy and flipping * mode as the driver assumes tbusy is a faithful indicator of card * state */ cli(); /* * Avoid timer-based retransmission conflicts. */ if (set_bit(0, (void*)&dev->tbusy) != 0) { restore_flags(flags); printk("%s: Transmitter access conflict.\n", dev->name); } else { int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN); unsigned char *buf = skb->data; load_it_again_sam: lp->tx_pkt_start = gp_start; lp->collisions = 0; /* * Command mode with status cleared should [in theory] * mean no more interrupts can be pending on the card. */ #ifdef BLOCKOUT_1 disable_irq(dev->irq); #endif outb_p(AX_SYS, AX_CMD); inb_p(RX_STATUS); inb_p(TX_STATUS); lp->loading=1; /* * Turn interrupts back on while we spend a pleasant afternoon * loading bytes into the board */ restore_flags(flags); outw(0x00, RX_BUF_CLR); /* Set rx packet area to 0. */ outw(gp_start, GP_LOW); /* aim - packet will be loaded into buffer start */ outsb(DATAPORT,buf,skb->len); /* load buffer (usual thing each byte increments the pointer) */ outw(gp_start, GP_LOW); /* the board reuses the same register */ #ifndef BLOCKOUT_1 if(lp->loading==2) /* A receive upset our load, despite our best efforts */ { if(el_debug>2) printk("%s: burped during tx load.\n", dev->name); goto load_it_again_sam; /* Sigh... */ } #endif outb(AX_XMIT, AX_CMD); /* fire ... Trigger xmit. */ lp->loading=0; #ifdef BLOCKOUT_1 enable_irq(dev->irq); #endif dev->trans_start = jiffies; } if (el_debug > 2) printk(" queued xmit.\n"); dev_kfree_skb (skb, FREE_WRITE); return 0; }
static int el_start_xmit(struct sk_buff *skb, struct device *dev) { if (dev->tbusy) { if (jiffies - dev->trans_start < 20) { if (el_debug > 2) printk(" transmitter busy, deferred.\n"); return 1; } if (el_debug) printk ("%s: transmit timed out, txsr %#2x axsr=%02x rxsr=%02x.\n", dev->name, inb(TX_STATUS), inb(AX_STATUS), inb(RX_STATUS)); el_status.stats.tx_errors++; #ifdef oldway el_reset(dev); #else outb(TX_NORM, TX_CMD); outb(RX_NORM, RX_CMD); outb(AX_OFF, AX_CMD); /* Just trigger a false interrupt. */ #endif outb(AX_RX, AX_CMD); /* Aux control, irq and receive enabled */ dev->tbusy = 0; dev->trans_start = jiffies; } if (skb == NULL) { dev_tint(dev); return 0; } /* Fill in the ethernet header. */ if (!skb->arp && dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; } skb->arp=1; if (skb->len <= 0) return 0; /* Avoid timer-based retransmission conflicts. */ if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN); unsigned char *buf = skb->data; el_status.tx_pkt_start = gp_start; el_status.collisions = 0; outb(AX_SYS, AX_CMD); inb(RX_STATUS); inb(TX_STATUS); outb(0x00, RX_BUF_CLR); /* Set rx packet area to 0. */ outw(gp_start, GP_LOW); outsb(DATAPORT,buf,skb->len); outw(gp_start, GP_LOW); outb(AX_XMIT, AX_CMD); /* Trigger xmit. */ dev->trans_start = jiffies; } if (el_debug > 2) printk(" queued xmit.\n"); if (skb->free) kfree_skb (skb, FREE_WRITE); return 0; }
static int ni52_send_packet(struct sk_buff *skb, struct device *dev) { int len,i; #ifndef NO_NOPCOMMANDS int next_nop; #endif struct priv *p = (struct priv *) dev->priv; if(dev->tbusy) { int tickssofar = jiffies - dev->trans_start; if (tickssofar < 5) return 1; if(p->scb->status & CU_ACTIVE) /* COMMAND-UNIT active? */ { dev->tbusy = 0; #ifdef DEBUG printk("%s: strange ... timeout with CU active?!?\n",dev->name); printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point); #endif p->scb->cmd = CUC_ABORT; ni_attn586(); WAIT_4_SCB_CMD(); p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]); p->scb->cmd = CUC_START; ni_attn586(); WAIT_4_SCB_CMD(); dev->trans_start = jiffies; return 0; } else { #ifdef DEBUG printk("%s: xmitter timed out, try to restart! stat: %04x\n",dev->name,p->scb->status); printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status); #endif ni52_close(dev); ni52_open(dev); } dev->trans_start = jiffies; return 0; } if(skb == NULL) { dev_tint(dev); return 0; } if (skb->len <= 0) return 0; if(skb->len > XMIT_BUFF_SIZE) { printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %ld bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len); return 0; } if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len); len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; #if (NUM_XMIT_BUFFS == 1) # ifdef NO_NOPCOMMANDS p->xmit_buffs[0]->size = TBD_LAST | len; for(i=0;i<16;i++) { p->scb->cbl_offset = make16(p->xmit_cmds[0]); p->scb->cmd = CUC_START; p->xmit_cmds[0]->cmd_status = 0; ni_attn586(); dev->trans_start = jiffies; if(!i) dev_kfree_skb(skb,FREE_WRITE); WAIT_4_SCB_CMD(); if( (p->scb->status & CU_ACTIVE)) /* test it, because CU sometimes doesn't start immediately */ break; if(p->xmit_cmds[0]->cmd_status) break; if(i==15) printk("%s: Can't start transmit-command.\n",dev->name); } # else next_nop = (p->nop_point + 1) & 0x1; p->xmit_buffs[0]->size = TBD_LAST | len; p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link = make16((p->nop_cmds[next_nop])); p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0; p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); dev->trans_start = jiffies; p->nop_point = next_nop; dev_kfree_skb(skb,FREE_WRITE); # endif #else p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len; if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS ) next_nop = 0; p->xmit_cmds[p->xmit_count]->cmd_status = 0; p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link = make16((p->nop_cmds[next_nop])); p->nop_cmds[next_nop]->cmd_status = 0; p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count])); dev->trans_start = jiffies; p->xmit_count = next_nop; cli(); if(p->xmit_count != p->xmit_last) dev->tbusy = 0; sti(); dev_kfree_skb(skb,FREE_WRITE); #endif } return 0; }
static int elp_start_xmit(struct sk_buff *skb, struct device *dev) { elp_device * adapter = (elp_device *) dev->priv; CHECK_NULL(dev); /* * not sure what this does, but the 3c509 driver does it, so... */ if (skb == NULL) { dev_tint(dev); return 0; } /* * Fill in the ethernet header * (for kernels prior to 1.1.4 only) */ #if (ELP_KERNEL_TYPE < 2) IS_SKB(skb); if (!skb->arp && dev->rebuild_header(SKB_DATA, dev)) { skb->dev = dev; IS_SKB(skb); arp_queue (skb); return 0; } #endif /* * if we ended up with a munged length, don't send it */ if (skb->len <= 0) return 0; if (elp_debug >= 3) printk("%s: request to send packet of length %d\n", dev->name, (int)skb->len); /* * if the transmitter is still busy, we have a transmit timeout... */ if (dev->tbusy) { int tickssofar = jiffies - dev->trans_start; if (tickssofar < 200) /* was 500, AJT */ return 1; printk("%s: transmit timed out, resetting adapter\n", dev->name); if ((INB(adapter->io_addr+PORT_STATUS)&STATUS_ACRF) != 0) printk("%s: hmmm...seemed to have missed an interrupt!\n", dev->name); adapter_reset(adapter); dev->trans_start = jiffies; dev->tbusy = 0; } /* * send the packet at skb->data for skb->len */ if (!send_packet(adapter, (unsigned char *)SKB_DATA, skb->len)) { printk("%s: send packet PCB failed\n", dev->name); return 1; } if (elp_debug >= 3) printk("%s: packet of length %d sent\n", dev->name, (int)skb->len); /* * start the transmit timeout */ dev->trans_start = jiffies; /* * the transmitter is now busy */ dev->tbusy = 1; /* * if we have been asked to free the buffer, do so */ #if (ELP_KERNEL_TYPE < 4) if (skb->free) { IS_SKB(skb); kfree_skb(skb, FREE_WRITE); } #else dev_kfree_skb(skb, FREE_WRITE); #endif return 0; }
/* * Copy a buffer to the adapter transmit page memory. * Start sending. */ static int d_link_start_xmit(struct sk_buff *skb, struct device *dev) { int transmit_from; int len; int tickssofar; unsigned char *buffer = skb->data; /* * If some higher layer thinks we've missed a * tx-done interrupt we are passed NULL. * Caution: dev_tint() handles the cli()/sti() itself. */ if (skb == NULL) { dev_tint(dev); return 0; } /* For ethernet, fill in the header (hardware addresses) with an arp. */ if (!skb->arp) if(dev->rebuild_header(skb->data, dev)) { skb->dev = dev; arp_queue (skb); return 0; } skb->arp = 1; if (free_tx_pages <= 0) { /* Do timeouts, to avoid hangs. */ tickssofar = jiffies - dev->trans_start; if (tickssofar < 5) return 1; /* else */ printk("%s: transmit timed out (%d), %s?\n", dev->name, tickssofar, "network cable problem" ); /* Restart the adapter. */ adapter_init(dev); } /* Start real output */ PRINTK(("d_link_start_xmit:len=%d, page %d/%d\n", skb->len, tx_fifo_in, free_tx_pages)); if ((len = skb->len) < RUNT) len = RUNT; cli(); select_nic(); tx_fifo[tx_fifo_in] = transmit_from = tx_page_adr(tx_fifo_in) - len; tx_fifo_in = (tx_fifo_in + 1) % TX_PAGES; /* Next free tx page */ d_link_setup_address(transmit_from, RW_ADDR); for ( ; len > 0; --len, ++buffer) d_link_put_byte(*buffer); if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */ dev->trans_start = jiffies; dev->tbusy = 0; /* allow more packets into adapter */ /* Send page and generate an interrupt */ d_link_setup_address(transmit_from, TX_ADDR); d_link_put_command(TX_ENABLE); } else { dev->tbusy = !free_tx_pages; select_prn(); } sti(); /* interrupts back on */ if (skb->free) kfree_skb (skb, FREE_WRITE); return 0; }
static int net_send_packet(struct sk_buff *skb, struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; if (dev->tbusy) { /* If we get here, some higher level has decided we are broken. There should really be a "kick me" function call instead. */ int tickssofar = jiffies - dev->trans_start; if (tickssofar < 10) return 1; printk("%s: transmit timed out with status %04x, %s?\n", dev->name, htons(inw(ioaddr + TX_STATUS)), inb(ioaddr + TX_STATUS) & 0x80 ? "IRQ conflict" : "network cable problem"); printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n", dev->name, htons(inw(ioaddr + 0)), htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)), htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)), htons(inw(ioaddr +10)), htons(inw(ioaddr +12)), htons(inw(ioaddr +14))); printk("eth card: %04x %04x\n", htons(inw(ioaddr+FJ_STATUS0)), htons(inw(ioaddr+FJ_CONFIG0))); lp->stats.tx_errors++; /* ToDo: We should try to restart the adaptor... */ cli(); /* Initialize LAN Controller and LAN Card */ outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */ outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */ outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */ outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */ net_open(dev); sti(); } /* If some higher layer thinks we've missed an tx-done interrupt we are passed NULL. Caution: dev_tint() handles the cli()/sti() itself. */ if (skb == NULL) { dev_tint(dev); return 0; } /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = skb->data; if (length > ETH_FRAME_LEN) { if (net_debug) printk("%s: Attempting to send a large packet (%d bytes).\n", dev->name, length); return 1; } if (net_debug > 4) printk("%s: Transmitting a packet of length %lu.\n", dev->name, (unsigned long)skb->len); /* Disable both interrupts. */ outw(0x0000, ioaddr + TX_INTR); outw(length, ioaddr + DATAPORT); outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); lp->tx_queue++; lp->tx_queue_len += length + 2; if (lp->tx_started == 0) { /* If the Tx is idle, always trigger a transmit. */ outb(0x80 | lp->tx_queue, ioaddr + TX_START); lp->tx_queue = 0; lp->tx_queue_len = 0; dev->trans_start = jiffies; lp->tx_started = 1; dev->tbusy = 0; } else if (lp->tx_queue_len < 4096 - 1502) /* Yes, there is room for one more packet. */ dev->tbusy = 0; /* Re-enable interrupts */ outw(0x8182, ioaddr + TX_INTR); } dev_kfree_skb (skb, FREE_WRITE); return 0; }
static int eexp_send_packet(struct sk_buff *skb, struct device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; if (dev->tbusy) { /* If we get here, some higher level has decided we are broken. There should really be a "kick me" function call instead. */ int tickssofar = jiffies - dev->trans_start; if (tickssofar < 5) return 1; if (net_debug > 1) printk("%s: transmit timed out, %s? ", dev->name, inw(ioaddr+SCB_STATUS) & 0x8000 ? "IRQ conflict" : "network cable problem"); lp->stats.tx_errors++; /* Try to restart the adaptor. */ if (lp->last_restart == lp->stats.tx_packets) { if (net_debug > 1) printk("Resetting board.\n"); /* Completely reset the adaptor. */ init_82586_mem(dev); } else { /* Issue the channel attention signal and hope it "gets better". */ if (net_debug > 1) printk("Kicking board.\n"); outw(0xf000|CUC_START|RX_START, ioaddr + SCB_CMD); outb(0, ioaddr + SIGNAL_CA); lp->last_restart = lp->stats.tx_packets; } dev->tbusy=0; dev->trans_start = jiffies; } /* If some higher layer thinks we've missed an tx-done interrupt we are passed NULL. Caution: dev_tint() handles the cli()/sti() itself. */ if (skb == NULL) { dev_tint(dev); return 0; } /* Block a timer-based transmit from overlapping. */ if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = skb->data; /* Disable the 82586's input to the interrupt line. */ outb(irqrmap[dev->irq], ioaddr + SET_IRQ); hardware_send_packet(dev, buf, length); dev->trans_start = jiffies; /* Enable the 82586 interrupt input. */ outb(0x08 | irqrmap[dev->irq], ioaddr + SET_IRQ); } dev_kfree_skb (skb, FREE_WRITE); /* You might need to clean up and record Tx statistics here. */ lp->stats.tx_aborted_errors++; return 0; }
static int tulip_start_xmit(struct sk_buff *skb, struct device *dev) { struct tulip_private *tp = (struct tulip_private *)dev->priv; int ioaddr = dev->base_addr; int entry; /* Transmitter timeout, serious problems. */ if (dev->tbusy) { int tickssofar = jiffies - dev->trans_start; int i; if (tickssofar < 20) return 1; printk("%s: transmit timed out, status %8.8x, SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n", dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12), inl(ioaddr + CSR13), inl(ioaddr + CSR14), inl(ioaddr + CSR15)); printk(" Rx ring %8.8x: ", (int)tp->rx_ring); for (i = 0; i < RX_RING_SIZE; i++) printk(" %8.8x", (unsigned int)tp->rx_ring[i].status); printk("\n Tx ring %8.8x: ", (int)tp->tx_ring); for (i = 0; i < TX_RING_SIZE; i++) printk(" %8.8x", (unsigned int)tp->tx_ring[i].status); printk("\n"); tp->stats.tx_errors++; /* We should reinitialize the hardware here. */ dev->tbusy=0; dev->trans_start = jiffies; return 0; } if (skb == NULL || skb->len <= 0) { printk("%s: Obsolete driver layer request made: skbuff==NULL.\n", dev->name); dev_tint(dev); return 0; } /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. If this ever occurs the queue layer is doing something evil! */ if (set_bit(0, (void*)&dev->tbusy) != 0) { printk("%s: Transmitter access conflict.\n", dev->name); return 1; } /* Caution: the write order is important here, set the base address with the "ownership" bits last. */ /* Calculate the next Tx descriptor entry. */ entry = tp->cur_tx % TX_RING_SIZE; tp->tx_full = 1; tp->tx_skbuff[entry] = skb; tp->tx_ring[entry].length = skb->len | (entry == TX_RING_SIZE-1 ? 0xe2000000 : 0xe0000000); tp->tx_ring[entry].buffer1 = skb->data; tp->tx_ring[entry].buffer2 = 0; tp->tx_ring[entry].status = 0x80000000; /* Pass ownership to the chip. */ tp->cur_tx++; /* Trigger an immediate transmit demand. */ outl(0, ioaddr + CSR1); dev->trans_start = jiffies; return 0; }
static int ni52_send_packet(struct sk_buff *skb, struct device *dev) { int len; #ifndef NO_NOPCOMMANDS int next_nop; #endif struct priv *p = (struct priv *) dev->priv; if(dev->tbusy) { int tickssofar = jiffies - dev->trans_start; if (tickssofar < 30) return 1; #ifdef DEBUG printk("%s: xmitter timed out, try to restart! stat: %04x\n",dev->name,p->scb->status); printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status); #endif ni52_close(dev); ni52_open(dev); dev->trans_start = jiffies; } if(skb == NULL) { dev_tint(dev); return 0; } if (skb->len <= 0) return 0; if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len); len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; #ifdef ONLY_ONE_XMIT_BUF # ifdef NO_NOPCOMMANDS p->xmit_buffs[0]->size = TBD_LAST | len; p->xmit_cmds[0]->cmd_status = 0; p->scb->cbl_offset = make16(p->xmit_cmds[0]); p->scb->cmd = CUC_START; dev->trans_start = jiffies; ni_attn586(); while(p->scb->cmd) for(len=0;len<256;len++); /* DELAY(1); */ /* TEST;TEST;TEST */ # else next_nop = (p->nop_point + 1) & 0x1; p->xmit_buffs[0]->size = TBD_LAST | len; p->xmit_cmds[0]->cmd_cmd = CMD_XMIT | CMD_INT; p->xmit_cmds[0]->cmd_status = 0; p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link = make16((p->nop_cmds[next_nop])); p->nop_cmds[next_nop]->cmd_status = 0; p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); dev->trans_start = jiffies; p->nop_point = next_nop; # endif #else p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len; if( (next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS ) next_nop = 0; p->xmit_cmds[p->xmit_count]->cmd_cmd = CMD_XMIT | CMD_INT; p->xmit_cmds[p->xmit_count]->cmd_status = 0; p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link = make16((p->nop_cmds[next_nop])); p->nop_cmds[next_nop]->cmd_status = 0; p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count])); dev->trans_start = jiffies; p->xmit_count = next_nop; cli(); if(p->xmit_count != p->xmit_last) dev->tbusy = 0; sti(); #endif } dev_kfree_skb(skb,FREE_WRITE); return 0; }
static int znet_send_packet(struct sk_buff *skb, struct device *dev) { int ioaddr = dev->base_addr; if (znet_debug > 4) printk(KERN_DEBUG "%s: ZNet_send_packet(%ld).\n", dev->name, dev->tbusy); /* Transmitter timeout, likely just recovery after suspending the machine. */ if (dev->tbusy) { ushort event, tx_status, rx_offset, state; int tickssofar = jiffies - dev->trans_start; if (tickssofar < 10) return 1; outb(CMD0_STAT0, ioaddr); event = inb(ioaddr); outb(CMD0_STAT1, ioaddr); tx_status = inw(ioaddr); outb(CMD0_STAT2, ioaddr); rx_offset = inw(ioaddr); outb(CMD0_STAT3, ioaddr); state = inb(ioaddr); printk(KERN_WARNING "%s: transmit timed out, status %02x %04x %04x %02x," " resetting.\n", dev->name, event, tx_status, rx_offset, state); if (tx_status == 0x0400) printk(KERN_WARNING "%s: Tx carrier error, check transceiver cable.\n", dev->name); outb(CMD0_RESET, ioaddr); hardware_init(dev); } if (skb == NULL) { dev_tint(dev); return 0; } /* Check that the part hasn't reset itself, probably from suspend. */ outb(CMD0_STAT0, ioaddr); if (inw(ioaddr) == 0x0010 && inw(ioaddr) == 0x0000 && inw(ioaddr) == 0x0010) hardware_init(dev); /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (set_bit(0, (void*)&dev->tbusy) != 0) printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = (void *)skb->data; ushort *tx_link = zn.tx_cur - 1; ushort rnd_len = (length + 1)>>1; { short dma_port = ((zn.tx_dma&3)<<2) + IO_DMA2_BASE; unsigned addr = inb(dma_port); addr |= inb(dma_port) << 8; addr <<= 1; if (((int)zn.tx_cur & 0x1ffff) != addr) printk(KERN_WARNING "Address mismatch at Tx: %#x vs %#x.\n", (int)zn.tx_cur & 0xffff, addr); zn.tx_cur = (ushort *)(((int)zn.tx_cur & 0xfe0000) | addr); } if (zn.tx_cur >= zn.tx_end) zn.tx_cur = zn.tx_start; *zn.tx_cur++ = length; if (zn.tx_cur + rnd_len + 1 > zn.tx_end) { int semi_cnt = (zn.tx_end - zn.tx_cur)<<1; /* Cvrt to byte cnt. */ memcpy(zn.tx_cur, buf, semi_cnt); rnd_len -= semi_cnt>>1; memcpy(zn.tx_start, buf + semi_cnt, length - semi_cnt); zn.tx_cur = zn.tx_start + rnd_len; } else {
static int i596_start_xmit(struct sk_buff *skb, struct device *dev) { struct i596_private *lp = (struct i596_private *)dev->priv; int ioaddr = dev->base_addr; struct tx_cmd *tx_cmd; if (i596_debug > 2) printk ("%s: Apricot start xmit\n", dev->name); /* Transmitter timeout, serious problems. */ if (dev->tbusy) { int tickssofar = jiffies - dev->trans_start; if (tickssofar < 5) return 1; printk("%s: transmit timed out, status resetting.\n", dev->name); lp->stats.tx_errors++; /* Try to restart the adaptor */ if (lp->last_restart == lp->stats.tx_packets) { if (i596_debug > 1) printk ("Resetting board.\n"); /* Shutdown and restart */ i596_reset(dev,lp, ioaddr); } else { /* Issue a channel attention signal */ if (i596_debug > 1) printk ("Kicking board.\n"); lp->scb.command = CUC_START|RX_START; outw(0, ioaddr+4); lp->last_restart = lp->stats.tx_packets; } dev->tbusy = 0; dev->trans_start = jiffies; } /* If some higher level thinks we've misses a tx-done interrupt we are passed NULL. n.b. dev_tint handles the cli()/sti() itself. */ if (skb == NULL) { dev_tint(dev); return 0; } /* shouldn't happen */ if (skb->len <= 0) return 0; if (i596_debug > 3) printk("%s: i596_start_xmit() called\n", dev->name); /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; dev->trans_start = jiffies; tx_cmd = (struct tx_cmd *) kmalloc ((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC); if (tx_cmd == NULL) { printk ("%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name); lp->stats.tx_dropped++; dev_kfree_skb(skb, FREE_WRITE); } else { tx_cmd->tbd = (struct i596_tbd *) (tx_cmd + 1); tx_cmd->tbd->next = (struct i596_tbd *) I596_NULL; tx_cmd->cmd.command = CMD_FLEX|CmdTx; tx_cmd->pad = 0; tx_cmd->size = 0; tx_cmd->tbd->pad = 0; tx_cmd->tbd->size = EOF | length; tx_cmd->tbd->data = skb->data; if (i596_debug > 3) print_eth(skb->data); i596_add_cmd(dev, (struct i596_cmd *)tx_cmd); lp->stats.tx_packets++; } } dev->tbusy = 0; return 0; }
static int net_send_packet(struct sk_buff *skb, struct device *dev) { if (dev->tbusy) { /* If we get here, some higher level has decided we are broken. There should really be a "kick me" function call instead. */ int tickssofar = jiffies - dev->trans_start; if (tickssofar < 5) return 1; if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name, tx_done(dev) ? "IRQ conflict" : "network cable problem"); /* Try to restart the adaptor. */ dev->tbusy=0; dev->trans_start = jiffies; } /* If some higher layer thinks we've missed an tx-done interrupt we are passed NULL. Caution: dev_tint() handles the cli()/sti() itself. */ if (skb == NULL) { dev_tint(dev); return 0; } /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { struct net_local *lp = (struct net_local *)dev->priv; unsigned long ioaddr = dev->base_addr; unsigned long flags; if (net_debug > 3)printk("%s: sent %ld byte packet of type %x\n", dev->name, skb->len, (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]); /* keep the upload from being interrupted, since we ask the chip to start transmitting before the whole packet has been completely uploaded. */ save_flags(flags); cli(); /* initiate a transmit sequence */ outw(lp->send_cmd, ioaddr + TX_CMD_PORT); outw(skb->len, ioaddr + TX_LEN_PORT); /* Test to see if the chip has allocated memory for the packet */ if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) { /* Gasp! It hasn't. But that shouldn't happen since we're waiting for TxOk, so return 1 and requeue this packet. */ restore_flags(flags); printk("cs8900 did not allocate memory for tx!\n"); return 1; } /* Write the contents of the packet */ outsw(ioaddr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1); restore_flags(flags); dev->trans_start = jiffies; } dev_kfree_skb (skb, FREE_WRITE); return 0; }