📄 3c527.c
字号:
/* 3c527.c: 3Com Etherlink/MC32 driver for Linux 2.4 * * (c) Copyright 1998 Red Hat Software Inc * Written by Alan Cox. * Further debugging by Carl Drougge. * Modified by Richard Procter (rnp@netlink.co.nz) * * Based on skeleton.c written 1993-94 by Donald Becker and ne2.c * (for the MCA stuff) written by Wim Dumon. * * Thanks to 3Com for making this possible by providing me with the * documentation. * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * */#define DRV_NAME "3c527"#define DRV_VERSION "0.6a"#define DRV_RELDATE "2001/11/17"static const char *version =DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Proctor (rnp@netlink.co.nz)\n";/** * DOC: Traps for the unwary * * The diagram (Figure 1-1) and the POS summary disagree with the * "Interrupt Level" section in the manual. * * The manual contradicts itself when describing the minimum number * buffers in the 'configure lists' command. * My card accepts a buffer config of 4/4. * * Setting the SAV BP bit does not save bad packets, but * only enables RX on-card stats collection. * * The documentation in places seems to miss things. In actual fact * I've always eventually found everything is documented, it just * requires careful study. * * DOC: Theory Of Operation * * The 3com 3c527 is a 32bit MCA bus mastering adapter with a large * amount of on board intelligence that housekeeps a somewhat dumber * Intel NIC. For performance we want to keep the transmit queue deep * as the card can transmit packets while fetching others from main * memory by bus master DMA. Transmission and reception are driven by * circular buffer queues. * * The mailboxes can be used for controlling how the card traverses * its buffer rings, but are used only for inital setup in this * implementation. The exec mailbox allows a variety of commands to * be executed. Each command must complete before the next is * executed. Primarily we use the exec mailbox for controlling the * multicast lists. We have to do a certain amount of interesting * hoop jumping as the multicast list changes can occur in interrupt * state when the card has an exec command pending. We defer such * events until the command completion interrupt. * * A copy break scheme (taken from 3c59x.c) is employed whereby * received frames exceeding a configurable length are passed * directly to the higher networking layers without incuring a copy, * in what amounts to a time/space trade-off. * * The card also keeps a large amount of statistical information * on-board. In a perfect world, these could be used safely at no * cost. However, lacking information to the contrary, processing * them without races would involve so much extra complexity as to * make it unworthwhile to do so. In the end, a hybrid SW/HW * implementation was made necessary --- see mc32_update_stats(). * * DOC: Notes * * It should be possible to use two or more cards, but at this stage * only by loading two copies of the same module. * * The on-board 82586 NIC has trouble receiving multiple * back-to-back frames and so is likely to drop packets from fast * senders.**/#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/mca.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/ethtool.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/dma.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/if_ether.h>#include "3c527.h"/* * The name of the card. Is used for messages and in the requests for * io regions, irqs and dma channels */static const char* cardname = DRV_NAME;/* use 0 for production, 1 for verification, >2 for debug */#ifndef NET_DEBUG#define NET_DEBUG 2#endif#undef DEBUG_IRQstatic unsigned int mc32_debug = NET_DEBUG;/* The number of low I/O ports used by the ethercard. */#define MC32_IO_EXTENT 8/* As implemented, values must be a power-of-2 -- 4/8/16/32 */ #define TX_RING_LEN 32 /* Typically the card supports 37 */#define RX_RING_LEN 8 /* " " " *//* Copy break point, see above for details. * Setting to > 1512 effectively disables this feature. */ #define RX_COPYBREAK 200 /* Value from 3c59x.c *//* Issue the 82586 workaround command - this is for "busy lans", but * basically means for all lans now days - has a performance (latency) * cost, but best set. */ static const int WORKAROUND_82586=1;/* Pointers to buffers and their on-card records */struct mc32_ring_desc { volatile struct skb_header *p; struct sk_buff *skb; };/* Information that needs to be kept for each board. */struct mc32_local { struct net_device_stats net_stats; int slot; volatile struct mc32_mailbox *rx_box; volatile struct mc32_mailbox *tx_box; volatile struct mc32_mailbox *exec_box; volatile struct mc32_stats *stats; /* Start of on-card statistics */ u16 tx_chain; /* Transmit list start offset */ u16 rx_chain; /* Receive list start offset */ u16 tx_len; /* Transmit list count */ u16 rx_len; /* Receive list count */ u32 base; u16 exec_pending; u16 mc_reload_wait; /* a multicast load request is pending */ u32 mc_list_valid; /* True when the mclist is set */ u16 xceiver_state; /* Current transceiver state. bitmapped */ u16 desired_state; /* The state we want the transceiver to be in */ atomic_t tx_count; /* buffers left */ wait_queue_head_t event; struct mc32_ring_desc tx_ring[TX_RING_LEN]; /* Host Transmit ring */ struct mc32_ring_desc rx_ring[RX_RING_LEN]; /* Host Receive ring */ u16 tx_ring_tail; /* index to tx de-queue end */ u16 tx_ring_head; /* index to tx en-queue end */ u16 rx_ring_tail; /* index to rx de-queue end */ };/* The station (ethernet) address prefix, used for a sanity check. */#define SA_ADDR0 0x02#define SA_ADDR1 0x60#define SA_ADDR2 0xACstruct mca_adapters_t { unsigned int id; char *name;};const struct mca_adapters_t mc32_adapters[] = { { 0x0041, "3COM EtherLink MC/32" }, { 0x8EF5, "IBM High Performance Lan Adapter" }, { 0x0000, NULL }};/* Macros for ring index manipulations */ static inline u16 next_rx(u16 rx) { return (rx+1)&(RX_RING_LEN-1); };static inline u16 prev_rx(u16 rx) { return (rx-1)&(RX_RING_LEN-1); };static inline u16 next_tx(u16 tx) { return (tx+1)&(TX_RING_LEN-1); };/* Index to functions, as function prototypes. */extern int mc32_probe(struct net_device *dev);static int mc32_probe1(struct net_device *dev, int ioaddr);static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len);static int mc32_open(struct net_device *dev);static void mc32_timeout(struct net_device *dev);static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev);static void mc32_interrupt(int irq, void *dev_id, struct pt_regs *regs);static int mc32_close(struct net_device *dev);static struct net_device_stats *mc32_get_stats(struct net_device *dev);static void mc32_set_multicast_list(struct net_device *dev);static void mc32_reset_multicast_list(struct net_device *dev);static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);/** * mc32_probe - Search for supported boards * @dev: device to probe * * Because MCA bus is a real bus and we can scan for cards we could do a * single scan for all boards here. Right now we use the passed in device * structure and scan for only one board. This needs fixing for modules * in paticular. */int __init mc32_probe(struct net_device *dev){ static int current_mca_slot = -1; int i; int adapter_found = 0; SET_MODULE_OWNER(dev); /* Do not check any supplied i/o locations. POS registers usually don't fail :) */ /* MCA cards have POS registers. Autodetecting MCA cards is extremely simple. Just search for the card. */ for(i = 0; (mc32_adapters[i].name != NULL) && !adapter_found; i++) { current_mca_slot = mca_find_unused_adapter(mc32_adapters[i].id, 0); if((current_mca_slot != MCA_NOTFOUND) && !adapter_found) { if(!mc32_probe1(dev, current_mca_slot)) { mca_set_adapter_name(current_mca_slot, mc32_adapters[i].name); mca_mark_as_used(current_mca_slot); return 0; } } } return -ENODEV;}/** * mc32_probe1 - Check a given slot for a board and test the card * @dev: Device structure to fill in * @slot: The MCA bus slot being used by this card * * Decode the slot data and configure the card structures. Having done this we * can reset the card and configure it. The card does a full self test cycle * in firmware so we have to wait for it to return and post us either a * failure case or some addresses we use to find the board internals. */static int __init mc32_probe1(struct net_device *dev, int slot){ static unsigned version_printed; int i, err; u8 POS; u32 base; struct mc32_local *lp; static u16 mca_io_bases[]={ 0x7280,0x7290, 0x7680,0x7690, 0x7A80,0x7A90, 0x7E80,0x7E90 }; static u32 mca_mem_bases[]={ 0x00C0000, 0x00C4000, 0x00C8000, 0x00CC000, 0x00D0000, 0x00D4000, 0x00D8000, 0x00DC000 }; static char *failures[]={ "Processor instruction", "Processor data bus", "Processor data bus", "Processor data bus", "Adapter bus", "ROM checksum", "Base RAM", "Extended RAM", "82586 internal loopback", "82586 initialisation failure", "Adapter list configuration error" }; /* Time to play MCA games */ if (mc32_debug && version_printed++ == 0) printk(KERN_DEBUG "%s", version); printk(KERN_INFO "%s: %s found in slot %d:", dev->name, cardname, slot); POS = mca_read_stored_pos(slot, 2); if(!(POS&1)) { printk(" disabled.\n"); return -ENODEV; } /* Fill in the 'dev' fields. */ dev->base_addr = mca_io_bases[(POS>>1)&7]; dev->mem_start = mca_mem_bases[(POS>>4)&7]; POS = mca_read_stored_pos(slot, 4); if(!(POS&1)) { printk("memory window disabled.\n"); return -ENODEV; } POS = mca_read_stored_pos(slot, 5); i=(POS>>4)&3; if(i==3) { printk("invalid memory window.\n"); return -ENODEV; } i*=16384; i+=16384; dev->mem_end=dev->mem_start + i; dev->irq = ((POS>>2)&3)+9; if(!request_region(dev->base_addr, MC32_IO_EXTENT, cardname)) { printk("io 0x%3lX, which is busy.\n", dev->base_addr); return -EBUSY; } printk("io 0x%3lX irq %d mem 0x%lX (%dK)\n", dev->base_addr, dev->irq, dev->mem_start, i/1024); /* We ought to set the cache line size here.. */ /* * Go PROM browsing */ printk("%s: Address ", dev->name); /* Retrieve and print the ethernet address. */ for (i = 0; i < 6; i++) { mca_write_pos(slot, 6, i+12); mca_write_pos(slot, 7, 0); printk(" %2.2x", dev->dev_addr[i] = mca_read_pos(slot,3)); } mca_write_pos(slot, 6, 0); mca_write_pos(slot, 7, 0); POS = mca_read_stored_pos(slot, 4); if(POS&2) printk(" : BNC port selected.\n"); else printk(" : AUI port selected.\n"); POS=inb(dev->base_addr+HOST_CTRL); POS|=HOST_CTRL_ATTN|HOST_CTRL_RESET; POS&=~HOST_CTRL_INTE; outb(POS, dev->base_addr+HOST_CTRL); /* Reset adapter */ udelay(100); /* Reset off */ POS&=~(HOST_CTRL_ATTN|HOST_CTRL_RESET); outb(POS, dev->base_addr+HOST_CTRL); udelay(300); /* * Grab the IRQ */ i = request_irq(dev->irq, &mc32_interrupt, SA_SHIRQ, dev->name, dev); if (i) { release_region(dev->base_addr, MC32_IO_EXTENT); printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); return i; } /* Initialize the device structure. */ dev->priv = kmalloc(sizeof(struct mc32_local), GFP_KERNEL); if (dev->priv == NULL) { err = -ENOMEM; goto err_exit_irq; } memset(dev->priv, 0, sizeof(struct mc32_local)); lp = dev->priv; lp->slot = slot; i=0; base = inb(dev->base_addr); while(base == 0xFF) { i++; if(i == 1000) { printk(KERN_ERR "%s: failed to boot adapter.\n", dev->name); err = -ENODEV; goto err_exit_free; } udelay(1000); if(inb(dev->base_addr+2)&(1<<5)) base = inb(dev->base_addr); } if(base>0) { if(base < 0x0C) printk(KERN_ERR "%s: %s%s.\n", dev->name, failures[base-1], base<0x0A?" test failure":""); else printk(KERN_ERR "%s: unknown failure %d.\n", dev->name, base); err = -ENODEV; goto err_exit_free; } base=0; for(i=0;i<4;i++) { int n=0; while(!(inb(dev->base_addr+2)&(1<<5))) { n++; udelay(50); if(n>100) { printk(KERN_ERR "%s: mailbox read fail (%d).\n", dev->name, i); err = -ENODEV; goto err_exit_free; } } base|=(inb(dev->base_addr)<<(8*i)); } lp->exec_box=bus_to_virt(dev->mem_start+base); base=lp->exec_box->data[1]<<16|lp->exec_box->data[0]; lp->base = dev->mem_start+base; lp->rx_box=bus_to_virt(lp->base + lp->exec_box->data[2]); lp->tx_box=bus_to_virt(lp->base + lp->exec_box->data[3]); lp->stats = bus_to_virt(lp->base + lp->exec_box->data[5]); /* * Descriptor chains (card relative) */ 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 */ init_waitqueue_head(&lp->event); printk("%s: Firmware Rev %d. %d RX buffers, %d TX buffers. Base of 0x%08X.\n", dev->name, lp->exec_box->data[12], lp->rx_len, lp->tx_len, lp->base); dev->open = mc32_open; dev->stop = mc32_close; dev->hard_start_xmit = mc32_send_packet; dev->get_stats = mc32_get_stats; dev->set_multicast_list = mc32_set_multicast_list; dev->tx_timeout = mc32_timeout; dev->watchdog_timeo = HZ*5; /* Board does all the work */ dev->do_ioctl = netdev_ioctl; lp->xceiver_state = HALTED; lp->tx_ring_tail=lp->tx_ring_head=0; /* Fill in the fields of the device structure with ethernet values. */ ether_setup(dev); return 0;err_exit_free: kfree(dev->priv);err_exit_irq: free_irq(dev->irq, dev); release_region(dev->base_addr, MC32_IO_EXTENT); return err;}/** * mc32_ready_poll - wait until we can feed it a command * @dev: The device to wait for * * Wait until the card becomes ready to accept a command via the * command register. This tells us nothing about the completion * status of any pending commands and takes very little time at all. */ static void mc32_ready_poll(struct net_device *dev){ int ioaddr = dev->base_addr; while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));}/** * mc32_command_nowait - send a command non blocking * @dev: The 3c527 to issue the command to * @cmd: The command word to write to the mailbox * @data: A data block if the command expects one * @len: Length of the data block * * Send a command from interrupt state. If there is a command * currently being executed then we return an error of -1. It simply * isn't viable to wait around as commands may be slow. Providing we * get in, we busy wait for the board to become ready to accept the * command and issue it. We do not wait for the command to complete * --- the card will interrupt us when it's done. */static int mc32_command_nowait(struct net_device *dev, u16 cmd, void *data, int len){ struct mc32_local *lp = (struct mc32_local *)dev->priv; int ioaddr = dev->base_addr; if(lp->exec_pending) return -1; lp->exec_pending=3; 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); return 0;}/** * mc32_command - send a command and sleep until completion * @dev: The 3c527 card to issue the command to * @cmd: The command word to write to the mailbox * @data: A data block if the command expects one * @len: Length of the data block * * Sends exec commands in a user context. This permits us to wait around * for the replies and also to wait for the command buffer to complete * from a previous command before we execute our command. After our * command completes we will complete any pending multicast reload * we blocked off by hogging the exec buffer. * * You feed the card a command, you wait, it interrupts you get a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -