📄 3c527.c
字号:
* reply. All well and good. The complication arises because you use * commands for filter list changes which come in at bh level from things * like IPV6 group stuff. * * We have a simple state machine * * 0 - nothing issued * * 1 - command issued, wait reply * * 2 - reply waiting - reader then goes to state 0 * * 3 - command issued, trash reply. In which case the irq * takes it back to state 0 * */ static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len){ struct mc32_local *lp = (struct mc32_local *)dev->priv; int ioaddr = dev->base_addr; unsigned long flags; int ret = 0; /* * Wait for a command */ save_flags(flags); cli(); while(lp->exec_pending) sleep_on(&lp->event); /* * Issue mine */ lp->exec_pending=1; restore_flags(flags); lp->exec_box->mbox=0; lp->exec_box->mbox=cmd; memcpy((void *)lp->exec_box->data, data, len); barrier(); /* the memcpy forgot the volatile so be sure */ /* Send the command */ while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR)); outb(1<<6, ioaddr+HOST_CMD); save_flags(flags); cli(); while(lp->exec_pending!=2) sleep_on(&lp->event); lp->exec_pending=0; restore_flags(flags); if(lp->exec_box->mbox&(1<<13)) ret = -1; /* * A multicast set got blocked - do it now */ if(lp->mc_reload_wait) { mc32_reset_multicast_list(dev); } return ret;}/** * mc32_start_transceiver - tell board to restart tx/rx * @dev: The 3c527 card to issue the command to * * This may be called from the interrupt state, where it is used * to restart the rx ring if the card runs out of rx buffers. * * First, we check if it's ok to start the transceiver. We then show * the card where to start in the rx ring and issue the * commands to start reception and transmission. We don't wait * around for these to complete. */ static void mc32_start_transceiver(struct net_device *dev) { struct mc32_local *lp = (struct mc32_local *)dev->priv; int ioaddr = dev->base_addr; /* Ignore RX overflow on device closure */ if (lp->desired_state==HALTED) return; mc32_ready_poll(dev); lp->tx_box->mbox=0; lp->rx_box->mbox=0; /* Give the card the offset to the post-EOL-bit RX descriptor */ lp->rx_box->data[0]=lp->rx_ring[prev_rx(lp->rx_ring_tail)].p->next; outb(HOST_CMD_START_RX, ioaddr+HOST_CMD); mc32_ready_poll(dev); outb(HOST_CMD_RESTRT_TX, ioaddr+HOST_CMD); /* card ignores this on RX restart */ /* We are not interrupted on start completion */ lp->xceiver_state=RUNNING; }/** * mc32_halt_transceiver - tell board to stop tx/rx * @dev: The 3c527 card to issue the command to * * We issue the commands to halt the card's transceiver. In fact, * after some experimenting we now simply tell the card to * suspend. When issuing aborts occasionally odd things happened. * * We then sleep until the card has notified us that both rx and * tx have been suspended. */ static void mc32_halt_transceiver(struct net_device *dev) { struct mc32_local *lp = (struct mc32_local *)dev->priv; int ioaddr = dev->base_addr; unsigned long flags; mc32_ready_poll(dev); lp->tx_box->mbox=0; lp->rx_box->mbox=0; outb(HOST_CMD_SUSPND_RX, ioaddr+HOST_CMD); mc32_ready_poll(dev); outb(HOST_CMD_SUSPND_TX, ioaddr+HOST_CMD); save_flags(flags); cli(); while(lp->xceiver_state!=HALTED) sleep_on(&lp->event); restore_flags(flags); } /** * mc32_load_rx_ring - load the ring of receive buffers * @dev: 3c527 to build the ring for * * This initalises the on-card and driver datastructures to * the point where mc32_start_transceiver() can be called. * * The card sets up the receive ring for us. We are required to use the * ring it provides although we can change the size of the ring. * * We allocate an sk_buff for each ring entry in turn and * initalise its house-keeping info. At the same time, we read * each 'next' pointer in our rx_ring array. This reduces slow * shared-memory reads and makes it easy to access predecessor * descriptors. * * We then set the end-of-list bit for the last entry so that the * card will know when it has run out of buffers. */ static int mc32_load_rx_ring(struct net_device *dev){ struct mc32_local *lp = (struct mc32_local *)dev->priv; int i; u16 rx_base; volatile struct skb_header *p; rx_base=lp->rx_chain; for(i=0;i<RX_RING_LEN;i++) { lp->rx_ring[i].skb=alloc_skb(1532, GFP_KERNEL); skb_reserve(lp->rx_ring[i].skb, 18); if(lp->rx_ring[i].skb==NULL) { for(;i>=0;i--) kfree_skb(lp->rx_ring[i].skb); return -ENOBUFS; } p=bus_to_virt(lp->base+rx_base); p->control=0; p->data=virt_to_bus(lp->rx_ring[i].skb->data); p->status=0; p->length=1532; lp->rx_ring[i].p=p; rx_base=p->next; } lp->rx_ring[i-1].p->control |= CONTROL_EOL; lp->rx_ring_tail=0; return 0;} /** * mc32_flush_rx_ring - free the ring of receive buffers * @lp: Local data of 3c527 to flush the rx ring of * * Free the buffer for each ring slot. This may be called * before mc32_load_rx_ring(), eg. on error in mc32_open(). */static void mc32_flush_rx_ring(struct net_device *dev){ struct mc32_local *lp = (struct mc32_local *)dev->priv; struct sk_buff *skb; int i; for(i=0; i < RX_RING_LEN; i++) { skb = lp->rx_ring[i].skb; if (skb!=NULL) { kfree_skb(skb); skb=NULL; } lp->rx_ring[i].p=NULL; } }/** * mc32_load_tx_ring - load transmit ring * @dev: The 3c527 card to issue the command to * * This sets up the host transmit data-structures. * * First, we obtain from the card it's current postion in the tx * ring, so that we will know where to begin transmitting * packets. * * Then, we read the 'next' pointers from the on-card tx ring into * our tx_ring array to reduce slow shared-mem reads. Finally, we * intitalise the tx house keeping variables. * */ static void mc32_load_tx_ring(struct net_device *dev){ struct mc32_local *lp = (struct mc32_local *)dev->priv; volatile struct skb_header *p; int i; u16 tx_base; tx_base=lp->tx_box->data[0]; for(i=0;i<lp->tx_len;i++) { p=bus_to_virt(lp->base+tx_base); lp->tx_ring[i].p=p; lp->tx_ring[i].skb=NULL; tx_base=p->next; } /* -1 so that tx_ring_head cannot "lap" tx_ring_tail, */ /* which would be bad news for mc32_tx_ring as cur. implemented */ atomic_set(&lp->tx_count, TX_RING_LEN-1); lp->tx_ring_head=lp->tx_ring_tail=0; } /** * mc32_flush_tx_ring - free transmit ring * @lp: Local data of 3c527 to flush the tx ring of * * We have to consider two cases here. We want to free the pending * buffers only. If the ring buffer head is past the start then the * ring segment we wish to free wraps through zero. The tx ring * house-keeping variables are then reset. */static void mc32_flush_tx_ring(struct net_device *dev){ struct mc32_local *lp = (struct mc32_local *)dev->priv; if(lp->tx_ring_tail!=lp->tx_ring_head) { int i; if(lp->tx_ring_tail < lp->tx_ring_head) { for(i=lp->tx_ring_tail;i<lp->tx_ring_head;i++) { dev_kfree_skb(lp->tx_ring[i].skb); lp->tx_ring[i].skb=NULL; lp->tx_ring[i].p=NULL; } } else { for(i=lp->tx_ring_tail; i<TX_RING_LEN; i++) { dev_kfree_skb(lp->tx_ring[i].skb); lp->tx_ring[i].skb=NULL; lp->tx_ring[i].p=NULL; } for(i=0; i<lp->tx_ring_head; i++) { dev_kfree_skb(lp->tx_ring[i].skb); lp->tx_ring[i].skb=NULL; lp->tx_ring[i].p=NULL; } } } atomic_set(&lp->tx_count, 0); lp->tx_ring_tail=lp->tx_ring_head=0;} /** * mc32_open - handle 'up' of card * @dev: device to open * * The user is trying to bring the card into ready state. This requires * a brief dialogue with the card. Firstly we enable interrupts and then * 'indications'. Without these enabled the card doesn't bother telling * us what it has done. This had me puzzled for a week. * * We configure the number of card descriptors, then load the network * address and multicast filters. Turn on the workaround mode. This * works around a bug in the 82586 - it asks the firmware to do * so. It has a performance (latency) hit but is needed on busy * [read most] lans. We load the ring with buffers then we kick it * all off. */static int mc32_open(struct net_device *dev){ int ioaddr = dev->base_addr; struct mc32_local *lp = (struct mc32_local *)dev->priv; u8 one=1; u8 regs; u16 descnumbuffs[2] = {TX_RING_LEN, RX_RING_LEN}; /* * Interrupts enabled */ regs=inb(ioaddr+HOST_CTRL); regs|=HOST_CTRL_INTE; outb(regs, ioaddr+HOST_CTRL); /* * Send the indications on command */ mc32_command(dev, 4, &one, 2); /* * Poke it to make sure it's really dead. */ mc32_halt_transceiver(dev); mc32_flush_tx_ring(dev); /* * Ask card to set up on-card descriptors to our spec */ if(mc32_command(dev, 8, descnumbuffs, 4)) { printk("%s: %s rejected our buffer configuration!\n", dev->name, cardname); mc32_close(dev); return -ENOBUFS; } /* Report new configuration */ mc32_command(dev, 6, NULL, 0); lp->tx_chain = lp->exec_box->data[8]; /* Transmit list start offset */ lp->rx_chain = lp->exec_box->data[10]; /* Receive list start offset */ lp->tx_len = lp->exec_box->data[9]; /* Transmit list count */ lp->rx_len = lp->exec_box->data[11]; /* Receive list count */ /* Set Network Address */ mc32_command(dev, 1, dev->dev_addr, 6); /* Set the filters */ mc32_set_multicast_list(dev); if (WORKAROUND_82586) { u16 zero_word=0; mc32_command(dev, 0x0D, &zero_word, 2); /* 82586 bug workaround on */ } mc32_load_tx_ring(dev); if(mc32_load_rx_ring(dev)) { mc32_close(dev); return -ENOBUFS; } lp->desired_state = RUNNING; /* And finally, set the ball rolling... */ mc32_start_transceiver(dev); netif_start_queue(dev); return 0;}/** * mc32_timeout - handle a timeout from the network layer * @dev: 3c527 that timed out * * Handle a timeout on transmit from the 3c527. This normally means * bad things as the hardware handles cable timeouts and mess for * us. * */static void mc32_timeout(struct net_device *dev){ printk(KERN_WARNING "%s: transmit timed out?\n", dev->name); /* Try to restart the adaptor. */ netif_wake_queue(dev);}/** * mc32_send_packet - queue a frame for transmit * @skb: buffer to transmit * @dev: 3c527 to send it out of * * Transmit a buffer. This normally means throwing the buffer onto * the transmit queue as the queue is quite large. If the queue is * full then we set tx_busy and return. Once the interrupt handler * gets messages telling it to reclaim transmit queue entries we will * clear tx_busy and the kernel will start calling this again. * * We use cli rather than spinlocks. Since I have no access to an SMP * MCA machine I don't plan to change it. It is probably the top * performance hit for this driver on SMP however. */static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev){ struct mc32_local *lp = (struct mc32_local *)dev->priv; unsigned long flags; volatile struct skb_header *p, *np; netif_stop_queue(dev); save_flags(flags); cli(); if(atomic_read(&lp->tx_count)==0) { restore_flags(flags); return 1; } atomic_dec(&lp->tx_count); /* P is the last sending/sent buffer as a pointer */ p=lp->tx_ring[lp->tx_ring_head].p; lp->tx_ring_head=next_tx(lp->tx_ring_head); /* NP is the buffer we will be loading */ np=lp->tx_ring[lp->tx_ring_head].p; /* We will need this to flush the buffer out */ lp->tx_ring[lp->tx_ring_head].skb=skb; np->length = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; np->data = virt_to_bus(skb->data); np->status = 0; np->control = CONTROL_EOP | CONTROL_EOL; wmb(); p->control &= ~CONTROL_EOL; /* Clear EOL on p */ restore_flags(flags); netif_wake_queue(dev); return 0;}/** * mc32_update_stats - pull off the on board statistics * @dev: 3c527 to service * * * Query and reset the on-card stats. There's the small possibility * of a race here, which would result in an underestimation of * actual errors. As such, we'd prefer to keep all our stats * collection in software. As a rule, we do. However it can't be * used for rx errors and collisions as, by default, the card discards * bad rx packets. * * Setting the SAV BP in the rx filter command supposedly * stops this behaviour. However, testing shows that it only seems to * enable the collation of on-card rx statistics --- the driver * never sees an RX descriptor with an error status set. * */static void mc32_update_stats(struct net_device *dev){ struct mc32_local *lp = (struct mc32_local *)dev->priv; volatile struct mc32_stats *st = lp->stats; u32 rx_errors=0; rx_errors+=lp->net_stats.rx_crc_errors +=st->rx_crc_errors; st->rx_crc_errors=0; rx_errors+=lp->net_stats.rx_fifo_errors +=st->rx_overrun_errors; st->rx_overrun_errors=0; rx_errors+=lp->net_stats.rx_frame_errors +=st->rx_alignment_errors; st->rx_alignment_errors=0; rx_errors+=lp->net_stats.rx_length_errors+=st->rx_tooshort_errors; st->rx_tooshort_errors=0; rx_errors+=lp->net_stats.rx_missed_errors+=st->rx_outofresource_errors; st->rx_outofresource_errors=0; lp->net_stats.rx_errors=rx_errors; /* Number of packets which saw one collision */ lp->net_stats.collisions+=st->dataC[10]; st->dataC[10]=0; /* Number of packets which saw 2--15 collisions */ lp->net_stats.collisions+=st->dataC[11]; st->dataC[11]=0; } /** * mc32_rx_ring - process the receive ring * @dev: 3c527 that needs its receive ring processing * * * We have received one or more indications from the card that a * receive has completed. The buffer ring thus contains dirty * entries. We walk the ring by iterating over the circular rx_ring * array, starting at the next dirty buffer (which happens to be the * one we finished up at last time around). * * For each completed packet, we will either copy it and pass it up * the stack or, if the packet is near MTU sized, we allocate * another buffer and flip the old one up the stack. * * We must succeed in keeping a buffer on the ring. If neccessary we * will toss a received packet rather than lose a ring entry. Once * the first uncompleted descriptor is found, we move the * End-Of-List bit to include the buffers just processed. * */static void mc32_rx_ring(struct net_device *dev){ struct mc32_local *lp=dev->priv; volatile struct skb_header *p; u16 rx_ring_tail = lp->rx_ring_tail; u16 rx_old_tail = rx_ring_tail; int x=0; do { p=lp->rx_ring[rx_ring_tail].p; if(!(p->status & (1<<7))) { /* Not COMPLETED */ break; } if(p->status & (1<<6)) /* COMPLETED_OK */ { u16 length=p->length; struct sk_buff *skb; struct sk_buff *newskb;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -