📄 ibmtr.c
字号:
/* ibmtr.c: A shared-memory IBM Token Ring 16/4 driver for linux * * Written 1993 by Mark Swanson and Peter De Schrijver. * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * * This device driver should work with Any IBM Token Ring Card that does * not use DMA. * * I used Donald Becker's (becker@scyld.com) device driver work * as a base for most of my initial work. * * Changes by Peter De Schrijver * (Peter.Deschrijver@linux.cc.kuleuven.ac.be) : * * + changed name to ibmtr.c in anticipation of other tr boards. * + changed reset code and adapter open code. * + added SAP open code. * + a first attempt to write interrupt, transmit and receive routines. * * Changes by David W. Morris (dwm@shell.portal.com) : * 941003 dwm: - Restructure tok_probe for multiple adapters, devices. * + Add comments, misc reorg for clarity. * + Flatten interrupt handler levels. * * Changes by Farzad Farid (farzy@zen.via.ecp.fr) * and Pascal Andre (andre@chimay.via.ecp.fr) (March 9 1995) : * + multi ring support clean up. * + RFC1042 compliance enhanced. * * Changes by Pascal Andre (andre@chimay.via.ecp.fr) (September 7 1995) : * + bug correction in tr_tx * + removed redundant information display * + some code reworking * * Changes by Michel Lespinasse (walken@via.ecp.fr), * Yann Doussot (doussot@via.ecp.fr) and Pascal Andre (andre@via.ecp.fr) * (February 18, 1996) : * + modified shared memory and mmio access port the driver to * alpha platform (structure access -> readb/writeb) * * Changes by Steve Kipisz (bungy@ibm.net or kipisz@vnet.ibm.com) * (January 18 1996): * + swapped WWOR and WWCR in ibmtr.h * + moved some init code from tok_probe into trdev_init. The * PCMCIA code can call trdev_init to complete initializing * the driver. * + added -DPCMCIA to support PCMCIA * + detecting PCMCIA Card Removal in interrupt handler. If * ISRP is FF, then a PCMCIA card has been removed * 10/2000 Burt needed a new method to avoid crashing the OS * * Changes by Paul Norton (pnorton@cts.com) : * + restructured the READ.LOG logic to prevent the transmit SRB * from being rudely overwritten before the transmit cycle is * complete. (August 15 1996) * + completed multiple adapter support. (November 20 1996) * + implemented csum_partial_copy in tr_rx and increased receive * buffer size and count. Minor fixes. (March 15, 1997) * * Changes by Christopher Turcksin <wabbit@rtfc.demon.co.uk> * + Now compiles ok as a module again. * * Changes by Paul Norton (pnorton@ieee.org) : * + moved the header manipulation code in tr_tx and tr_rx to * net/802/tr.c. (July 12 1997) * + add retry and timeout on open if cable disconnected. (May 5 1998) * + lifted 2000 byte mtu limit. now depends on shared-RAM size. * May 25 1998) * + can't allocate 2k recv buff at 8k shared-RAM. (20 October 1998) * * Changes by Joel Sloan (jjs@c-me.com) : * + disable verbose debug messages by default - to enable verbose * debugging, edit the IBMTR_DEBUG_MESSAGES define below * * Changes by Mike Phillips <phillim@amtrak.com> : * + Added extra #ifdef's to work with new PCMCIA Token Ring Code. * The PCMCIA code now just sets up the card so it can be recognized * by ibmtr_probe. Also checks allocated memory vs. on-board memory * for correct figure to use. * * Changes by Tim Hockin (thockin@isunix.it.ilstu.edu) : * + added spinlocks for SMP sanity (10 March 1999) * * Changes by Jochen Friedrich to enable RFC1469 Option 2 multicasting * i.e. using functional address C0 00 00 04 00 00 to transmit and * receive multicast packets. * * Changes by Mike Sullivan (based on original sram patch by Dave Grothe * to support windowing into on adapter shared ram. * i.e. Use LANAID to setup a PnP configuration with 16K RAM. Paging * will shift this 16K window over the entire available shared RAM. * * Changes by Peter De Schrijver (p2@mind.be) : * + fixed a problem with PCMCIA card removal * * Change by Mike Sullivan et al.: * + added turbo card support. No need to use lanaid to configure * the adapter into isa compatiblity mode. * * Changes by Burt Silverman to allow the computer to behave nicely when * a cable is pulled or not in place, or a PCMCIA card is removed hot. *//* change the define of IBMTR_DEBUG_MESSAGES to a nonzero value in the event that chatty debug messages are desired - jjs 12/30/98 */#define IBMTR_DEBUG_MESSAGES 0#include <linux/module.h>#ifdef PCMCIA /* required for ibmtr_cs.c to build */#undef MODULE /* yes, really */#undef ENABLE_PAGING#else#define ENABLE_PAGING 1 #endif#define FALSE 0#define TRUE (!FALSE)/* changes the output format of driver initialization */#define TR_VERBOSE 0/* some 95 OS send many non UI frame; this allow removing the warning */#define TR_FILTERNONUI 1#include <linux/ioport.h>#include <linux/netdevice.h>#include <linux/ip.h>#include <linux/trdevice.h>#include <linux/ibmtr.h>#include <net/checksum.h>#include <asm/io.h>#define DPRINTK(format, args...) printk("%s: " format, dev->name , ## args)#define DPRINTD(format, args...) DummyCall("%s: " format, dev->name , ## args)/* version and credits */#ifndef PCMCIAstatic char version[] __initdata = "\nibmtr.c: v1.3.57 8/ 7/94 Peter De Schrijver and Mark Swanson\n" " v2.1.125 10/20/98 Paul Norton <pnorton@ieee.org>\n" " v2.2.0 12/30/98 Joel Sloan <jjs@c-me.com>\n" " v2.2.1 02/08/00 Mike Sullivan <sullivam@us.ibm.com>\n" " v2.2.2 07/27/00 Burt Silverman <burts@us.ibm.com>\n" " v2.4.0 03/01/01 Mike Sullivan <sullivan@us.ibm.com>\n";#endif/* this allows displaying full adapter information */static char *channel_def[] __devinitdata = { "ISA", "MCA", "ISA P&P" };static char pcchannelid[] __devinitdata = { 0x05, 0x00, 0x04, 0x09, 0x04, 0x03, 0x04, 0x0f, 0x03, 0x06, 0x03, 0x01, 0x03, 0x01, 0x03, 0x00, 0x03, 0x09, 0x03, 0x09, 0x03, 0x00, 0x02, 0x00};static char mcchannelid[] __devinitdata = { 0x04, 0x0d, 0x04, 0x01, 0x05, 0x02, 0x05, 0x03, 0x03, 0x06, 0x03, 0x03, 0x05, 0x08, 0x03, 0x04, 0x03, 0x05, 0x03, 0x01, 0x03, 0x08, 0x02, 0x00};static char __devinit *adapter_def(char type){ switch (type) { case 0xF: return "PC Adapter | PC Adapter II | Adapter/A"; case 0xE: return "16/4 Adapter | 16/4 Adapter/A (long)"; case 0xD: return "16/4 Adapter/A (short) | 16/4 ISA-16 Adapter"; case 0xC: return "Auto 16/4 Adapter"; default: return "adapter (unknown type)"; };};#define TRC_INIT 0x01 /* Trace initialization & PROBEs */#define TRC_INITV 0x02 /* verbose init trace points */static unsigned char ibmtr_debug_trace = 0;static int ibmtr_probe(struct net_device *dev);static int ibmtr_probe1(struct net_device *dev, int ioaddr);static unsigned char get_sram_size(struct tok_info *adapt_info);static int trdev_init(struct net_device *dev);static int tok_open(struct net_device *dev);static int tok_init_card(struct net_device *dev);static void tok_open_adapter(unsigned long dev_addr);static void open_sap(unsigned char type, struct net_device *dev);static void tok_set_multicast_list(struct net_device *dev);static int tok_send_packet(struct sk_buff *skb, struct net_device *dev);static int tok_close(struct net_device *dev);static irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs);static void initial_tok_int(struct net_device *dev);static void tr_tx(struct net_device *dev);static void tr_rx(struct net_device *dev);static void ibmtr_reset_timer(struct timer_list*tmr,struct net_device *dev);static void tok_rerun(unsigned long dev_addr);static void ibmtr_readlog(struct net_device *dev);static struct net_device_stats *tok_get_stats(struct net_device *dev);static int ibmtr_change_mtu(struct net_device *dev, int mtu);static void find_turbo_adapters(int *iolist);static int ibmtr_portlist[IBMTR_MAX_ADAPTERS+1] __devinitdata = { 0xa20, 0xa24, 0, 0, 0};static int __devinitdata turbo_io[IBMTR_MAX_ADAPTERS] = {0};static int __devinitdata turbo_irq[IBMTR_MAX_ADAPTERS] = {0};static int __devinitdata turbo_searched = 0;#ifndef PCMCIAstatic __u32 ibmtr_mem_base __initdata = 0xd0000;#endifstatic void __devinit PrtChanID(char *pcid, short stride){ short i, j; for (i = 0, j = 0; i < 24; i++, j += stride) printk("%1x", ((int) pcid[j]) & 0x0f); printk("\n");}static void __devinit HWPrtChanID(void __iomem *pcid, short stride){ short i, j; for (i = 0, j = 0; i < 24; i++, j += stride) printk("%1x", ((int) readb(pcid + j)) & 0x0f); printk("\n");}/* We have to ioremap every checked address, because isa_readb is * going away. */static void __devinit find_turbo_adapters(int *iolist){ int ram_addr; int index=0; void __iomem *chanid; int found_turbo=0; unsigned char *tchanid, ctemp; int i, j; unsigned long jif; void __iomem *ram_mapped ; if (turbo_searched == 1) return; turbo_searched=1; for (ram_addr=0xC0000; ram_addr < 0xE0000; ram_addr+=0x2000) { __u32 intf_tbl=0; found_turbo=1; ram_mapped = ioremap((u32)ram_addr,0x1fff) ; if (ram_mapped==NULL) continue ; chanid=(CHANNEL_ID + ram_mapped); tchanid=pcchannelid; ctemp=readb(chanid) & 0x0f; if (ctemp != *tchanid) continue; for (i=2,j=1; i<=46; i=i+2,j++) { if ((readb(chanid+i) & 0x0f) != tchanid[j]){ found_turbo=0; break; } } if (!found_turbo) continue; writeb(0x90, ram_mapped+0x1E01); for(i=2; i<0x0f; i++) { writeb(0x00, ram_mapped+0x1E01+i); } writeb(0x00, ram_mapped+0x1E01); for(jif=jiffies+TR_BUSY_INTERVAL; time_before_eq(jiffies,jif);); intf_tbl=ntohs(readw(ram_mapped+ACA_OFFSET+ACA_RW+WRBR_EVEN)); if (intf_tbl) {#if IBMTR_DEBUG_MESSAGES printk("ibmtr::find_turbo_adapters, Turbo found at " "ram_addr %x\n",ram_addr); printk("ibmtr::find_turbo_adapters, interface_table "); for(i=0; i<6; i++) { printk("%x:",readb(ram_addr+intf_tbl+i)); } printk("\n");#endif turbo_io[index]=ntohs(readw(ram_mapped+intf_tbl+4)); turbo_irq[index]=readb(ram_mapped+intf_tbl+3); outb(0, turbo_io[index] + ADAPTRESET); for(jif=jiffies+TR_RST_TIME;time_before_eq(jiffies,jif);); outb(0, turbo_io[index] + ADAPTRESETREL); index++; continue; }#if IBMTR_DEBUG_MESSAGES printk("ibmtr::find_turbo_adapters, ibmtr card found at" " %x but not a Turbo model\n",ram_addr);#endif iounmap(ram_mapped) ; } /* for */ for(i=0; i<IBMTR_MAX_ADAPTERS; i++) { if(!turbo_io[i]) break; for (j=0; j<IBMTR_MAX_ADAPTERS; j++) { if ( iolist[j] && iolist[j] != turbo_io[i]) continue; iolist[j]=turbo_io[i]; break; } }}static void ibmtr_cleanup_card(struct net_device *dev){ if (dev->base_addr) { outb(0,dev->base_addr+ADAPTRESET); schedule_timeout_uninterruptible(TR_RST_TIME); /* wait 50ms */ outb(0,dev->base_addr+ADAPTRESETREL); }#ifndef PCMCIA free_irq(dev->irq, dev); release_region(dev->base_addr, IBMTR_IO_EXTENT); { struct tok_info *ti = (struct tok_info *) dev->priv; iounmap(ti->mmio); iounmap(ti->sram_virt); }#endif }int ibmtr_probe_card(struct net_device *dev){ int err = ibmtr_probe(dev); if (!err) { err = register_netdev(dev); if (err) ibmtr_cleanup_card(dev); } return err;}/**************************************************************************** * ibmtr_probe(): Routine specified in the network device structure * to probe for an IBM Token Ring Adapter. Routine outline: * I. Interrogate hardware to determine if an adapter exists * and what the speeds and feeds are * II. Setup data structures to control execution based upon * adapter characteristics. * * We expect ibmtr_probe to be called once for each device entry * which references it. ****************************************************************************/static int ibmtr_probe(struct net_device *dev){ int i; int base_addr = dev->base_addr; if (base_addr && base_addr <= 0x1ff) /* Don't probe at all. */ return -ENXIO; if (base_addr > 0x1ff) { /* Check a single specified location. */ if (!ibmtr_probe1(dev, base_addr)) return 0; return -ENODEV; } find_turbo_adapters(ibmtr_portlist); for (i = 0; ibmtr_portlist[i]; i++) { int ioaddr = ibmtr_portlist[i]; if (!ibmtr_probe1(dev, ioaddr)) return 0; } return -ENODEV;}/*****************************************************************************/static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr){ unsigned char segment, intr=0, irq=0, i, j, cardpresent=NOTOK, temp=0; void __iomem * t_mmio = NULL; struct tok_info *ti = dev->priv; void __iomem *cd_chanid; unsigned char *tchanid, ctemp;#ifndef PCMCIA unsigned char t_irq=0; unsigned long timeout; static int version_printed;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -