From 756b5aabfed7c39e27e195c350080be6edeeed8f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:15:58 -0500 Subject: [PATCH] What 2.1.110-3 does is to much more aggressively throw out dentries (and thus inodes) under low-memory circumstances. It may be _too_ aggressive right now, but if so that just gives a good mid point to strive for. I'd really like to hear comments about how this "feels" (and numbers too, if you have them). It's fairly hard for me to judge, as whenever I run Linux on small-memory machines it always feels slower than I'm used to, regardless of whether Linux does the right thing or not ;) Linus --- CREDITS | 5 +- Documentation/Configure.help | 19 +- Documentation/parport.txt | 5 + Documentation/tlan.txt | 135 ++ MAINTAINERS | 6 +- Makefile | 13 +- arch/alpha/Makefile | 7 +- arch/alpha/defconfig | 15 +- arch/alpha/kernel/bios32.c | 36 +- arch/alpha/kernel/mcpcia.c | 12 +- arch/alpha/kernel/osf_sys.c | 4 +- arch/alpha/lib/io.c | 141 +- arch/alpha/lib/memset.S | 25 +- arch/alpha/math-emu/fp-emul.c | 1 + arch/arm/mm/mm-ebsa285.c | 1 + arch/i386/Makefile | 8 - arch/i386/boot/Makefile | 5 +- arch/i386/boot/compressed/Makefile | 16 +- arch/i386/kernel/Makefile | 17 +- arch/i386/kernel/bios32.c | 30 +- arch/i386/lib/Makefile | 5 - arch/sparc/kernel/Makefile | 21 - arch/sparc/lib/Makefile | 15 +- arch/sparc/mm/Makefile | 18 - arch/sparc64/kernel/Makefile | 12 - arch/sparc64/mm/Makefile | 12 - drivers/char/Makefile | 2 +- drivers/char/h8.c | 55 +- drivers/char/hfmodem/Makefile | 2 +- drivers/char/i2c.c | 1 + drivers/char/mem.c | 16 +- drivers/misc/parport_procfs.c | 34 + drivers/misc/parport_share.c | 69 +- drivers/net/8390.c | 2 +- drivers/net/hamradio/soundmodem/Makefile | 2 +- drivers/net/ne.c | 6 +- drivers/net/ne2k-pci.c | 8 +- drivers/net/sk_g16.c | 2 +- drivers/net/tlan.c | 1504 ++++++++++++---------- drivers/net/tlan.h | 242 ++-- drivers/pnp/parport_probe.c | 19 +- drivers/scsi/ChangeLog.ncr53c8xx | 18 + drivers/scsi/ncr53c8xx.c | 36 +- drivers/scsi/ncr53c8xx.h | 22 +- drivers/sound/Makefile | 4 +- drivers/video/macmodes.c | 1 - drivers/video/promcon.c | 1 - drivers/video/vgacon.c | 1 + fs/coda/psdev.c | 11 +- fs/coda/upcall.c | 2 + fs/dcache.c | 4 + include/asm-alpha/apecs.h | 15 + include/asm-alpha/cia.h | 15 + include/asm-alpha/io.h | 30 +- include/asm-alpha/jensen.h | 20 + include/asm-alpha/lca.h | 15 + include/asm-alpha/mcpcia.h | 60 +- include/asm-alpha/pgtable.h | 7 +- include/asm-alpha/pyxis.h | 72 +- include/asm-alpha/string.h | 16 +- include/asm-alpha/t2.h | 189 +-- include/asm-alpha/tsunami.h | 114 +- include/asm-arm/init.h | 2 + include/linux/console_struct.h | 2 - include/linux/parport.h | 13 +- include/linux/pci.h | 74 ++ include/linux/quotaops.h | 6 +- include/linux/random.h | 4 + init/main.c | 4 + mm/page_alloc.c | 15 +- mm/vmscan.c | 5 +- scripts/Makefile | 1 - scripts/lxdialog/Makefile | 7 +- 73 files changed, 1966 insertions(+), 1368 deletions(-) create mode 100644 Documentation/tlan.txt diff --git a/CREDITS b/CREDITS index 431153ec4ed6..8bce91680759 100644 --- a/CREDITS +++ b/CREDITS @@ -717,9 +717,10 @@ S: D - 72072 Tuebingen S: Germany N: Jauder Ho -E: jauderho@transmeta.com +E: jauderho@carumba.com +W: http://www.carumba.com/~jauderho/ D: bug toaster (A1 sauce makes all the difference) -D: Transmeta BOFH in my free time +D: Transmeta BOFH in my copius free time N: Dirk Hohndel E: hohndel@aib.com diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 23bd0ab0b348..29f6793a4642 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -3226,7 +3226,6 @@ CONFIG_SCSI_NCR53C8XX The NCR53C860 and NCR53C875 support FAST-20 transfers. The NCR53C895 supports FAST-40 transfers with Ultra2 LVD devices. Please read drivers/scsi/README.ncr53c8xx for more information. - Linux/i386 and Linux/Alpha are supported by this driver. synchronous data transfers frequency CONFIG_SCSI_NCR53C8XX_SYNC @@ -3261,17 +3260,17 @@ CONFIG_SCSI_NCR53C8XX_IOMAPPED not allow targets to disconnect CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT - This option is only provided for safety if you suspect some scsi + This option is only provided for safety if you suspect some SCSI device of yours to not support properly the target-disconnect feature. In that case, you would say Y here. In general however, to not allow targets to disconnect is not reasonable if there is more - than 1 device on a scsi bus. The normal answer therefore is N. + than 1 device on a SCSI bus. The normal answer therefore is N. default tagged command queue depth CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS This option allows you to enable tagged command queuing support at linux start-up and to define the default value for the number of - tags per device. If you donnot want tagged command queuing to be + tags per device. If you do not want tagged command queuing to be used by the driver you must enter either 0 or 1 for this option. The default value is 8 and should be supported by most hard disks. This option has no effect for adapters with NVRAM, since the driver @@ -3283,17 +3282,17 @@ CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS The normal answer therefore is to go with the default 8 and to use a boot command line option for devices that need to use a different command queue depth. - There is no safe option other than using good scsi devices. + There is no safe option other than using good SCSI devices. maximum number of queued commands CONFIG_SCSI_NCR53C8XX_MAX_TAGS This option allows you to specify the maximum number of commands that can be queued to any device, when tagged command queuing is possible. The default value is 32. Minimum is 2, maximum is 64. - For value less than 32, this option only spares a fiew memory - (8*7*(32-MAXTAGS) bytes), so using less than 32 is'nt worth it. + For value less than 32, this option only spares a few memory + (8*7*(32-MAXTAGS) bytes), so using less than 32 isn't worth it. For value greater than 32, latency on reselection will be increased - of 1 or 2 micro-seconds. So, the normal answer here is to go with the + by 1 or 2 micro-seconds. So, the normal answer here is to go with the default value 32 unless you are using very large hard disks with large cache (>= 1MB) that are able to get advantage of more than 32 tagged commands. @@ -3312,8 +3311,8 @@ CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT enable profiling statistics gathering CONFIG_SCSI_NCR53C8XX_PROFILE - This option allows you to enable profiling informations gathering. - This statististics are not very accurate due to the low frequency + This option allows you to enable profiling information gathering. + These statistics are not very accurate due to the low frequency of the kernel clock (100 Hz on i386) and have performance impact on systems that use very fast devices. The normal answer therefore is N. diff --git a/Documentation/parport.txt b/Documentation/parport.txt index 8695ba7db378..94a6318b91a7 100644 --- a/Documentation/parport.txt +++ b/Documentation/parport.txt @@ -62,6 +62,8 @@ message similar to: (If you are using kmod and have configured parport_probe as a module, this will just happen.) +The probe information is available in /proc/parport/?/autoprobe. + Parport linked into the kernel statically ========================================= @@ -103,6 +105,9 @@ File: Contents: allow you to alter it by writing a new value in (IRQ number or "none"). +/proc/parport/0/autoprobe Any IEEE-1284 device ID information + that has been acquired. + Device drivers ============== diff --git a/Documentation/tlan.txt b/Documentation/tlan.txt new file mode 100644 index 000000000000..270fb0d63fe5 --- /dev/null +++ b/Documentation/tlan.txt @@ -0,0 +1,135 @@ +TLAN driver for Linux, version 1.0 +README + +Well, I'm back. The TLAN driver seems pretty stable, so I'm +declaring this cycle of development finished, and calling the +driver 1.0. I will, of course continue to work on improving +the driver, and work towards a 2.0 release. + + + +I. Supported Devices. + + Only PCI devices will work with this driver. + + Supported: + Vendor ID Device ID Name + 0e11 ae32 Compaq Netelligent 10/100 TX PCI UTP + 0e11 ae34 Compaq Netelligent 10 T PCI UTP + 0e11 ae35 Compaq Integrated NetFlex 3/P + 0e11 ae40 Compaq Netelligent Dual 10/100 TX PCI UTP + 0e11 ae43 Compaq Netelligent Integrated 10/100 TX UTP + 0e11 b011 Compaq Netelligent 10/100 TX Embedded UTP + 0e11 b012 Compaq Netelligent 10 T/2 PCI UTP/Coax + 0e11 b030 Compaq Netelligent 10/100 TX UTP + 0e11 f130 Compaq NetFlex 3/P + 0e11 f150 Compaq NetFlex 3/P + 108d 0012 Olicom OC-2325 + 108d 0013 Olicom OC-2183 + 108d 0014 Olicom OC-2326 + + + Caveats: + + I am not sure if 100BaseTX daughterboards (for those cards which + support such things) will work. I haven't had any solid evidence + either way. + + However, if a card supports 100BaseTx without requiring an add + on daughterboard, it should work with 100BaseTx. + + The "Netelligent 10 T/2 PCI UTP/Coax" (b012) device is untested, + but I do not expect any problems. + + +II. Building the Driver. + + The TLAN driver may be compiled into the kernel, or it may be compiled + as a module separately, or in the kernel. A patch is included for + 2.0.29 (which also works for 2.0.30, 2.0.31, and 2.0.32). + + To compile it as part of the kernel: + 1. Download and untar the TLAN driver package. + 2. If your kernel is 2.1.45 or later, you do not need to patch the + kernel sources. Copy the tlan.c and tlan.h to drivers/net in + the kernel source tree. + 3. Otherwise, apply the appropriate patch for your kernel. For + example: + + cd /usr/src/linux + patch -p1 < kernel.2.0.29 + + 4. Copy the files tlan.c and tlan.h from the TLAN package to the + directory drivers/net in the Linux kernel source tree. + 5. Configure your kernel for the TLAN driver. Answer 'Y' when + prompted to ask about experimental code (the first question). + Then answer 'Y' when prompted if to include TI ThunderLAN + support. If you want the driver compiled as a module, answer 'M' + instead of 'Y'. + 6. Make the kernel and, if necessary, the modules. + + To compile the TLAN driver independently: + 1. Download and untar the TLAN driver package. + 2. Change to the tlan directory. + 3. If you are NOT using a versioned kernel (ie, want an non- + versioned module), edit the Makefile, and comment out the + line: + MODVERSIONS = -DMODVERSIONS + 4. Run 'make'. + + +III. Driver Options + 1. You can append debug=x to the end of the insmod line to get + debug messages, where x is a bit field where the bits mean + the following: + + 0x01 Turn on general debugging messages. + 0x02 Turn on receive debugging messages. + 0x04 Turn on transmit debugging messages. + 0x08 Turn on list debugging messsages. + + 2. You can append aui=1 to the end of the insmod line to cause + the adapter to use the AUI interface instead of the 10 Base T + interface. This is also what to do if you want to use the BNC + connector on a TLAN based device. (Setting this option on a + device that does not have an AUI/BNC connector will probably + cause it to not function correctly.) + + 4. You can set duplex=1 to force half duplex, and duplex=2 to + force full duplex. + + 5. You can set speed=10 to force 10Mbs operation, and speed=100Mbs + to force 100Mbs operation. (I'm not sure what will happen + if a card which only supports 10Mbs is forced into 100Mbs + mode.) + + 3. If the driver is built into the kernel, you can use the 3rd + and 4th parameters to set aui and debug respectively. For + example: + + ether=0,0,0x1,0x7,eth0 + + This sets aui to 0x1 and debug to 0x7, assuming eth0 is a + supported TLAN device. + + The bits in the third byte are assigned as follows: + + 0x01 = aui + 0x02 = use SA_INTERRUPT flag when reserving the irq. + 0x04 = use half duplex + 0x08 = use full duplex + 0x10 = use 10BaseT + 0x20 = use 100BaseTx + + +IV. Things to try if you have problems. + 1. Make sure your card's PCI id is among those listed in + section I, above. + 1. Make sure routing is correct. + 2. If you are using a 2.1.x kernel, try to duplicate the + problem on a 2.0.x (preferably 2.0.29 or 2.0.30) kernel. + + +There is also a tlan mailing list which you can join by sending "subscribe tlan" +in the body of an email to majordomo@vuser.vu.union.edu. + diff --git a/MAINTAINERS b/MAINTAINERS index 702819dcd61a..c29f8a85c84b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -589,9 +589,9 @@ S: Maintained TLAN NETWORK DRIVER P: James Banks -M: james.banks@caldera.com -L: linux-net@vger.rutgers.edu -S: Supported +M: james@sovereign.org +L: tlan@vuser.vu.union.edu +S: Maintained TOKEN-RING NETWORK DRIVER P: Paul Norton diff --git a/Makefile b/Makefile index 069d4abdd108..2e4d439d1196 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ HPATH = $(TOPDIR)/include FINDHPATH = $(HPATH)/asm $(HPATH)/linux $(HPATH)/scsi $(HPATH)/net HOSTCC =gcc -HOSTCFLAGS =-O2 -fomit-frame-pointer +HOSTCFLAGS =-Wall -Wstrict-prototypes -O2 -fomit-frame-pointer CROSS_COMPILE = @@ -159,22 +159,11 @@ endif include arch/$(ARCH)/Makefile -ifdef SMP - .S.s: $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -E -o $*.s $< .S.o: $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c -o $*.o $< -else - -.S.s: - $(CC) -D__ASSEMBLY__ -traditional -E -o $*.s $< -.S.o: - $(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $< - -endif - Version: dummy @rm -f include/linux/compile.h diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile index 8de9f7153d0b..77dde66141f3 100644 --- a/arch/alpha/Makefile +++ b/arch/alpha/Makefile @@ -29,13 +29,18 @@ CFLAGS := $(CFLAGS) -mno-fp-regs -ffixed-8 # determine if we can use the BWX instructions with GAS OLD_GAS := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi) -# if PYXIS, then enable use of BWIO space +# If PYXIS, then enable use of BWIO space ifneq ($(OLD_GAS),y) ifeq ($(CONFIG_ALPHA_PYXIS),y) CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED endif endif +# If EV6, turn on the proper optimizations. +ifeq ($(CONFIG_ALPHA_EV6),y) + CFLAGS := -mcpu=ev6 $(CFLAGS) +endif + HEAD := arch/alpha/kernel/head.o SUBDIRS := $(SUBDIRS) arch/alpha/kernel arch/alpha/mm arch/alpha/lib \ diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig index 7d78e4b973cc..c8fd68be795a 100644 --- a/arch/alpha/defconfig +++ b/arch/alpha/defconfig @@ -47,10 +47,11 @@ CONFIG_ALPHA_EV5=y CONFIG_ALPHA_CIA=y CONFIG_ALPHA_SRM=y CONFIG_ALPHA_EISA=y -CONFIG_TGA_CONSOLE=y +# CONFIG_PCI_QUIRKS is not set CONFIG_PCI_OLD_PROC=y CONFIG_NET=y CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y @@ -64,7 +65,7 @@ CONFIG_BINFMT_EM86=y # CONFIG_PNP is not set # -# Floppy, IDE, and other block devices +# Block devices # CONFIG_BLK_DEV_FD=y # CONFIG_BLK_DEV_IDE is not set @@ -78,6 +79,7 @@ CONFIG_BLK_DEV_FD=y # Additional Block Devices # # CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_XD is not set @@ -98,8 +100,6 @@ CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set # CONFIG_IP_PNP is not set -# CONFIG_IP_ACCT is not set -# CONFIG_IP_MASQUERADE is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set @@ -195,6 +195,7 @@ CONFIG_DE4X5=y # CONFIG_DEC_ELCP is not set # CONFIG_DGRS is not set # CONFIG_EEXPRESS_PRO100 is not set +# CONFIG_NE2K_PCI is not set # CONFIG_NET_POCKET is not set # CONFIG_FDDI is not set # CONFIG_DLCI is not set @@ -282,6 +283,12 @@ CONFIG_PSMOUSE=y # # CONFIG_FTAPE is not set +# +# Console drivers +# +CONFIG_VGA_CONSOLE=y +# CONFIG_FB is not set + # # Sound # diff --git a/arch/alpha/kernel/bios32.c b/arch/alpha/kernel/bios32.c index 47f53a2f6cf2..e2a04324b5c8 100644 --- a/arch/alpha/kernel/bios32.c +++ b/arch/alpha/kernel/bios32.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #if 0 @@ -39,24 +41,11 @@ #ifndef CONFIG_PCI -int pcibios_present(void) -{ - return 0; -} - -asmlinkage int sys_pciconfig_read() -{ - return -ENOSYS; -} - -asmlinkage int sys_pciconfig_write() -{ - return -ENOSYS; -} +asmlinkage int sys_pciconfig_read() { return -ENOSYS; } +asmlinkage int sys_pciconfig_write() { return -ENOSYS; } #else /* CONFIG_PCI */ -#include #include #include @@ -82,17 +71,19 @@ asmlinkage int sys_pciconfig_write() #define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1)) -#if defined(CONFIG_ALPHA_MCPCIA) || defined(CONFIG_ALPHA_TSUNAMI) -/* multiple PCI bus machines */ -/* make handle from bus number */ +/* + * On multiple PCI bus machines, create a handle from the bus number. + */ +#if defined(CONFIG_ALPHA_MCPCIA) /* || defined(CONFIG_ALPHA_TSUNAMI) */ extern struct linux_hose_info *bus2hose[256]; #define HANDLE(b) (((unsigned long)(bus2hose[(b)]->pci_hose_index)&3)<<32) #define DEV_IS_ON_PRIMARY(dev) \ (bus2hose[(dev)->bus->number]->pci_first_busno == (dev)->bus->number) -#else /* MCPCIA || TSUNAMI */ +#else #define HANDLE(b) (0) #define DEV_IS_ON_PRIMARY(dev) ((dev)->bus->number == 0) -#endif /* MCPCIA || TSUNAMI */ +#endif + /* * PCI_MODIFY * @@ -2199,7 +2190,6 @@ __initfunc(char *pcibios_setup(char *str)) #ifdef CONFIG_ALPHA_SRM_SETUP void reset_for_srm(void) { - extern void scrreset(void); struct pci_dev *dev; int i; @@ -2230,9 +2220,7 @@ void reset_for_srm(void) io_to_reset[i]); #endif } - - /* reset the visible screen to the top of display memory */ - scrreset(); + /* FIXME: reset the video origin. */ } #endif /* CONFIG_ALPHA_SRM_SETUP */ diff --git a/arch/alpha/kernel/mcpcia.c b/arch/alpha/kernel/mcpcia.c index f8bdcca69176..e88526fb8508 100644 --- a/arch/alpha/kernel/mcpcia.c +++ b/arch/alpha/kernel/mcpcia.c @@ -9,13 +9,13 @@ #include #include #include +#include #include #include #include #include #include -#include /* * NOTE: Herein lie back-to-back mb instructions. They are magic. @@ -921,8 +921,7 @@ DBG_PCI(("mcpcia_fixup_busno: hose %d startbus %d nbus %d\n", } while (nbus-- > 0); } -static void mcpcia_probe(struct linux_hose_info *hose, - unsigned long *mem_start) +static void mcpcia_probe(struct linux_hose_info *hose) { static struct pci_bus *pchain = NULL; struct pci_bus *pbus = &hose->pci_bus; @@ -939,7 +938,7 @@ static void mcpcia_probe(struct linux_hose_info *hose, mcpcia_fixup_busno(hose, busno); - pbus->subordinate = pci_scan_bus(pbus, mem_start); /* the original! */ + pbus->subordinate = pci_scan_bus(pbus); /* the original! */ /* * Set the maximum subordinate bus of this hose. @@ -970,8 +969,7 @@ void mcpcia_fixup(void) pci_probe_enabled = 1; /* for each hose, probe and setup the devices on the hose */ - for (hose = mcpcia_root; hose; hose = hose->next) { - mcpcia_probe(hose, &memory_start); - } + for (hose = mcpcia_root; hose; hose = hose->next) + mcpcia_probe(hose); } #endif /* CONFIG_ALPHA_MCPCIA */ diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 168b8fbb10c2..dc49826d4006 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -761,7 +761,7 @@ asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss) } if (uss) { - unsigned long ss_sp; + void *ss_sp; error = -EFAULT; if (get_user(ss_sp, &uss->ss_sp)) @@ -776,7 +776,7 @@ asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss) /* Since we don't know the extent of the stack, and we don't track onstack-ness, but rather calculate it, we must presume a size. Ho hum this interface is lossy. */ - current->sas_ss_sp = ss_sp - SIGSTKSZ; + current->sas_ss_sp = (unsigned long)ss_sp - SIGSTKSZ; current->sas_ss_size = SIGSTKSZ; } diff --git a/arch/alpha/lib/io.c b/arch/alpha/lib/io.c index 405a3afa859f..7c99fe5aea18 100644 --- a/arch/alpha/lib/io.c +++ b/arch/alpha/lib/io.c @@ -3,7 +3,7 @@ * files.. */ #include - +#include #include /* @@ -70,6 +70,10 @@ unsigned long _readl(unsigned long addr) return __readl(addr); } +unsigned long _readq(unsigned long addr) +{ + return __readq(addr); +} void _writeb(unsigned char b, unsigned long addr) { @@ -86,6 +90,11 @@ void _writel(unsigned int b, unsigned long addr) __writel(b, addr); } +void _writeq(unsigned long b, unsigned long addr) +{ + __writeq(b, addr); +} + /* * Read COUNT 8-bit bytes from port PORT into memory starting at * SRC. @@ -363,12 +372,48 @@ void outsl (unsigned long port, const void *src, unsigned long count) * Copy data from IO memory space to "real" memory space. * This needs to be optimized. */ -void _memcpy_fromio(void * to, unsigned long from, unsigned long count) +void _memcpy_fromio(void * to, unsigned long from, long count) { - while (count) { + /* Optimize co-aligned transfers. Everything else gets handled + a byte at a time. */ + + if (count >= 8 && ((long)to & 7) == (from & 7)) { + count -= 8; + do { + *(u64 *)to = readq(from); + count -= 8; + to += 8; + from += 8; + } while (count >= 0); + count += 8; + } + + if (count >= 4 && ((long)to & 3) == (from & 3)) { + count -= 4; + do { + *(u32 *)to = readl(from); + count -= 4; + to += 4; + from += 4; + } while (count >= 0); + count += 4; + } + + if (count >= 2 && ((long)to & 1) == (from & 1)) { + count -= 2; + do { + *(u16 *)to = readw(from); + count -= 2; + to += 2; + from += 2; + } while (count >= 0); + count += 2; + } + + while (count > 0) { + *(u8 *) to = readb(from); count--; - *(char *) to = readb(from); - ((char *) to)++; + to++; from++; } } @@ -377,13 +422,49 @@ void _memcpy_fromio(void * to, unsigned long from, unsigned long count) * Copy data from "real" memory space to IO memory space. * This needs to be optimized. */ -void _memcpy_toio(unsigned long to, void * from, unsigned long count) +void _memcpy_toio(unsigned long to, void * from, long count) { - while (count) { + /* Optimize co-aligned transfers. Everything else gets handled + a byte at a time. */ + + if (count >= 8 && (to & 7) == ((long)from & 7)) { + count -= 8; + do { + writeq(*(u64 *)from, to); + count -= 8; + to += 8; + from += 8; + } while (count >= 0); + count += 8; + } + + if (count >= 4 && (to & 3) == ((long)from & 3)) { + count -= 4; + do { + writel(*(u32 *)from, to); + count -= 4; + to += 4; + from += 4; + } while (count >= 0); + count += 4; + } + + if (count >= 2 && (to & 1) == ((long)from & 1)) { + count -= 2; + do { + writew(*(u16 *)from, to); + count -= 2; + to += 2; + from += 2; + } while (count >= 0); + count += 2; + } + + while (count > 0) { + writeb(*(u8 *) from, to); count--; - writeb(*(char *) from, to); - ((char *) from)++; to++; + from++; } } @@ -391,11 +472,45 @@ void _memcpy_toio(unsigned long to, void * from, unsigned long count) * "memset" on IO memory space. * This needs to be optimized. */ -void _memset_io(unsigned long dst, int c, unsigned long count) +void _memset_c_io(unsigned long to, unsigned long c, long count) { - while (count) { + if (count > 0 && (to & 1)) { + writeb(c, to); + to++; + count--; + } + if (count >= 2 && (to & 2)) { + writew(c, to); + to += 2; + count -= 2; + } + if (count >= 4 && (to & 4)) { + writel(c, to); + to += 4; + count -= 4; + } + if ((to & 7) == 0) { + count -= 8; + while (count >= 0) { + writeq(c, to); + to += 8; + count -= 8; + } + count += 8; + } + if (count >= 4 && (to & 4)) { + writel(c, to); + to += 4; + count -= 4; + } + if (count >= 2 && (to & 2)) { + writew(c, to); + to += 2; + count -= 2; + } + while (count > 0) { + writeb(c, to); count--; - writeb(c, dst); - dst++; + to++; } } diff --git a/arch/alpha/lib/memset.S b/arch/alpha/lib/memset.S index dc2075e1f920..f39197deed04 100644 --- a/arch/alpha/lib/memset.S +++ b/arch/alpha/lib/memset.S @@ -18,6 +18,7 @@ .set noreorder .text .globl __memset + .globl __memsetw .globl __constant_c_memset .ent __memset .align 5 @@ -25,8 +26,8 @@ __memset: .frame $30,0,$26,0 .prologue 0 - zapnot $17,1,$17 /* E0 */ - sll $17,8,$1 /* E1 (p-c latency, next cycle) */ + and $17,255,$1 /* E1 */ + insbl $17,1,$17 /* .. E0 */ bis $17,$1,$17 /* E0 (p-c latency, next cycle) */ sll $17,16,$1 /* E1 (p-c latency, next cycle) */ @@ -52,9 +53,9 @@ __constant_c_memset: insql $17,$16,$2 /* E0 */ subq $3,8,$3 /* .. E1 */ - addq $18,$3,$18 /* E0 $18 is new count ($3 is negative) */ + addq $18,$3,$18 /* E0 $18 is new count ($3 is negative) */ mskql $4,$16,$4 /* .. E1 (and possible load stall) */ - subq $16,$3,$16 /* E0 $16 is new aligned destination */ + subq $16,$3,$16 /* E0 $16 is new aligned destination */ bis $2,$4,$1 /* .. E1 */ bis $31,$31,$31 /* E0 */ @@ -103,6 +104,22 @@ end: ret $31,($26),1 /* E1 */ .end __memset + .align 5 + .ent __memsetw +__memsetw: + .prologue 0 + + inswl $17,0,$1 /* E0 */ + inswl $17,2,$2 /* E0 */ + inswl $17,4,$3 /* E0 */ + or $1,$2,$1 /* .. E1 */ + inswl $17,6,$4 /* E0 */ + or $1,$3,$1 /* .. E1 */ + or $1,$4,$17 /* E0 */ + br __constant_c_memset /* .. E1 */ + + .end __memsetw + #ifdef __ELF__ .weak memset; memset = __memset #else diff --git a/arch/alpha/math-emu/fp-emul.c b/arch/alpha/math-emu/fp-emul.c index 543044019b26..b3c10887b4ca 100644 --- a/arch/alpha/math-emu/fp-emul.c +++ b/arch/alpha/math-emu/fp-emul.c @@ -76,6 +76,7 @@ void cleanup_module(void) alpha_fp_emul_imprecise = save_emul; } +#undef alpha_fp_emul_imprecise #define alpha_fp_emul_imprecise do_alpha_fp_emul_imprecise #endif /* MODULE */ diff --git a/arch/arm/mm/mm-ebsa285.c b/arch/arm/mm/mm-ebsa285.c index ec635b1e73df..82bbce899dbf 100644 --- a/arch/arm/mm/mm-ebsa285.c +++ b/arch/arm/mm/mm-ebsa285.c @@ -5,6 +5,7 @@ * * Copyright (C) 1998 Russell King, Dave Gilbert. */ +#include #include #include #include diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 9126a390c866..3e5c4e7ffc9a 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -13,10 +13,6 @@ # Copyright (C) 1994 by Linus Torvalds # -AS86 =$(CROSS_COMPILE)as86 -0 -a -AS386 =$(CROSS_COMPILE)as86 -3 -LD86 =$(CROSS_COMPILE)ld86 -0 - LD=$(CROSS_COMPILE)ld -m elf_i386 CPP=$(CC) -E OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S @@ -43,10 +39,6 @@ ifdef CONFIG_M686 CFLAGS := $(CFLAGS) -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=686 endif -ifdef SMP -CFLAGS := $(CFLAGS) -D__SMP__ -endif - HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o SUBDIRS := $(SUBDIRS) arch/i386/kernel arch/i386/mm arch/i386/lib diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile index c876022cdbfd..ff26d087c4c5 100644 --- a/arch/i386/boot/Makefile +++ b/arch/i386/boot/Makefile @@ -8,9 +8,8 @@ # Copyright (C) 1994 by Linus Torvalds # -ifdef SMP -HOSTCFLAGS := $(HOSTCFLAGS) -D__SMP__ -endif +AS86 =$(CROSS_COMPILE)as86 -0 -a +LD86 =$(CROSS_COMPILE)ld86 -0 BOOT_INCL = $(TOPDIR)/include/linux/config.h \ $(TOPDIR)/include/linux/autoconf.h \ diff --git a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile index 770c563ece8c..6a3fda06dcc7 100644 --- a/arch/i386/boot/compressed/Makefile +++ b/arch/i386/boot/compressed/Makefile @@ -22,10 +22,6 @@ BZIMAGE_OFFSET = 0x100000 ZLINKFLAGS = -Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS) BZLINKFLAGS = -Ttext $(BZIMAGE_OFFSET) $(ZLDFLAGS) -ifdef SMP -CFLAGS := $(CFLAGS) -D__SMP__ -endif - all: vmlinux vmlinux: piggy.o $(OBJECTS) @@ -34,18 +30,8 @@ vmlinux: piggy.o $(OBJECTS) bvmlinux: piggy.o $(OBJECTS) $(LD) $(BZLINKFLAGS) -o bvmlinux $(OBJECTS) piggy.o -ifdef SMP - head.o: head.S $(TOPDIR)/include/linux/tasks.h - $(CC) -D__SMP__ -traditional -c head.S - -else - -head.o: head.S $(TOPDIR)/include/linux/tasks.h - $(CC) -traditional -c head.S - -endif - + $(CC) $(AFLAGS) -traditional -c head.S piggy.o: $(SYSTEM) tmppiggy=_tmp_$$$$piggy; \ diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 6f63d2c9714b..917e7abdfe7b 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -7,13 +7,8 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... -ifdef SMP .S.o: $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o -else -.S.o: - $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o -endif all: kernel.o head.o init_task.o @@ -39,19 +34,11 @@ else endif endif - ifdef SMP - O_OBJS += io_apic.o smp.o trampoline.o +endif head.o: head.S $(TOPDIR)/include/linux/tasks.h - $(CC) -D__ASSEMBLY__ -D__SMP__ -traditional -c $*.S -o $*.o - -else - -head.o: head.S $(TOPDIR)/include/linux/tasks.h - $(CC) -D__ASSEMBLY__ -traditional -c $*.S -o $*.o - -endif + $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o include $(TOPDIR)/Rules.make diff --git a/arch/i386/kernel/bios32.c b/arch/i386/kernel/bios32.c index 0c7e692a481c..cca619790b72 100644 --- a/arch/i386/kernel/bios32.c +++ b/arch/i386/kernel/bios32.c @@ -967,18 +967,24 @@ __initfunc(void pcibios_fixup_devices(void)) } else if (a & PCI_BASE_ADDRESS_MEM_MASK) has_mem = 1; } - pci_read_config_word(dev, PCI_COMMAND, &cmd); - if (has_io && !(cmd & PCI_COMMAND_IO)) { - printk("PCI: Enabling I/O for device %02x:%02x\n", - dev->bus->number, dev->devfn); - cmd |= PCI_COMMAND_IO; - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) { - printk("PCI: Enabling memory for device %02x:%02x\n", - dev->bus->number, dev->devfn); - cmd |= PCI_COMMAND_MEMORY; - pci_write_config_word(dev, PCI_COMMAND, cmd); + /* + * Don't enable VGA-compatible cards since they have + * fixed I/O and memory space. + */ + if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + if (has_io && !(cmd & PCI_COMMAND_IO)) { + printk("PCI: Enabling I/O for device %02x:%02x\n", + dev->bus->number, dev->devfn); + cmd |= PCI_COMMAND_IO; + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) { + printk("PCI: Enabling memory for device %02x:%02x\n", + dev->bus->number, dev->devfn); + cmd |= PCI_COMMAND_MEMORY; + pci_write_config_word(dev, PCI_COMMAND, cmd); + } } #ifdef __SMP__ /* diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile index a4e4b1486b5d..1776bab98f03 100644 --- a/arch/i386/lib/Makefile +++ b/arch/i386/lib/Makefile @@ -2,13 +2,8 @@ # Makefile for i386-specific library files.. # -ifdef SMP .S.o: $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o -else -.S.o: - $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o -endif L_TARGET = lib.a L_OBJS = checksum.o semaphore.o locks.o delay.o usercopy.o getuser.o putuser.o diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 53ed6d340db4..a6c2c54db1cc 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -7,24 +7,12 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... -ifdef SMP - .S.s: $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s .S.o: $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o -else - -.S.s: - $(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s - -.S.o: - $(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o - -endif - all: kernel.o head.o init_task.o O_TARGET := kernel.o @@ -46,18 +34,9 @@ ifdef CONFIG_SUN_AUXIO O_OBJS += auxio.o endif -ifdef SMP - head.o: head.S $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $*.S -o $*.o -else - -head.o: head.S - $(CC) -D__ASSEMBLY__ -ansi -c $*.S -o $*.o - -endif - check_asm: dummy @echo "/* Automatically generated. Do not edit. */" > asm_offsets.h @echo "#ifndef __ASM_OFFSETS_H__" >> asm_offsets.h diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index 6ec986c86bf4..6183d9f4bc89 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile @@ -45,8 +45,6 @@ blockops.o: blockops.S memset.o: memset.S $(CC) -D__ASSEMBLY__ -ansi -c -o memset.o memset.S -ifdef SMP - locks.o: locks.S $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o locks.o locks.S @@ -56,20 +54,9 @@ atomic.o: atomic.S bitops.o: bitops.S $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o bitops.o bitops.S +ifdef SMP irqlock.o: irqlock.S $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o irqlock.o irqlock.S - -else - -locks.o: locks.S - $(CC) -D__ASSEMBLY__ -ansi -c -o locks.o locks.S - -atomic.o: atomic.S - $(CC) -D__ASSEMBLY__ -ansi -c -o atomic.o atomic.S - -bitops.o: bitops.S - $(CC) -D__ASSEMBLY__ -ansi -c -o bitops.o bitops.S - endif strlen.o: strlen.S diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile index 18eeb1f52c3d..4d3f3735ffa8 100644 --- a/arch/sparc/mm/Makefile +++ b/arch/sparc/mm/Makefile @@ -22,8 +22,6 @@ endif include $(TOPDIR)/Rules.make -ifdef SMP - hypersparc.o: hypersparc.S $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o hypersparc.o hypersparc.S @@ -35,19 +33,3 @@ viking.o: viking.S tsunami.o: tsunami.S $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o tsunami.o tsunami.S - -else - -hypersparc.o: hypersparc.S - $(CC) -D__ASSEMBLY__ -ansi -c -o hypersparc.o hypersparc.S - -turbosparc.o: turbosparc.S - $(CC) -D__ASSEMBLY__ -ansi -c -o turbosparc.o turbosparc.S - -viking.o: viking.S - $(CC) -D__ASSEMBLY__ -ansi -c -o viking.o viking.S - -tsunami.o: tsunami.S - $(CC) -D__ASSEMBLY__ -ansi -c -o tsunami.o tsunami.S - -endif diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 1c3f459bc5c2..f80d14ca11a7 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -7,24 +7,12 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... -ifdef SMP - .S.s: $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s .S.o: $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o -else - -.S.s: - $(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s - -.S.o: - $(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o - -endif - all: kernel.o head.o init_task.o O_TARGET := kernel.o diff --git a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile index 72f4fa07937b..781ad5afc967 100644 --- a/arch/sparc64/mm/Makefile +++ b/arch/sparc64/mm/Makefile @@ -7,24 +7,12 @@ # # Note 2! The CFLAGS definition is now in the main makefile... -ifdef SMP - .S.s: $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s .S.o: $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o -else - -.S.s: - $(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s - -.S.o: - $(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o - -endif - O_TARGET := mm.o O_OBJS := ultra.o fault.o init.o generic.o asyncd.o extable.o modutil.o diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 3255710d4375..912d6d6ec849 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -451,7 +451,7 @@ include $(TOPDIR)/Rules.make fastdep: conmakehash: conmakehash.c - $(HOSTCC) -o conmakehash conmakehash.c + $(HOSTCC) $(HOSTCFLAGS) -o conmakehash conmakehash.c consolemap_deftbl.c: $(FONTMAPFILE) conmakehash ./conmakehash $(FONTMAPFILE) > consolemap_deftbl.c diff --git a/drivers/char/h8.c b/drivers/char/h8.c index 12d90ebeef85..2876982986d2 100644 --- a/drivers/char/h8.c +++ b/drivers/char/h8.c @@ -1,5 +1,3 @@ -/* - */ /* * Hitachi H8/337 Microcontroller driver * @@ -27,6 +25,7 @@ #include #include #include +#include #define __KERNEL_SYSCALLS__ #include @@ -55,12 +54,6 @@ int h8_init(void); int h8_display_blank(void); int h8_display_unblank(void); -static int h8_open(struct inode *, struct file *); -static void h8_release(struct inode *, struct file *); -static long h8_read(struct inode *, struct file *, char *, u_long); -static int h8_select(struct inode *, struct file *, int, select_table *); -static int h8_ioctl(struct inode *, struct file *, u_int, u_long); - static void h8_intr(int irq, void *dev_id, struct pt_regs *regs); #ifdef CONFIG_PROC_FS @@ -113,14 +106,14 @@ static char driver_version[] = "X0.0";/* no spaces */ static struct file_operations h8_fops = { NULL, /* lseek */ - h8_read, + NULL, NULL, /* write */ NULL, /* readdir */ - h8_select, - h8_ioctl, + NULL, + NULL, NULL, /* mmap */ - h8_open, - h8_release, + NULL, + NULL, NULL, /* fsync */ NULL /* fasync */ }; @@ -328,7 +321,7 @@ int init_module(void) request_region(h8_base, 8, "h8"); #ifdef CONFIG_PROC_FS - proc_register_dynamic(&proc_root, &h8_proc_entry); + proc_register(&proc_root, &h8_proc_entry); #endif QUEUE_INIT(&h8_actq, link, h8_cmd_q_t *); @@ -362,7 +355,7 @@ int h8_init(void) printk("H8 at 0x%x IRQ %d\n", h8_base, h8_irq); #ifdef CONFIG_PROC_FS - proc_register_dynamic(&proc_root, &h8_proc_entry); + proc_register(&proc_root, &h8_proc_entry); #endif misc_register(&h8_device); @@ -439,38 +432,6 @@ int h8_get_info(char *buf, char **start, off_t fpos, int length, int dummy) } #endif -static long h8_read(struct inode *inode, struct file *fp, char *buf, - u_long count) -{ - printk("h8_read: IMPDEL\n"); - return 0; -} - -static int h8_select(struct inode *inode, struct file *fp, int sel_type, - select_table * wait) -{ - printk("h8_select: IMPDEL\n"); - return 0; -} - -static int h8_ioctl(struct inode * inode, struct file *filp, - u_int cmd, u_long arg) -{ - printk("h8_ioctl: IMPDEL\n"); - return 0; -} - -static void h8_release(struct inode * inode, struct file * filp) -{ - printk("h8_release: IMPDEL\n"); -} - -static int h8_open(struct inode * inode, struct file * filp) -{ - printk("h8_open: IMPDEL\n"); - return 0; -} - /* Called from console driver -- must make sure h8_enabled. */ int h8_display_blank(void) { diff --git a/drivers/char/hfmodem/Makefile b/drivers/char/hfmodem/Makefile index 42629693bcbb..2219cd52e570 100644 --- a/drivers/char/hfmodem/Makefile +++ b/drivers/char/hfmodem/Makefile @@ -25,7 +25,7 @@ all: all_targets .PHONY: all gentbl: gentbl.c - $(HOSTCC) -Wall $< -o $@ -lm + $(HOSTCC) $(HOSTCFLAGS) $< -o $@ -lm TBLHDR := tables.h diff --git a/drivers/char/i2c.c b/drivers/char/i2c.c index ad8f0fe95080..089f27adedef 100644 --- a/drivers/char/i2c.c +++ b/drivers/char/i2c.c @@ -5,6 +5,7 @@ * */ +#include #include #include #include diff --git a/drivers/char/mem.c b/drivers/char/mem.c index d2f51af82dbe..fec1c9d61d8c 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -266,12 +266,15 @@ static inline size_t read_zero_pagealigned(char * buf, size_t size) struct vm_area_struct * vma; unsigned long addr=(unsigned long)buf; + /* Oops, this was forgotten before. -ben */ + down(¤t->mm->mmap_sem); + /* For private mappings, just map in zero pages. */ for (vma = find_vma(current->mm, addr); vma; vma = vma->vm_next) { unsigned long count; if (vma->vm_start > addr || (vma->vm_flags & VM_WRITE) == 0) - return size; + goto out_up; if (vma->vm_flags & VM_SHARED) break; count = vma->vm_end - addr; @@ -279,16 +282,18 @@ static inline size_t read_zero_pagealigned(char * buf, size_t size) count = size; flush_cache_range(current->mm, addr, addr + count); - zap_page_range(current->mm, addr, count); - zeromap_page_range(addr, count, PAGE_COPY); + zap_page_range(vma, addr, count); + zeromap_page_range(vma, addr, count, PAGE_COPY); flush_tlb_range(current->mm, addr, addr + count); size -= count; buf += count; addr += count; if (size == 0) - return 0; + goto out_up; } + + up(¤t->mm->mmap_sem); /* The shared case is hard. Let's do the conventional zeroing. */ do { @@ -301,6 +306,9 @@ static inline size_t read_zero_pagealigned(char * buf, size_t size) size -= PAGE_SIZE; } while (size); + return size; +out_up: + up(¤t->mm->mmap_sem); return size; } diff --git a/drivers/misc/parport_procfs.c b/drivers/misc/parport_procfs.c index 09d6ebdda13b..7e097c8a41b6 100644 --- a/drivers/misc/parport_procfs.c +++ b/drivers/misc/parport_procfs.c @@ -175,6 +175,33 @@ static int hardware_read_proc(char *page, char **start, off_t off, return len; } +static int autoprobe_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct parport *pp = (struct parport *) data; + int len = 0; + const char *str; + + if ((str = pp->probe_info.class_name) != NULL) + len += sprintf (page+len, "CLASS:%s;\n", str); + + if ((str = pp->probe_info.model) != NULL) + len += sprintf (page+len, "MODEL:%s;\n", str); + + if ((str = pp->probe_info.mfr) != NULL) + len += sprintf (page+len, "MANUFACTURER:%s;\n", str); + + if ((str = pp->probe_info.description) != NULL) + len += sprintf (page+len, "DESCRIPTION:%s;\n", str); + + if ((str = pp->probe_info.cmdset) != NULL) + len += sprintf (page+len, "COMMAND SET:%s;\n", str); + + *start = 0; + *eof = 1; + return strlen (page); +} + static inline void destroy_proc_entry(struct proc_dir_entry *root, struct proc_dir_entry **d) { @@ -314,6 +341,13 @@ int parport_proc_register(struct parport *pp) pp->pdir.hardware->read_proc = hardware_read_proc; pp->pdir.hardware->data = pp; + pp->pdir.probe = new_proc_entry("autoprobe", 0, pp->pdir.entry, 0, pp); + if (pp->pdir.probe == NULL) + goto out_fail; + + pp->pdir.probe->read_proc = autoprobe_read_proc; + pp->pdir.probe->data = pp; + return 0; out_fail: diff --git a/drivers/misc/parport_share.c b/drivers/misc/parport_share.c index b427b14f21b2..cde81f028e8f 100644 --- a/drivers/misc/parport_share.c +++ b/drivers/misc/parport_share.c @@ -37,6 +37,7 @@ #define PARPORT_DEFAULT_TIMESLICE (HZ/5) static struct parport *portlist = NULL, *portlist_tail = NULL; +spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED; void (*parport_probe_hook)(struct parport *port) = NULL; @@ -45,9 +46,7 @@ struct parport *parport_enumerate(void) { #ifdef CONFIG_KMOD if (portlist == NULL) { -#if defined(CONFIG_PARPORT_PC_MODULE) || defined(CONFIG_PARPORT_AX_MODULE) || defined(CONFIG_PARPORT_ARC_MODULE) request_module("parport_lowlevel"); -#endif /* CONFIG_PARPORT_LOWLEVEL_MODULE */ #ifdef CONFIG_PNP_PARPORT_MODULE request_module("parport_probe"); #endif /* CONFIG_PNP_PARPORT_MODULE */ @@ -67,6 +66,8 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, { struct parport *tmp; int portnum; + char *name; + unsigned long flags; /* Check for a previously registered port. NOTE: we will ignore irq and dma if we find a previously @@ -109,22 +110,26 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, tmp->flags = 0; tmp->ops = ops; tmp->number = portnum; + memset (&tmp->probe_info, 0, sizeof (struct parport_device_info)); spin_lock_init (&tmp->lock); - tmp->name = kmalloc(15, GFP_KERNEL); - if (!tmp->name) { + name = kmalloc(15, GFP_KERNEL); + if (!name) { printk(KERN_ERR "parport: memory squeeze\n"); kfree(tmp); return NULL; } - sprintf(tmp->name, "parport%d", portnum); + sprintf(name, "parport%d", portnum); + tmp->name = name; /* Chain the entry to our list. */ + spin_lock_irqsave (&parportlist_lock, flags); if (portlist_tail) portlist_tail->next = tmp; portlist_tail = tmp; if (!portlist) portlist = tmp; + spin_unlock_irqrestore (&parportlist_lock, flags); tmp->probe_info.class = PARPORT_CLASS_LEGACY; /* assume the worst */ tmp->waithead = tmp->waittail = NULL; @@ -135,7 +140,8 @@ struct parport *parport_register_port(unsigned long base, int irq, int dma, void parport_unregister_port(struct parport *port) { struct parport *p; - kfree(port->name); + unsigned long flags; + spin_lock_irqsave (&parportlist_lock, flags); if (portlist == port) { if ((portlist = port->next) == NULL) portlist_tail = NULL; @@ -146,19 +152,35 @@ void parport_unregister_port(struct parport *port) if ((p->next = port->next) == NULL) portlist_tail = p; } + else printk (KERN_WARNING + "%s not found in port list!\n", port->name); } + spin_unlock_irqrestore (&parportlist_lock, flags); + if (p->probe_info.class_name) + kfree (p->probe_info.class_name); + if (p->probe_info.mfr) + kfree (p->probe_info.mfr); + if (p->probe_info.model) + kfree (p->probe_info.model); + if (p->probe_info.cmdset) + kfree (p->probe_info.cmdset); + if (p->probe_info.description) + kfree (p->probe_info.description); + kfree(port->name); kfree(port); } void parport_quiesce(struct parport *port) { if (port->devices) { - printk(KERN_WARNING "%s: attempt to quiesce active port.\n", port->name); + printk(KERN_WARNING "%s: attempt to quiesce active port.\n", + port->name); return; } if (port->flags & PARPORT_FLAG_COMA) { - printk(KERN_WARNING "%s: attempt to quiesce comatose port.\n", port->name); + printk(KERN_WARNING "%s: attempt to quiesce comatose port.\n", + port->name); return; } @@ -173,6 +195,7 @@ struct pardevice *parport_register_device(struct parport *port, const char *name int flags, void *handle) { struct pardevice *tmp; + unsigned long flgs; if (flags & PARPORT_DEV_LURK) { if (!pf || !kf) { @@ -181,15 +204,6 @@ struct pardevice *parport_register_device(struct parport *port, const char *name } } - /* We may need to claw back the port hardware. */ - if (port->flags & PARPORT_FLAG_COMA) { - if (port->ops->claim_resources(port)) { - printk(KERN_WARNING "%s: unable to get hardware to register %s.\n", port->name, name); - return NULL; - } - port->flags &= ~PARPORT_FLAG_COMA; - } - tmp = kmalloc(sizeof(struct pardevice), GFP_KERNEL); if (tmp == NULL) { printk(KERN_WARNING "%s: memory squeeze, couldn't register %s.\n", port->name, name); @@ -203,7 +217,20 @@ struct pardevice *parport_register_device(struct parport *port, const char *name return NULL; } - tmp->name = (char *) name; + /* We may need to claw back the port hardware. */ + if (port->flags & PARPORT_FLAG_COMA) { + if (port->ops->claim_resources(port)) { + printk(KERN_WARNING + "%s: unable to get hardware to register %s.\n", + port->name, name); + kfree (tmp->state); + kfree (tmp); + return NULL; + } + port->flags &= ~PARPORT_FLAG_COMA; + } + + tmp->name = name; tmp->port = port; tmp->preempt = pf; tmp->wakeup = kf; @@ -215,10 +242,12 @@ struct pardevice *parport_register_device(struct parport *port, const char *name /* Chain this onto the list */ tmp->prev = NULL; + spin_lock_irqsave (&port->lock, flgs); tmp->next = port->devices; if (port->devices) port->devices->prev = tmp; port->devices = tmp; + spin_unlock_irqrestore (&port->lock, flgs); inc_parport_count(); port->ops->inc_use_count(); @@ -286,7 +315,7 @@ int parport_claim(struct pardevice *dev) try_again: /* Preempt any current device */ - if ((oldcad = port->cad)) { + if ((oldcad = port->cad) != NULL) { if (oldcad->preempt) { if (oldcad->preempt(oldcad->private)) goto blocked; @@ -439,7 +468,7 @@ void parport_release(struct pardevice *dev) /* If anybody is waiting, find out who's been there longest and then wake them up. (Note: no locking required) */ for (pd = port->waithead; pd; pd = pd->waitnext) { - if (pd->waiting & 2) { + if (pd->waiting & 2) { /* sleeping in claim_or_block */ parport_claim(pd); if (waitqueue_active(&pd->wait_q)) wake_up(&pd->wait_q); diff --git a/drivers/net/8390.c b/drivers/net/8390.c index f6ef665192f2..e00094f4517d 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -238,7 +238,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev) else { /* We should never get here. */ if (ei_debug) - printk(KERN_DEBUG "%s: No Tx buffers free! irq=%d tx1=%d tx2=%d last=%d\n", + printk(KERN_DEBUG "%s: No Tx buffers free! irq=%ld tx1=%d tx2=%d last=%d\n", dev->name, dev->interrupt, ei_local->tx1, ei_local->tx2, ei_local->lasttx); ei_local->irqlock = 0; dev->tbusy = 1; diff --git a/drivers/net/hamradio/soundmodem/Makefile b/drivers/net/hamradio/soundmodem/Makefile index 1aabdd9e803f..a5adf62d02cb 100644 --- a/drivers/net/hamradio/soundmodem/Makefile +++ b/drivers/net/hamradio/soundmodem/Makefile @@ -46,7 +46,7 @@ all: all_targets .PHONY: all gentbl: gentbl.c - $(HOSTCC) -Wall $< -o $@ -lm + $(HOSTCC) $(HOSTCFLAGS) $< -o $@ -lm TBLHDR := sm_tbl_afsk1200.h sm_tbl_afsk2400_8.h TBLHDR += sm_tbl_afsk2666.h sm_tbl_psk4800.h diff --git a/drivers/net/ne.c b/drivers/net/ne.c index a4790568644f..ab284bf09f26 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -530,7 +530,7 @@ ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page) /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne_get_8390_hdr " - "[DMAstat:%d][irqlock:%d][intr:%d].\n", + "[DMAstat:%d][irqlock:%d][intr:%ld].\n", dev->name, ei_status.dmaing, ei_status.irqlock, dev->interrupt); return; @@ -570,7 +570,7 @@ ne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offs /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne_block_input " - "[DMAstat:%d][irqlock:%d][intr:%d].\n", + "[DMAstat:%d][irqlock:%d][intr:%ld].\n", dev->name, ei_status.dmaing, ei_status.irqlock, dev->interrupt); return; @@ -639,7 +639,7 @@ ne_block_output(struct device *dev, int count, /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne_block_output." - "[DMAstat:%d][irqlock:%d][intr:%d]\n", + "[DMAstat:%d][irqlock:%d][intr:%ld]\n", dev->name, ei_status.dmaing, ei_status.irqlock, dev->interrupt); return; diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index de2a5e748de4..8f152673c4a7 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -45,7 +45,7 @@ static const char *version = #include "8390.h" /* Set statically or when loading the driver module. */ -static debug = 1; +static int debug = 1; /* Some defines that people can play with if so inclined. */ @@ -446,7 +446,7 @@ ne2k_pci_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_pa /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr " - "[DMAstat:%d][irqlock:%d][intr:%d].\n", + "[DMAstat:%d][irqlock:%d][intr:%ld].\n", dev->name, ei_status.dmaing, ei_status.irqlock, dev->interrupt); return; @@ -484,7 +484,7 @@ ne2k_pci_block_input(struct device *dev, int count, struct sk_buff *skb, int rin /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne2k_pci_block_input " - "[DMAstat:%d][irqlock:%d][intr:%d].\n", + "[DMAstat:%d][irqlock:%d][intr:%ld].\n", dev->name, ei_status.dmaing, ei_status.irqlock, dev->interrupt); return; @@ -532,7 +532,7 @@ ne2k_pci_block_output(struct device *dev, int count, /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne2k_pci_block_output." - "[DMAstat:%d][irqlock:%d][intr:%d]\n", + "[DMAstat:%d][irqlock:%d][intr:%ld]\n", dev->name, ei_status.dmaing, ei_status.irqlock, dev->interrupt); return; diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c index 723a6e46eace..d05f113f27ee 100644 --- a/drivers/net/sk_g16.c +++ b/drivers/net/sk_g16.c @@ -2002,7 +2002,7 @@ void SK_print_dev(struct device *dev, char *text) printk("## Device Name: %s Base Address: %#06lx IRQ: %d\n", dev->name, dev->base_addr, dev->irq); - printk("## FLAGS: start: %d tbusy: %ld int: %d\n", + printk("## FLAGS: start: %d tbusy: %ld int: %ld\n", dev->start, dev->tbusy, dev->interrupt); printk("## next device: %#08x init function: %#08x\n", diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 2edde5d78d80..e1c694414e7f 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -3,20 +3,23 @@ * Linux ThunderLAN Driver * * tlan.c - * by James Banks, james.banks@caldera.com + * by James Banks * - * (C) 1997 Caldera, Inc. + * (C) 1997-1998 Caldera, Inc. + * (C) 1998 James Banks * * This software may be used and distributed according to the terms * of the GNU Public License, incorporated herein by reference. * - ** This file is best viewed/edited with tabstop=4 and colums>=132. + ** This file is best viewed/edited with columns>=132. * ** Useful (if not required) reading: * * Texas Instruments, ThunderLAN Programmer's Guide, * TI Literature Number SPWU013A * available in PDF format from www.ti.com + * Level One, LXT901 and LXT970 Data Sheets + * available in PDF format from www.level1.com * National Semiconductor, DP83840A Data Sheet * available in PDF format from www.national.com * Microchip Technology, 24C01A/02A/04A Data Sheet @@ -29,6 +32,7 @@ #include "tlan.h" +#include #include #include #include @@ -49,53 +53,105 @@ static int TLanDevicesInstalled = 0; static int debug = 0; static int aui = 0; +static int sa_int = 0; +static int bbuf = 0; +static int duplex = 0; +static int speed = 0; static u8 *TLanPadBuffer; static char TLanSignature[] = "TLAN"; -static int TLanVersionMajor = 0; -static int TLanVersionMinor = 38; +static int TLanVersionMajor = 1; +static int TLanVersionMinor = 0; -static TLanPciId TLanDeviceList[] = { +static TLanAdapterEntry TLanAdapterList[] = { { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10, - "Compaq Netelligent 10" + "Compaq Netelligent 10 T PCI UTP", + TLAN_ADAPTER_ACTIVITY_LED, + 0x83 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100, - "Compaq Netelligent 10/100" + "Compaq Netelligent 10/100 TX PCI UTP", + TLAN_ADAPTER_ACTIVITY_LED, + 0x83 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETFLEX_3P_INTEGRATED, - "Compaq Integrated NetFlex-3/P" + "Compaq Integrated NetFlex-3/P", + TLAN_ADAPTER_NONE, + 0x83 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETFLEX_3P, - "Compaq NetFlex-3/P" + "Compaq NetFlex-3/P", + TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, + 0x83 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETFLEX_3P_BNC, - "Compaq NetFlex-3/P" + "Compaq NetFlex-3/P", + TLAN_ADAPTER_NONE, + 0x83 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_PROLIANT, - "Compaq ProLiant Netelligent 10/100" + "Compaq Netelligent Integrated 10/100 TX UTP", + TLAN_ADAPTER_NONE, + 0x83 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_DUAL, - "Compaq Dual Port Netelligent 10/100" + "Compaq Netelligent Dual 10/100 TX PCI UTP", + TLAN_ADAPTER_NONE, + 0x83 }, { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_DESKPRO_4000_5233MMX, - "Compaq Deskpro 4000 5233MMX" + "Compaq Netelligent 10/100 TX Embedded UTP", + TLAN_ADAPTER_NONE, + 0x83 + }, + { PCI_VENDOR_ID_OLICOM, + PCI_DEVICE_ID_OLICOM_OC2183, + "Olicom OC-2183/2185", + TLAN_ADAPTER_USE_INTERN_10, + 0xF8 + }, + { PCI_VENDOR_ID_OLICOM, + PCI_DEVICE_ID_OLICOM_OC2325, + "Olicom OC-2325", + TLAN_ADAPTER_UNMANAGED_PHY, + 0xF8 + }, + { PCI_VENDOR_ID_OLICOM, + PCI_DEVICE_ID_OLICOM_OC2326, + "Olicom OC-2326", + TLAN_ADAPTER_USE_INTERN_10, + 0xF8 + }, + { PCI_VENDOR_ID_COMPAQ, + PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100, + "Compaq Netelligent 10/100 TX UTP", + TLAN_ADAPTER_ACTIVITY_LED, + 0x83 + }, + { PCI_VENDOR_ID_COMPAQ, + PCI_DEVICE_ID_NETELLIGENT_10_T2, + "Compaq Netelligent 10 T/2 PCI UTP/Coax", + TLAN_ADAPTER_NONE, + 0x83 }, { 0, 0, - NULL + NULL, + 0, + 0 } /* End of List */ }; -static int TLan_PciProbe( u8 *, u8 *, int *, u8 *, u32 *, u32 * ); +static int TLan_PciProbe( u8 *, u8 *, u8 *, u8 *, u32 *, u32 * ); static int TLan_Init( struct device * ); static int TLan_Open(struct device *dev); static int TLan_StartTx(struct sk_buff *, struct device *); @@ -116,28 +172,37 @@ static u32 TLan_HandleRxEOC( struct device *, u16 ); static void TLan_Timer( unsigned long ); static void TLan_ResetLists( struct device * ); +static void TLan_FreeLists( struct device * ); static void TLan_PrintDio( u16 ); static void TLan_PrintList( TLanList *, char *, int ); static void TLan_ReadAndClearStats( struct device *, int ); -static int TLan_Reset( struct device * ); +static void TLan_ResetAdapter( struct device * ); +static void TLan_FinishReset( struct device * ); static void TLan_SetMac( struct device *, int areg, char *mac ); -static int TLan_PhyNop( struct device * ); static void TLan_PhyPrint( struct device * ); -static void TLan_PhySelect( struct device * ); +static void TLan_PhyDetect( struct device * ); +static void TLan_PhyPowerDown( struct device * ); +static void TLan_PhyPowerUp( struct device * ); +static void TLan_PhyReset( struct device * ); +static void TLan_PhyStartLink( struct device * ); +static void TLan_PhyFinishAutoNeg( struct device * ); +/* +static int TLan_PhyNop( struct device * ); static int TLan_PhyInternalCheck( struct device * ); static int TLan_PhyInternalService( struct device * ); static int TLan_PhyDp83840aCheck( struct device * ); +*/ -static int TLan_MiiReadReg(u16, u16, u16, u16 *); +static int TLan_MiiReadReg( struct device *, u16, u16, u16 * ); static void TLan_MiiSendData( u16, u32, unsigned ); -static void TLan_MiiSync(u16); -static void TLan_MiiWriteReg(u16, u16, u16, u16); +static void TLan_MiiSync( u16 ); +static void TLan_MiiWriteReg( struct device *, u16, u16, u16 ); static void TLan_EeSendStart( u16 ); static int TLan_EeSendByte( u16, u8, int ); static void TLan_EeReceiveByte( u16, u8 *, int ); -static int TLan_EeReadByte( u16, u8, u8 * ); +static int TLan_EeReadByte( struct device *, u8, u8 * ); static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = { @@ -151,6 +216,25 @@ static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = { TLan_HandleRxEOC }; +static inline void +TLan_SetTimer( struct device *dev, u32 ticks, u32 type ) +{ + TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; + + cli(); + if ( priv->timer.function != NULL ) { + return; + } + priv->timer.function = &TLan_Timer; + sti(); + + priv->timer.data = (unsigned long) dev; + priv->timer.expires = jiffies + ticks; + priv->timerSetAt = jiffies; + priv->timerType = type; + add_timer( &priv->timer ); + +} /* TLan_SetTimer */ /***************************************************************************** @@ -176,7 +260,7 @@ static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = { * * This function begins the setup of the driver creating a * pad buffer, finding all TLAN devices (matching - * TLanDeviceList entries), and creating and initializing a + * TLanAdapterList entries), and creating and initializing a * device structure for each adapter. * **************************************************************/ @@ -188,14 +272,14 @@ extern int init_module(void) struct device *dev; size_t dev_size; u8 dfn; - u32 dl_ix; + u32 index; int failed; int found; u32 io_base; - int irq; + u8 irq; u8 rev; - printk( "TLAN driver, v%d.%d, (C) 1997 Caldera, Inc.\n", + printk( "TLAN driver, v%d.%d, (C) 1997-8 Caldera, Inc.\n", TLanVersionMajor, TLanVersionMinor ); @@ -211,8 +295,7 @@ extern int init_module(void) dev_size = sizeof(struct device) + sizeof(TLanPrivateInfo); - while ( ( found = TLan_PciProbe( &bus, &dfn, &irq, &rev, &io_base, &dl_ix ) ) ) - { + while ( ( found = TLan_PciProbe( &bus, &dfn, &irq, &rev, &io_base, &index ) ) ) { dev = (struct device *) kmalloc( dev_size, GFP_KERNEL ); if ( dev == NULL ) { printk( "TLAN: Could not allocate memory for device.\n" ); @@ -227,23 +310,37 @@ extern int init_module(void) dev->irq = irq; dev->init = TLan_Init; - priv->pciBus = bus; - priv->pciDeviceFn = dfn; - priv->pciRevision = rev; - priv->pciEntry = dl_ix; + priv->adapter = &TLanAdapterList[index]; + priv->adapterRev = rev; + priv->aui = aui; + if ( ( duplex != 1 ) && ( duplex != 2 ) ) { + duplex = 0; + } + priv->duplex = duplex; + if ( ( speed != 10 ) && ( speed != 100 ) ) { + speed = 0; + } + priv->speed = speed; + priv->sa_int = sa_int; + priv->debug = debug; ether_setup( dev ); failed = register_netdev( dev ); if ( failed ) { - printk( "TLAN: Could not register network device. Freeing struct.\n" ); + printk( "TLAN: Could not register device.\n" ); kfree( dev ); } else { priv->nextDevice = TLanDevices; TLanDevices = dev; TLanDevicesInstalled++; - printk("TLAN: %s irq=%2d io=%04x, %s\n", dev->name, (int) irq, io_base, TLanDeviceList[dl_ix].deviceName ); + printk("TLAN: %s irq=%2d io=%04x, %s, Rev. %d\n", + dev->name, + (int) dev->irq, + (int) dev->base_addr, + priv->adapter->deviceLabel, + priv->adapterRev ); } } @@ -276,11 +373,12 @@ extern void cleanup_module(void) struct device *dev; TLanPrivateInfo *priv; - while (TLanDevicesInstalled) { + while ( TLanDevicesInstalled ) { dev = TLanDevices; priv = (TLanPrivateInfo *) dev->priv; - if ( priv->dmaStorage ) + if ( priv->dmaStorage ) { kfree( priv->dmaStorage ); + } release_region( dev->base_addr, 0x10 ); unregister_netdev( dev ); TLanDevices = priv->nextDevice; @@ -315,54 +413,79 @@ extern void cleanup_module(void) extern int tlan_probe( struct device *dev ) { + TLanPrivateInfo *priv; static int pad_allocated = 0; int found; - TLanPrivateInfo *priv; - u8 bus, dfn, rev; - int irq; - u32 io_base, dl_ix; - - found = TLan_PciProbe( &bus, &dfn, &irq, &rev, &io_base, &dl_ix ); - if ( found ) { - dev->priv = kmalloc( sizeof(TLanPrivateInfo), GFP_KERNEL ); - if ( dev->priv == NULL ) { - printk( "TLAN: Could not allocate memory for device.\n" ); + u8 bus, dfn, irq, rev; + u32 io_base, index; + + found = TLan_PciProbe( &bus, &dfn, &irq, &rev, &io_base, &index ); + + if ( ! found ) { + return -ENODEV; + } + + dev->priv = kmalloc( sizeof(TLanPrivateInfo), GFP_KERNEL ); + + if ( dev->priv == NULL ) { + printk( "TLAN: Could not allocate memory for device.\n" ); + return -ENOMEM; + } + + memset( dev->priv, 0, sizeof(TLanPrivateInfo) ); + + if ( ! pad_allocated ) { + TLanPadBuffer = (u8 *) kmalloc( TLAN_MIN_FRAME_SIZE, +// ( GFP_KERNEL | GFP_DMA ) + ( GFP_KERNEL ) + ); + if ( TLanPadBuffer == NULL ) { + printk( "TLAN: Could not allocate memory for padding.\n" ); + kfree( dev->priv ); + return -ENOMEM; + } else { + pad_allocated = 1; + memset( TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE ); } - memset( dev->priv, 0, sizeof(TLanPrivateInfo) ); - priv = (TLanPrivateInfo *) dev->priv; + } - dev->name = priv->devName; - strcpy( priv->devName, " " ); + priv = (TLanPrivateInfo *) dev->priv; - dev = init_etherdev( dev, sizeof(TLanPrivateInfo) ); + dev->name = priv->devName; + strcpy( priv->devName, " " ); - dev->base_addr = io_base; - dev->irq = irq; + dev = init_etherdev( dev, sizeof(TLanPrivateInfo) ); - priv->pciBus = bus; - priv->pciDeviceFn = dfn; - priv->pciRevision = rev; - priv->pciEntry = dl_ix; + dev->base_addr = io_base; + dev->irq = irq; - if ( ! pad_allocated ) { - TLanPadBuffer = (u8 *) kmalloc( TLAN_MIN_FRAME_SIZE, GFP_KERNEL | GFP_DMA ); - if ( TLanPadBuffer == NULL ) { - printk( "TLAN: Could not allocate memory for pad buffer.\n" ); - } else { - pad_allocated = 1; - memset( TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE ); - } - } - printk("TLAN %d.%d: %s irq=%2d io=%04x, %s\n",TLanVersionMajor, - TLanVersionMinor, - dev->name, - (int) irq, - io_base, - TLanDeviceList[dl_ix].deviceName ); - TLan_Init( dev ); + + priv->adapter = &TLanAdapterList[index]; + priv->adapterRev = rev; + priv->aui = dev->mem_start & 0x01; + priv->duplex = ( ( dev->mem_start & 0x0C ) == 0x0C ) ? 0 : ( dev->mem_start & 0x0C ) >> 2; + priv->speed = ( ( dev->mem_start & 0x30 ) == 0x30 ) ? 0 : ( dev->mem_start & 0x30 ) >> 4; + if ( priv->speed == 0x1 ) { + priv->speed = TLAN_SPEED_10; + } else if ( priv->speed == 0x2 ) { + priv->speed = TLAN_SPEED_100; } + priv->sa_int = dev->mem_start & 0x02; + priv->debug = dev->mem_end; + + + printk("TLAN %d.%d: %s irq=%2d io=%04x, %s, Rev. %d\n", + TLanVersionMajor, + TLanVersionMinor, + dev->name, + (int) irq, + io_base, + priv->adapter->deviceLabel, + priv->adapterRev ); + + TLan_Init( dev ); - return ( ( found ) ? 0 : -ENODEV ); + return 0; } /* tlan_probe */ @@ -390,7 +513,7 @@ extern int tlan_probe( struct device *dev ) * of the adapter. * * This function searches for an adapter with PCI vendor - * and device IDs matching those in the TLanDeviceList. + * and device IDs matching those in the TLanAdapterList. * The function 'remembers' the last device it found, * and so finds a new device (if anymore are to be found) * each time the function is called. It then looks up @@ -398,7 +521,7 @@ extern int tlan_probe( struct device *dev ) * **************************************************************/ -int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, int *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix ) +int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, u8 *pci_irq, u8 *pci_rev, u32 *pci_io_base, u32 *dl_ix ) { static int dl_index = 0; static int pci_index = 0; @@ -409,43 +532,43 @@ int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, int *pci_irq, u8 *pci_rev, u32 *pci int reg; - if ( ! pci_present() ) { + if ( ! pcibios_present() ) { printk( "TLAN: PCI Bios not present.\n" ); return 0; } - for (; TLanDeviceList[dl_index].vendorId != 0; dl_index++) { + for (; TLanAdapterList[dl_index].vendorId != 0; dl_index++) { not_found = pcibios_find_device( - TLanDeviceList[dl_index].vendorId, - TLanDeviceList[dl_index].deviceId, + TLanAdapterList[dl_index].vendorId, + TLanAdapterList[dl_index].deviceId, pci_index, pci_bus, pci_dfn ); if ( ! not_found ) { - struct pci_dev *pdev = pci_find_slot(*pci_bus, *pci_dfn); TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: found: Vendor Id = 0x%hx, Device Id = 0x%hx\n", - TLanDeviceList[dl_index].vendorId, - TLanDeviceList[dl_index].deviceId + TLanAdapterList[dl_index].vendorId, + TLanAdapterList[dl_index].deviceId ); - pci_read_config_byte ( pdev, PCI_REVISION_ID, pci_rev); - *pci_irq = pdev->irq; - pci_read_config_word ( pdev, PCI_COMMAND, &pci_command); - pci_read_config_byte ( pdev, PCI_LATENCY_TIMER, &pci_latency); + pcibios_read_config_byte ( *pci_bus, *pci_dfn, PCI_REVISION_ID, pci_rev); + pcibios_read_config_byte ( *pci_bus, *pci_dfn, PCI_INTERRUPT_LINE, pci_irq); + pcibios_read_config_word ( *pci_bus, *pci_dfn, PCI_COMMAND, &pci_command); + pcibios_read_config_dword( *pci_bus, *pci_dfn, PCI_BASE_ADDRESS_0, pci_io_base); + pcibios_read_config_byte ( *pci_bus, *pci_dfn, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < 0x10) { - pci_write_config_byte( pdev, PCI_LATENCY_TIMER, 0xff); + pcibios_write_config_byte( *pci_bus, *pci_dfn, PCI_LATENCY_TIMER, 0xff); TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: Setting latency timer to max.\n"); } - for ( reg = 0; reg <= 5; reg ++ ) { - *pci_io_base = pdev->base_address[reg]; + for ( reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg +=4 ) { + pcibios_read_config_dword( *pci_bus, *pci_dfn, reg, pci_io_base); if ((pci_command & PCI_COMMAND_IO) && (*pci_io_base & 0x3)) { *pci_io_base &= PCI_BASE_ADDRESS_IO_MASK; TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: IO mapping is available at %x.\n", *pci_io_base); @@ -458,8 +581,9 @@ int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, int *pci_irq, u8 *pci_rev, u32 *pci if ( *pci_io_base == 0 ) printk("TLAN: IO mapping not available, ignoring device.\n"); - if (pci_command & PCI_COMMAND_MASTER) { - TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: Bus mastering is active.\n"); + if ( ! ( pci_command & PCI_COMMAND_MASTER ) ) { + pcibios_write_config_word ( *pci_bus, *pci_dfn, PCI_COMMAND, pci_command | PCI_COMMAND_MASTER ); + printk( "TLAN: Activating PCI bus mastering for this device.\n" ); } pci_index++; @@ -500,9 +624,9 @@ int TLan_PciProbe( u8 *pci_bus, u8 *pci_dfn, int *pci_irq, u8 *pci_rev, u32 *pci int TLan_Init( struct device *dev ) { - int dma_size; - int err; - int i; + int dma_size; + int err; + int i; TLanPrivateInfo *priv; priv = (TLanPrivateInfo *) dev->priv; @@ -517,8 +641,14 @@ int TLan_Init( struct device *dev ) } request_region( dev->base_addr, 0x10, TLanSignature ); - dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS ) + if ( bbuf ) { + dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS ) * ( sizeof(TLanList) + TLAN_MAX_FRAME_SIZE ); + } else { + dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS ) + * ( sizeof(TLanList) ); + } + priv->dmaStorage = kmalloc( dma_size, GFP_KERNEL | GFP_DMA ); if ( priv->dmaStorage == NULL ) { printk( "TLAN: Could not allocate lists and buffers for %s.\n", @@ -529,19 +659,24 @@ int TLan_Init( struct device *dev ) priv->rxList = (TLanList *) ( ( ( (u32) priv->dmaStorage ) + 7 ) & 0xFFFFFFF8 ); priv->txList = priv->rxList + TLAN_NUM_RX_LISTS; - priv->rxBuffer = (u8 *) ( priv->txList + TLAN_NUM_TX_LISTS ); - priv->txBuffer = priv->rxBuffer - + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE ); + + if ( bbuf ) { + priv->rxBuffer = (u8 *) ( priv->txList + TLAN_NUM_TX_LISTS ); + priv->txBuffer = priv->rxBuffer + + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE ); + } err = 0; for ( i = 0; i < 6 ; i++ ) - err |= TLan_EeReadByte( dev->base_addr, - (u8) 0x83 + i, + err |= TLan_EeReadByte( dev, + (u8) priv->adapter->addrOfs + i, (u8 *) &dev->dev_addr[i] ); - if ( err ) + if ( err ) { printk( "TLAN: %s: Error reading MAC from eeprom: %d\n", dev->name, err ); + } + dev->addr_len = 6; dev->open = &TLan_Open; @@ -550,12 +685,6 @@ int TLan_Init( struct device *dev ) dev->get_stats = &TLan_GetStats; dev->set_multicast_list = &TLan_SetMulticastList; -#ifndef MODULE - - aui = dev->mem_start & 0x01; - debug = dev->mem_end; - -#endif /* MODULE */ return 0; @@ -583,16 +712,21 @@ int TLan_Init( struct device *dev ) int TLan_Open( struct device *dev ) { - int err; TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; + int err; priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION ); - err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev); + if ( priv->sa_int ) { + TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: Using SA_INTERRUPT\n" ); + err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ | SA_INTERRUPT, TLanSignature, dev ); + } else { + err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev ); + } if ( err ) { - printk( "TLAN: Cannot open %s because IRQ %d is already in use.\n", dev->name , dev->irq ); + printk( "TLAN: Cannot open %s because IRQ %d is already in use.\n", dev->name, dev->irq ); return -EAGAIN; } - + MOD_INC_USE_COUNT; dev->tbusy = 0; @@ -604,27 +738,9 @@ int TLan_Open( struct device *dev ) */ TLan_ResetLists( dev ); TLan_ReadAndClearStats( dev, TLAN_IGNORE ); - TLan_Reset( dev ); - TLan_Reset( dev ); - TLan_SetMac( dev, 0, dev->dev_addr ); - outb( ( TLAN_HC_INT_ON >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 ); - if ( debug >= 1 ) - outb( ( TLAN_HC_REQ_INT >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 ); - - init_timer( &priv->timer ); - priv->timer.data = (unsigned long) dev; - priv->timer.function = &TLan_Timer; - if ( priv->phyFlags & TLAN_PHY_AUTONEG ) { - priv->timer.expires = jiffies + TLAN_TIMER_LINK_DELAY; - priv->timerSetAt = jiffies; - priv->timerType = TLAN_TIMER_LINK; - add_timer( &priv->timer ); - } else { - outl( virt_to_bus( priv->rxList ), dev->base_addr + TLAN_CH_PARM ); - outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD ); - } + TLan_ResetAdapter( dev ); - TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: Device %s opened. Revision = %x\n", dev->name, priv->tlanRev ); + TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: %s: Opened. TLAN Chip Rev: %x\n", dev->name, priv->tlanRev ); return 0; @@ -657,27 +773,37 @@ int TLan_Open( struct device *dev ) int TLan_StartTx( struct sk_buff *skb, struct device *dev ) { TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; - TLanList *tail_list; - u8 *tail_buffer; - int pad; + TLanList *tail_list; + u8 *tail_buffer; + int pad; if ( ! priv->phyOnline ) { TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: %s PHY is not ready\n", dev->name ); - dev_kfree_skb( skb ); + dev_kfree_skb( skb, FREE_WRITE ); return 0; } tail_list = priv->txList + priv->txTail; + if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) { TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: %s is busy (Head=%d Tail=%d)\n", dev->name, priv->txHead, priv->txTail ); dev->tbusy = 1; priv->txBusyCount++; return 1; } + tail_list->forward = 0; - tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE ); - memcpy( tail_buffer, skb->data, skb->len ); + + if ( bbuf ) { + tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE ); + memcpy( tail_buffer, skb->data, skb->len ); + } else { + tail_list->buffer[0].address = virt_to_bus( skb->data ); + tail_list->buffer[9].address = (u32) skb; + } + pad = TLAN_MIN_FRAME_SIZE - skb->len; + if ( pad > 0 ) { tail_list->frameSize = (u16) skb->len + pad; tail_list->buffer[0].count = (u32) skb->len; @@ -689,7 +815,7 @@ int TLan_StartTx( struct sk_buff *skb, struct device *dev ) tail_list->buffer[1].count = 0; tail_list->buffer[1].address = 0; } - /* are we transferring? */ + cli(); tail_list->cStat = TLAN_CSTAT_READY; if ( ! priv->txInProgress ) { @@ -700,17 +826,19 @@ int TLan_StartTx( struct sk_buff *skb, struct device *dev ) outl( TLAN_HC_GO | TLAN_HC_ACK, dev->base_addr + TLAN_HOST_CMD ); } else { TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Adding buffer %d to TX channel\n", priv->txTail ); - if ( priv->txTail == 0 ) + if ( priv->txTail == 0 ) { ( priv->txList + ( TLAN_NUM_TX_LISTS - 1 ) )->forward = virt_to_bus( tail_list ); - else + } else { ( priv->txList + ( priv->txTail - 1 ) )->forward = virt_to_bus( tail_list ); + } } sti(); - priv->txTail++; - if ( priv->txTail >= TLAN_NUM_TX_LISTS ) - priv->txTail = 0; - dev_kfree_skb( skb ); + CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS ); + + if ( bbuf ) { + dev_kfree_skb( skb, FREE_WRITE ); + } dev->trans_start = jiffies; return 0; @@ -743,35 +871,34 @@ int TLan_StartTx( struct sk_buff *skb, struct device *dev ) void TLan_HandleInterrupt(int irq, void *dev_id, struct pt_regs *regs) { - u32 ack; + u32 ack; struct device *dev; - u32 host_cmd; - u16 host_int; - int type; + u32 host_cmd; + u16 host_int; + int type; dev = (struct device *) dev_id; - if ( dev->interrupt ) - printk( "TLAN: Re-entering interrupt handler for %s: %d.\n" , dev->name, dev->interrupt ); - dev->interrupt++; - cli(); + if ( dev->interrupt ) { + printk( "TLAN: Re-entering interrupt handler for %s: %ld.\n" , dev->name, dev->interrupt ); + } + dev->interrupt++; host_int = inw( dev->base_addr + TLAN_HOST_INT ); - outw( host_int, dev->base_addr + TLAN_HOST_INT ); /* Deactivate Ints */ + outw( host_int, dev->base_addr + TLAN_HOST_INT ); type = ( host_int & TLAN_HI_IT_MASK ) >> 2; ack = TLanIntVector[type]( dev, host_int ); - sti(); - if ( ack ) { host_cmd = TLAN_HC_ACK | ack | ( type << 18 ); outl( host_cmd, dev->base_addr + TLAN_HOST_CMD ); } dev->interrupt--; + sti(); } /* TLan_HandleInterrupts */ @@ -802,10 +929,11 @@ int TLan_Close(struct device *dev) TLan_ReadAndClearStats( dev, TLAN_RECORD ); outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD ); - if ( priv->timerSetAt != 0 ) + if ( priv->timer.function != NULL ) del_timer( &priv->timer ); free_irq( dev->irq, dev ); - TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: Device %s closed.\n", dev->name ); + TLan_FreeLists( dev ); + TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: Device %s closed.\n", dev->name ); MOD_DEC_USE_COUNT; @@ -882,11 +1010,11 @@ struct net_device_stats *TLan_GetStats( struct device *dev ) void TLan_SetMulticastList( struct device *dev ) { struct dev_mc_list *dmi = dev->mc_list; - u32 hash1 = 0; - u32 hash2 = 0; - int i; - u32 offset; - u8 tmp; + u32 hash1 = 0; + u32 hash2 = 0; + int i; + u32 offset; + u8 tmp; if ( dev->flags & IFF_PROMISC ) { tmp = TLan_DioRead8( dev->base_addr, TLAN_NET_CMD ); @@ -989,19 +1117,24 @@ u32 TLan_HandleInvalid( struct device *dev, u16 host_int ) u32 TLan_HandleTxEOF( struct device *dev, u16 host_int ) { TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; - int eoc = 0; - TLanList *head_list; - u32 ack = 1; + int eoc = 0; + TLanList *head_list; + u32 ack = 1; TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Handling TX EOF (Head=%d Tail=%d)\n", priv->txHead, priv->txTail ); host_int = 0; head_list = priv->txList + priv->txHead; + + if ( ! bbuf ) { + dev_kfree_skb( (struct sk_buff *) head_list->buffer[9].address, FREE_WRITE ); + head_list->buffer[9].address = 0; + } + if ( head_list->cStat & TLAN_CSTAT_EOC ) eoc = 1; if ( ! head_list->cStat & TLAN_CSTAT_FRM_CMP ) { printk( "TLAN: Received interrupt for uncompleted TX frame.\n" ); } - /* printk( "Ack %d CSTAT=%hx\n", priv->txHead, head_list->cStat ); */ #if LINUX_KERNEL_VERSION > 0x20100 priv->stats->tx_bytes += head_list->frameSize; @@ -1009,9 +1142,7 @@ u32 TLan_HandleTxEOF( struct device *dev, u16 host_int ) head_list->cStat = TLAN_CSTAT_UNUSED; dev->tbusy = 0; - priv->txHead++; - if ( priv->txHead >= TLAN_NUM_TX_LISTS ) - priv->txHead = 0; + CIRC_INC( priv->txHead, TLAN_NUM_TX_LISTS ); if ( eoc ) { TLAN_DBG( TLAN_DEBUG_TX, "TLAN TRANSMIT: Handling TX EOC (Head=%d Tail=%d)\n", priv->txHead, priv->txTail ); head_list = priv->txList + priv->txHead; @@ -1022,17 +1153,13 @@ u32 TLan_HandleTxEOF( struct device *dev, u16 host_int ) priv->txInProgress = 0; } } - TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT ); - if ( priv->phyFlags & TLAN_PHY_ACTIVITY ) { - if ( priv->timerSetAt == 0 ) { - /* printk("TxEOF Starting timer...\n"); */ - priv->timerSetAt = jiffies; - priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY; - priv->timerType = TLAN_TIMER_ACT; - add_timer( &priv->timer ); - } else if ( priv->timerType == TLAN_TIMER_ACT ) { + + if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) { + TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT ); + if ( priv->timer.function == NULL ) { + TLan_SetTimer( dev, TLAN_TIMER_ACT_DELAY, TLAN_TIMER_ACTIVITY ); + } else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) { priv->timerSetAt = jiffies; - /* printk("TxEOF continuing timer...\n"); */ } } @@ -1093,7 +1220,7 @@ u32 TLan_HandleStatOverflow( struct device *dev, u16 host_int ) * of the list. If the frame was the last in the Rx * channel (EOC), the function restarts the receive channel * by sending an Rx Go command to the adapter. Then it - * activates/continues the activity LED. + * activates/continues the the activity LED. * **************************************************************/ @@ -1112,11 +1239,14 @@ u32 TLan_HandleRxEOF( struct device *dev, u16 host_int ) host_int = 0; head_list = priv->rxList + priv->rxHead; tail_list = priv->rxList + priv->rxTail; - if ( head_list->cStat & TLAN_CSTAT_EOC ) + + if ( head_list->cStat & TLAN_CSTAT_EOC ) { eoc = 1; + } + if ( ! head_list->cStat & TLAN_CSTAT_FRM_CMP ) { printk( "TLAN: Received interrupt for uncompleted RX frame.\n" ); - } else { + } else if ( bbuf ) { skb = dev_alloc_skb( head_list->frameSize + 7 ); if ( skb == NULL ) { printk( "TLAN: Couldn't allocate memory for received data.\n" ); @@ -1125,7 +1255,6 @@ u32 TLan_HandleRxEOF( struct device *dev, u16 host_int ) skb->dev = dev; skb_reserve( skb, 2 ); t = (void *) skb_put( skb, head_list->frameSize ); - /* printk( " %hd %p %p\n", head_list->frameSize, skb->data, t ); */ #if LINUX_KERNEL_VERSION > 0x20100 priv->stats->rx_bytes += head_list->frameSize; @@ -1135,17 +1264,39 @@ u32 TLan_HandleRxEOF( struct device *dev, u16 host_int ) skb->protocol = eth_type_trans( skb, dev ); netif_rx( skb ); } + } else { + skb = (struct sk_buff *) head_list->buffer[9].address; + head_list->buffer[9].address = 0; + skb_trim( skb, head_list->frameSize ); + +#if LINUX_KERNEL_VERSION > 0x20100 + priv->stats->rx_bytes += head_list->frameSize; +#endif + + skb->protocol = eth_type_trans( skb, dev ); + netif_rx( skb ); + + skb = dev_alloc_skb( TLAN_MAX_FRAME_SIZE + 7 ); + if ( skb == NULL ) { + printk( "TLAN: Couldn't allocate memory for received data.\n" ); + /* If this ever happened it would be a problem */ + } else { + skb->dev = dev; + skb_reserve( skb, 2 ); + t = (void *) skb_put( skb, TLAN_MAX_FRAME_SIZE ); + head_list->buffer[0].address = virt_to_bus( t ); + head_list->buffer[9].address = (u32) skb; + } } + head_list->forward = 0; head_list->frameSize = TLAN_MAX_FRAME_SIZE; head_list->buffer[0].count = TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER; tail_list->forward = virt_to_bus( head_list ); - priv->rxHead++; - if ( priv->rxHead >= TLAN_NUM_RX_LISTS ) - priv->rxHead = 0; - priv->rxTail++; - if ( priv->rxTail >= TLAN_NUM_RX_LISTS ) - priv->rxTail = 0; + + CIRC_INC( priv->rxHead, TLAN_NUM_RX_LISTS ); + CIRC_INC( priv->rxTail, TLAN_NUM_RX_LISTS ); + if ( eoc ) { TLAN_DBG( TLAN_DEBUG_RX, "TLAN RECEIVE: Handling RX EOC (Head=%d Tail=%d)\n", priv->rxHead, priv->rxTail ); head_list = priv->rxList + priv->rxHead; @@ -1153,19 +1304,16 @@ u32 TLan_HandleRxEOF( struct device *dev, u16 host_int ) ack |= TLAN_HC_GO | TLAN_HC_RT; priv->rxEocCount++; } - TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT ); - if ( priv->phyFlags & TLAN_PHY_ACTIVITY ) { - if ( priv->timerSetAt == 0 ) { - /* printk("RxEOF Starting timer...\n"); */ - priv->timerSetAt = jiffies; - priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY; - priv->timerType = TLAN_TIMER_ACT; - add_timer( &priv->timer ); - } else if ( priv->timerType == TLAN_TIMER_ACT ) { - /* printk("RxEOF tarting continuing timer...\n"); */ + + if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) { + TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT ); + if ( priv->timer.function == NULL ) { + TLan_SetTimer( dev, TLAN_TIMER_ACT_DELAY, TLAN_TIMER_ACTIVITY ); + } else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) { priv->timerSetAt = jiffies; } } + dev->last_rx = jiffies; return ack; @@ -1195,7 +1343,7 @@ u32 TLan_HandleRxEOF( struct device *dev, u16 host_int ) u32 TLan_HandleDummy( struct device *dev, u16 host_int ) { host_int = 0; - printk( "TLAN: Dummy interrupt on %s.\n", dev->name ); + printk( "TLAN: Test interrupt on %s.\n", dev->name ); return 1; } /* TLan_HandleDummy */ @@ -1270,45 +1418,49 @@ u32 TLan_HandleTxEOC( struct device *dev, u16 host_int ) u32 TLan_HandleStatusCheck( struct device *dev, u16 host_int ) { - u32 ack; - u32 error; - u8 net_sts; TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; + u32 ack; + u32 error; + u8 net_sts; + u32 phy; + u16 tlphy_ctl; + u16 tlphy_sts; ack = 1; if ( host_int & TLAN_HI_IV_MASK ) { error = inl( dev->base_addr + TLAN_CH_PARM ); - printk( "TLAN: Adaptor Check on device %s err = 0x%x\n", dev->name, error ); + printk( "TLAN: %s: Adaptor Error = 0x%x\n", dev->name, error ); TLan_ReadAndClearStats( dev, TLAN_RECORD ); outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD ); + TLan_FreeLists( dev ); TLan_ResetLists( dev ); - TLan_Reset( dev ); + TLan_ResetAdapter( dev ); dev->tbusy = 0; - TLan_SetMac( dev, 0, dev->dev_addr ); - if ( priv->timerType == 0 ) { - if ( priv->phyFlags & TLAN_PHY_AUTONEG ) { - priv->timer.expires = jiffies + TLAN_TIMER_LINK_DELAY; - priv->timerSetAt = jiffies; - priv->timerType = TLAN_TIMER_LINK; - add_timer( &priv->timer ); - } else { - /*printk( " RX GO---->\n" ); */ - outl( virt_to_bus( priv->rxList ), dev->base_addr + TLAN_CH_PARM ); - outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD ); - } - } ack = 0; } else { + TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: %s: Status Check\n", dev->name ); + phy = priv->phy[priv->phyNum]; + net_sts = TLan_DioRead8( dev->base_addr, TLAN_NET_STS ); - if ( net_sts ) + if ( net_sts ) { TLan_DioWrite8( dev->base_addr, TLAN_NET_STS, net_sts ); - if ( net_sts & TLAN_NET_STS_MIRQ ) { - (*priv->phyService)( dev ); + TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: %s: Net_Sts = %x\n", dev->name, (unsigned) net_sts ); + } + if ( ( net_sts & TLAN_NET_STS_MIRQ ) && ( priv->phyNum == 0 ) ) { + TLan_MiiReadReg( dev, phy, TLAN_TLPHY_STS, &tlphy_sts ); + TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl ); + if ( ! ( tlphy_sts & TLAN_TS_POLOK ) && ! ( tlphy_ctl & TLAN_TC_SWAPOL ) ) { + tlphy_ctl |= TLAN_TC_SWAPOL; + TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl); + } else if ( ( tlphy_sts & TLAN_TS_POLOK ) && ( tlphy_ctl & TLAN_TC_SWAPOL ) ) { + tlphy_ctl &= ~TLAN_TC_SWAPOL; + TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl); + } + if (debug) { TLan_PhyPrint( dev ); } } - TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: Status Check! %s Net_Sts=%x\n", dev->name, (unsigned) net_sts ); } return ack; @@ -1341,8 +1493,8 @@ u32 TLan_HandleStatusCheck( struct device *dev, u16 host_int ) u32 TLan_HandleRxEOC( struct device *dev, u16 host_int ) { TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; - TLanList *head_list; - u32 ack = 1; + TLanList *head_list; + u32 ack = 1; host_int = 0; if ( priv->tlanRev < 0x30 ) { @@ -1402,34 +1554,44 @@ u32 TLan_HandleRxEOC( struct device *dev, u16 host_int ) void TLan_Timer( unsigned long data ) { struct device *dev = (struct device *) data; - u16 gen_sts; TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; + u32 elapsed; - /* printk( "TLAN: %s Entered Timer, type = %d\n", dev->name, priv->timerType ); */ + priv->timer.function = NULL; switch ( priv->timerType ) { - case TLAN_TIMER_LINK: - TLan_MiiReadReg( dev->base_addr, priv->phyAddr, MII_GEN_STS, &gen_sts ); - if ( gen_sts & MII_GS_LINK ) { - priv->phyOnline = 1; - outl( virt_to_bus( priv->rxList ), dev->base_addr + TLAN_CH_PARM ); - outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD ); - priv->timerSetAt = 0; - priv->timerType = 0; - } else { - priv->timer.expires = jiffies + ( TLAN_TIMER_LINK_DELAY * 2 ); - add_timer( &priv->timer ); - } + case TLAN_TIMER_PHY_PDOWN: + TLan_PhyPowerDown( dev ); break; - case TLAN_TIMER_ACT: - if ( jiffies - priv->timerSetAt >= TLAN_TIMER_ACT_DELAY ) { - TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK ); - priv->timerSetAt = 0; - priv->timerType = 0; - } else { - priv->timer.expires = priv->timerSetAt + TLAN_TIMER_ACT_DELAY; - add_timer( &priv->timer ); + case TLAN_TIMER_PHY_PUP: + TLan_PhyPowerUp( dev ); + break; + case TLAN_TIMER_PHY_RESET: + TLan_PhyReset( dev ); + break; + case TLAN_TIMER_PHY_START_LINK: + TLan_PhyStartLink( dev ); + break; + case TLAN_TIMER_PHY_FINISH_AN: + TLan_PhyFinishAutoNeg( dev ); + break; + case TLAN_TIMER_FINISH_RESET: + TLan_FinishReset( dev ); + break; + case TLAN_TIMER_ACTIVITY: + cli(); + if ( priv->timer.function == NULL ) { + elapsed = jiffies - priv->timerSetAt; + if ( elapsed >= TLAN_TIMER_ACT_DELAY ) { + TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK ); + } else { + priv->timer.function = &TLan_Timer; + priv->timer.expires = priv->timerSetAt + TLAN_TIMER_ACT_DELAY; + sti(); + add_timer( &priv->timer ); + } } + sti(); break; default: break; @@ -1468,13 +1630,19 @@ void TLan_ResetLists( struct device *dev ) TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; int i; TLanList *list; + struct sk_buff *skb; + void *t = NULL; priv->txHead = 0; priv->txTail = 0; for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) { list = priv->txList + i; list->cStat = TLAN_CSTAT_UNUSED; - list->buffer[0].address = virt_to_bus( priv->txBuffer + ( i * TLAN_MAX_FRAME_SIZE ) ); + if ( bbuf ) { + list->buffer[0].address = virt_to_bus( priv->txBuffer + ( i * TLAN_MAX_FRAME_SIZE ) ); + } else { + list->buffer[0].address = 0; + } list->buffer[2].count = 0; list->buffer[2].address = 0; } @@ -1486,7 +1654,21 @@ void TLan_ResetLists( struct device *dev ) list->cStat = TLAN_CSTAT_READY; list->frameSize = TLAN_MAX_FRAME_SIZE; list->buffer[0].count = TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER; - list->buffer[0].address = virt_to_bus( priv->rxBuffer + ( i * TLAN_MAX_FRAME_SIZE ) ); + if ( bbuf ) { + list->buffer[0].address = virt_to_bus( priv->rxBuffer + ( i * TLAN_MAX_FRAME_SIZE ) ); + } else { + skb = dev_alloc_skb( TLAN_MAX_FRAME_SIZE + 7 ); + if ( skb == NULL ) { + printk( "TLAN: Couldn't allocate memory for received data.\n" ); + /* If this ever happened it would be a problem */ + } else { + skb->dev = dev; + skb_reserve( skb, 2 ); + t = (void *) skb_put( skb, TLAN_MAX_FRAME_SIZE ); + } + list->buffer[0].address = virt_to_bus( t ); + list->buffer[9].address = (u32) skb; + } list->buffer[1].count = 0; list->buffer[1].address = 0; if ( i < TLAN_NUM_RX_LISTS - 1 ) @@ -1498,6 +1680,36 @@ void TLan_ResetLists( struct device *dev ) } /* TLan_ResetLists */ +void TLan_FreeLists( struct device *dev ) +{ + TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; + int i; + TLanList *list; + struct sk_buff *skb; + + if ( ! bbuf ) { + for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) { + list = priv->txList + i; + skb = (struct sk_buff *) list->buffer[9].address; + if ( skb ) { + dev_kfree_skb( skb, FREE_WRITE ); + list->buffer[9].address = 0; + } + } + + for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) { + list = priv->rxList + i; + skb = (struct sk_buff *) list->buffer[9].address; + if ( skb ) { + dev_kfree_skb( skb, FREE_READ ); + list->buffer[9].address = 0; + } + } + } + +} /* TLan_FreeLists */ + + /*************************************************************** @@ -1509,7 +1721,7 @@ void TLan_ResetLists( struct device *dev ) * io_base Base IO port of the device of * which to print DIO registers. * - * This function prints out all the internal (DIO) + * This function prints out all the the internal (DIO) * registers of a TLAN chip. * **************************************************************/ @@ -1588,11 +1800,11 @@ void TLan_PrintList( TLanList *list, char *type, int num) void TLan_ReadAndClearStats( struct device *dev, int record ) { TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; - u32 tx_good, tx_under; - u32 rx_good, rx_over; - u32 def_tx, crc, code; - u32 multi_col, single_col; - u32 excess_col, late_col, loss; + u32 tx_good, tx_under; + u32 rx_good, rx_over; + u32 def_tx, crc, code; + u32 multi_col, single_col; + u32 excess_col, late_col, loss; outw( TLAN_GOOD_TX_FRMS, dev->base_addr + TLAN_DIO_ADR ); tx_good = inb( dev->base_addr + TLAN_DIO_DATA ); @@ -1660,7 +1872,8 @@ void TLan_ReadAndClearStats( struct device *dev, int record ) * **************************************************************/ -int TLan_Reset( struct device *dev ) +void +TLan_ResetAdapter( struct device *dev ) { TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; int i; @@ -1668,11 +1881,14 @@ int TLan_Reset( struct device *dev ) u32 data; u8 data8; + priv->tlanFullDuplex = FALSE; /* 1. Assert reset bit. */ data = inl(dev->base_addr + TLAN_HOST_CMD); data |= TLAN_HC_AD_RST; outl(data, dev->base_addr + TLAN_HOST_CMD); + + udelay(1000); /* 2. Turn off interrupts. ( Probably isn't necessary ) */ @@ -1708,37 +1924,97 @@ int TLan_Reset( struct device *dev ) data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC; TLan_DioWrite8( dev->base_addr, TLAN_INT_DIS, data8 ); } - TLan_PhySelect( dev ); + TLan_PhyDetect( dev ); data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN; - if ( priv->phyFlags & TLAN_PHY_BIT_RATE ) { + if ( priv->adapter->flags & TLAN_ADAPTER_BIT_RATE_PHY ) { data |= TLAN_NET_CFG_BIT; - if ( aui == 1 ) { + if ( priv->aui == 1 ) { TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x0a ); + } else if ( priv->duplex == TLAN_DUPLEX_FULL ) { + TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x00 ); + priv->tlanFullDuplex = TRUE; } else { TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x08 ); } } - if ( priv->phyFlags & TLAN_PHY_INTERNAL ) { + if ( priv->phyNum == 0 ) { data |= TLAN_NET_CFG_PHY_EN; } TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data ); - (*priv->phyCheck)( dev ); - data8 = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP; - TLan_DioWrite8( dev->base_addr, TLAN_NET_CMD, data8 ); - data8 = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5; - if ( priv->phyFlags & TLAN_PHY_INTS ) { - data8 |= TLAN_NET_MASK_MASK7; - } - TLan_DioWrite8( dev->base_addr, TLAN_NET_MASK, data8 ); + + if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) { + TLan_FinishReset( dev ); + } else { + TLan_PhyPowerDown( dev ); + } + +} /* TLan_ResetAdapter */ + + + + +void +TLan_FinishReset( struct device *dev ) +{ + TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; + u8 data; + u32 phy; + u8 sio; + u16 status; + u16 tlphy_ctl; + + phy = priv->phy[priv->phyNum]; + + data = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP; + if ( priv->tlanFullDuplex ) { + data |= TLAN_NET_CMD_DUPLEX; + } + TLan_DioWrite8( dev->base_addr, TLAN_NET_CMD, data ); + data = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5; + if ( priv->phyNum == 0 ) { + data |= TLAN_NET_MASK_MASK7; + } + TLan_DioWrite8( dev->base_addr, TLAN_NET_MASK, data ); TLan_DioWrite16( dev->base_addr, TLAN_MAX_RX, TLAN_MAX_FRAME_SIZE ); - if ( priv->phyFlags & TLAN_PHY_UNMANAGED ) { - priv->phyOnline = 1; + if ( ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) || ( priv->aui ) ) { + status = MII_GS_LINK; + printk( "TLAN: %s: Link forced.\n", dev->name ); + } else { + TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status ); + udelay( 1000 ); + TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status ); + if ( status & MII_GS_LINK ) { + printk( "TLAN: %s: Link active.\n", dev->name ); + TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK ); + } } - return 0; + if ( priv->phyNum == 0 ) { + TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl ); + tlphy_ctl |= TLAN_TC_INTEN; + TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl ); + sio = TLan_DioRead8( dev->base_addr, TLAN_NET_SIO ); + sio |= TLAN_NET_SIO_MINTEN; + TLan_DioWrite8( dev->base_addr, TLAN_NET_SIO, sio ); + } + + if ( status & MII_GS_LINK ) { + TLan_SetMac( dev, 0, dev->dev_addr ); + priv->phyOnline = 1; + outb( ( TLAN_HC_INT_ON >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 ); + if ( debug >= 1 ) { + outb( ( TLAN_HC_REQ_INT >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 ); + } + outl( virt_to_bus( priv->rxList ), dev->base_addr + TLAN_CH_PARM ); + outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD ); + } else { + printk( "TLAN: %s: Link inactive, will retry in 10 secs...\n", dev->name ); + TLan_SetTimer( dev, 1000, TLAN_TIMER_FINISH_RESET ); + return; + } -} /* TLan_Reset */ +} /* TLan_FinishReset */ @@ -1754,7 +2030,7 @@ int TLan_Reset( struct device *dev ) * areg The AREG to set the address in (0 - 3). * mac A pointer to an array of chars. Each * element stores one byte of the address. - * That is, it isn't in ASCII. + * IE, it isn't in ascii. * * This function transfers a MAC address to one of the * TLAN AREGs (address registers). The TLAN chip locks @@ -1788,56 +2064,10 @@ void TLan_SetMac( struct device *dev, int areg, char *mac ) ThunderLAN Driver PHY Layer Routines - The TLAN chip can drive any number of PHYs (physical devices). Rather - than having lots of 'if' or '#ifdef' statements, I have created a - second driver layer for the PHYs. Each PHY can be identified from its - id in registers 2 and 3, and can be given a Check and Service routine - that will be called when the adapter is reset and when the adapter - receives a Network Status interrupt, respectively. - ****************************************************************************** *****************************************************************************/ -static TLanPhyIdEntry TLanPhyIdTable[] = { - { 0x4000, - 0x5014, - &TLan_PhyInternalCheck, - &TLan_PhyInternalService, - TLAN_PHY_ACTIVITY | TLAN_PHY_INTS | TLAN_PHY_INTERNAL }, - { 0x4000, - 0x5015, - &TLan_PhyInternalCheck, - &TLan_PhyInternalService, - TLAN_PHY_ACTIVITY | TLAN_PHY_INTS | TLAN_PHY_INTERNAL }, - { 0x4000, - 0x5016, - &TLan_PhyInternalCheck, - &TLan_PhyInternalService, - TLAN_PHY_ACTIVITY | TLAN_PHY_INTS | TLAN_PHY_INTERNAL }, - { 0x2000, - 0x5C00, - &TLan_PhyDp83840aCheck, - &TLan_PhyNop, - TLAN_PHY_ACTIVITY | TLAN_PHY_AUTONEG }, - { 0x2000, - 0x5C01, - &TLan_PhyDp83840aCheck, - &TLan_PhyNop, - TLAN_PHY_ACTIVITY | TLAN_PHY_AUTONEG }, - { 0x7810, - 0x0000, - &TLan_PhyDp83840aCheck, - &TLan_PhyNop, - TLAN_PHY_AUTONEG }, - { 0x0000, - 0x0000, - NULL, - NULL, - 0 - } - }; - /********************************************************************* * TLan_PhyPrint @@ -1845,10 +2075,10 @@ static TLanPhyIdEntry TLanPhyIdTable[] = { * Returns: * Nothing * Parms: - * dev A pointer to the device structure of the adapter - * which the desired PHY is located. + * dev A pointer to the device structure of the + * TLAN device having the PHYs to be detailed. * - * This function prints the registers a PHY. + * This function prints the registers a PHY (aka tranceiver). * ********************************************************************/ @@ -1856,30 +2086,27 @@ void TLan_PhyPrint( struct device *dev ) { TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; u16 i, data0, data1, data2, data3, phy; - u32 io; - phy = priv->phyAddr; - io = dev->base_addr; + phy = priv->phy[priv->phyNum]; - if ( ( phy > 0 ) && ( phy <= TLAN_PHY_MAX_ADDR ) ) { + if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) { + printk( "TLAN: Device %s, Unmanaged PHY.\n", dev->name ); + } else if ( phy <= TLAN_PHY_MAX_ADDR ) { printk( "TLAN: Device %s, PHY 0x%02x.\n", dev->name, phy ); printk( "TLAN: Off. +0 +1 +2 +3 \n" ); for ( i = 0; i < 0x20; i+= 4 ) { printk( "TLAN: 0x%02x", i ); - TLan_MiiReadReg( io, phy, i, &data0 ); + TLan_MiiReadReg( dev, phy, i, &data0 ); printk( " 0x%04hx", data0 ); - TLan_MiiReadReg( io, phy, i + 1, &data1 ); + TLan_MiiReadReg( dev, phy, i + 1, &data1 ); printk( " 0x%04hx", data1 ); - TLan_MiiReadReg( io, phy, i + 2, &data2 ); + TLan_MiiReadReg( dev, phy, i + 2, &data2 ); printk( " 0x%04hx", data2 ); - TLan_MiiReadReg( io, phy, i + 3, &data3 ); + TLan_MiiReadReg( dev, phy, i + 3, &data3 ); printk( " 0x%04hx\n", data3 ); } } else { - printk( "TLAN: Device %s, PHY 0x%02x (Unmanaged/Unknown).\n", - dev->name, - phy - ); + printk( "TLAN: Device %s, Invalid PHY.\n", dev->name ); } } /* TLan_PhyPrint */ @@ -1888,7 +2115,7 @@ void TLan_PhyPrint( struct device *dev ) /********************************************************************* - * TLan_PhySelect + * TLan_PhyDetect * * Returns: * Nothing @@ -1896,352 +2123,271 @@ void TLan_PhyPrint( struct device *dev ) * dev A pointer to the device structure of the adapter * for which the PHY needs determined. * - * This function decides which PHY amoung those attached to the - * TLAN chip is to be used. The TLAN chip can be attached to - * multiple PHYs, and the driver needs to decide which one to - * talk to. Currently this routine picks the PHY with the lowest - * address as the internal PHY address is 0x1F, the highest - * possible. This strategy assumes that there can be only one - * other PHY, and, if it exists, it is the one to be used. If - * token ring PHYs are ever supported, this routine will become - * a little more interesting... + * So far I've found that adapters which have external PHYs + * may also use the internal PHY for part of the functionality. + * (eg, AUI/Thinnet). This function finds out if this TLAN + * chip has an internal PHY, and then finds the first external + * PHY (starting from address 0) if it exists). * ********************************************************************/ -void TLan_PhySelect( struct device *dev ) +void TLan_PhyDetect( struct device *dev ) { TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; - int phy; - int entry; - u16 id_hi[TLAN_PHY_MAX_ADDR + 1]; - u16 id_lo[TLAN_PHY_MAX_ADDR + 1]; - u16 hi; - u16 lo; - u16 vendor; - u16 device; - - priv->phyCheck = &TLan_PhyNop; /* Make sure these aren't ever NULL */ - priv->phyService = &TLan_PhyNop; - - vendor = TLanDeviceList[priv->pciEntry].vendorId; - device = TLanDeviceList[priv->pciEntry].deviceId; - - /* - * This is a bit uglier than I'd like, but the 0xF130 device must - * NOT be assigned a valid PHY as it uses an unmanaged, bit-rate - * PHY. It is simplest just to use another goto, rather than - * nesting the two for loops in the if statement. - */ - if ( ( vendor == PCI_VENDOR_ID_COMPAQ ) && - ( device == PCI_DEVICE_ID_NETFLEX_3P ) ) { - entry = 0; - phy = 0; - goto FINISH; + u16 control; + u16 hi; + u16 lo; + u32 phy; + + if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) { + priv->phyNum = 0xFFFF; + return; } - for ( phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++ ) { - hi = lo = 0; - TLan_MiiReadReg( dev->base_addr, phy, MII_GEN_ID_HI, &hi ); - TLan_MiiReadReg( dev->base_addr, phy, MII_GEN_ID_LO, &lo ); - id_hi[phy] = hi; - id_lo[phy] = lo; - TLAN_DBG( TLAN_DEBUG_GNRL, - "TLAN: Phy %2x, hi = %hx, lo = %hx\n", - phy, - hi, - lo - ); + TLan_MiiReadReg( dev, TLAN_PHY_MAX_ADDR, MII_GEN_ID_HI, &hi ); + + if ( hi != 0xFFFF ) { + priv->phy[0] = TLAN_PHY_MAX_ADDR; + } else { + priv->phy[0] = TLAN_PHY_NONE; } + priv->phy[1] = TLAN_PHY_NONE; for ( phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++ ) { - if ( ( aui == 1 ) && ( phy != TLAN_PHY_MAX_ADDR ) ) { - if ( id_hi[phy] != 0xFFFF ) { - TLan_MiiSync(dev->base_addr); - TLan_MiiWriteReg(dev->base_addr, - phy, - MII_GEN_CTL, - MII_GC_PDOWN | - MII_GC_LOOPBK | - MII_GC_ISOLATE ); - - } - continue; - } - for ( entry = 0; TLanPhyIdTable[entry].check; entry++) { - if ( ( id_hi[phy] == TLanPhyIdTable[entry].idHi ) && - ( id_lo[phy] == TLanPhyIdTable[entry].idLo ) ) { - TLAN_DBG( TLAN_DEBUG_GNRL, - "TLAN: Selected Phy %hx\n", - phy - ); - goto FINISH; + TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &control ); + TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &hi ); + TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &lo ); + if ( ( control != 0xFFFF ) || ( hi != 0xFFFF ) || ( lo != 0xFFFF ) ) { + TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: PHY found at %02x %04x %04x %04x\n", phy, control, hi, lo ); + if ( ( priv->phy[1] == TLAN_PHY_NONE ) && ( phy != TLAN_PHY_MAX_ADDR ) ) { + priv->phy[1] = phy; } } } - entry = 0; - phy = 0; - -FINISH: - - if ( ( entry == 0 ) && ( phy == 0 ) ) { - priv->phyAddr = phy; - priv->phyEntry = entry; - priv->phyCheck = TLan_PhyNop; - priv->phyService = TLan_PhyNop; - priv->phyFlags = TLAN_PHY_BIT_RATE | - TLAN_PHY_UNMANAGED | - TLAN_PHY_ACTIVITY; + if ( priv->phy[1] != TLAN_PHY_NONE ) { + priv->phyNum = 1; + } else if ( priv->phy[0] != TLAN_PHY_NONE ) { + priv->phyNum = 0; } else { - priv->phyAddr = phy; - priv->phyEntry = entry; - priv->phyCheck = TLanPhyIdTable[entry].check; - priv->phyService = TLanPhyIdTable[entry].service; - priv->phyFlags = TLanPhyIdTable[entry].flags; + printk( "TLAN: Cannot initialize device, no PHY was found!\n" ); } -} /* TLan_PhySelect */ +} /* TLan_PhyDetect */ - /*************************************************************** - * TLan_PhyNop - * - * Returns: - * Nothing - * Parms: - * dev A pointer to a device structure. - * - * This function does nothing and is meant as a stand-in - * for when a Check or Service function would be - * meaningless. - * - **************************************************************/ - -int TLan_PhyNop( struct device *dev ) +void TLan_PhyPowerDown( struct device *dev ) { - dev = NULL; - return 0; + TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; + u16 value; + + TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: %s: Powering down PHY(s).\n", dev->name ); + value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE; + TLan_MiiSync( dev->base_addr ); + TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value ); + if ( ( priv->phyNum == 0 ) && ( priv->phy[1] != TLAN_PHY_NONE ) && ( ! ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) ) ) { + TLan_MiiSync( dev->base_addr ); + TLan_MiiWriteReg( dev, priv->phy[1], MII_GEN_CTL, value ); + } -} /* TLan_PhyNop */ + /* Wait for 5 jiffies (50 ms) and powerup + * This is abitrary. It is intended to make sure the + * tranceiver settles. + */ + TLan_SetTimer( dev, 5, TLAN_TIMER_PHY_PUP ); +} /* TLan_PhyPowerDown */ - /*************************************************************** - * TLan_PhyInternalCheck - * - * Returns: - * Nothing - * Parms: - * dev A pointer to a device structure of the - * adapter holding the PHY to be checked. - * - * This function resets the internal PHY on a TLAN chip. - * See Chap. 7, "Physical Interface (PHY)" of "ThunderLAN - * Programmer's Guide" - * - **************************************************************/ -int TLan_PhyInternalCheck( struct device *dev ) +void TLan_PhyPowerUp( struct device *dev ) { TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; - u16 gen_ctl; - u32 io; - u16 phy; - u16 value; - u8 sio; - - io = dev->base_addr; - phy = priv->phyAddr; - - TLan_MiiReadReg( io, phy, MII_GEN_CTL, &gen_ctl ); - if ( gen_ctl & MII_GC_PDOWN ) { - TLan_MiiSync( io ); - TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE ); - TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK ); - mdelay(50); - TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_RESET | MII_GC_LOOPBK ); - TLan_MiiSync( io ); - } - - TLan_MiiReadReg( io, phy, MII_GEN_CTL, &value ); - while ( value & MII_GC_RESET ) - TLan_MiiReadReg( io, phy, MII_GEN_CTL, &value ); - - /* TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK | MII_GC_DUPLEX ); */ - /* TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_DUPLEX ); */ - TLan_MiiWriteReg( io, phy, MII_GEN_CTL, 0 ); - - mdelay(500); - - TLan_MiiReadReg( io, phy, TLAN_TLPHY_CTL, &value ); - if ( aui ) - value |= TLAN_TC_AUISEL; - else - value &= ~TLAN_TC_AUISEL; - TLan_MiiWriteReg( io, phy, TLAN_TLPHY_CTL, value ); - - /* Read Possible Latched Link Status */ - TLan_MiiReadReg( io, phy, MII_GEN_STS, &value ); - /* Read Real Link Status */ - TLan_MiiReadReg( io, phy, MII_GEN_STS, &value ); - if ( ( value & MII_GS_LINK ) || aui ) { - priv->phyOnline = 1; - TLan_DioWrite8( io, TLAN_LED_REG, TLAN_LED_LINK ); - } else { - priv->phyOnline = 0; - TLan_DioWrite8( io, TLAN_LED_REG, 0 ); - } - - /* Enable Interrupts */ - TLan_MiiReadReg( io, phy, TLAN_TLPHY_CTL, &value ); - value |= TLAN_TC_INTEN; - TLan_MiiWriteReg( io, phy, TLAN_TLPHY_CTL, value ); + u16 value; - sio = TLan_DioRead8( io, TLAN_NET_SIO ); - sio |= TLAN_NET_SIO_MINTEN; - TLan_DioWrite8( io, TLAN_NET_SIO, sio ); - - return 0; + TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: %s: Powering up PHY.\n", dev->name ); + TLan_MiiSync( dev->base_addr ); + value = MII_GC_LOOPBK; + TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value ); -} /* TLanPhyInternalCheck */ + /* Wait for 50 jiffies (500 ms) and reset the + * tranceiver. The TLAN docs say both 50 ms and + * 500 ms, so do the longer, just in case + */ + TLan_SetTimer( dev, 50, TLAN_TIMER_PHY_RESET ); +} /* TLan_PhyPowerUp */ - /*************************************************************** - * TLan_PhyInternalService - * - * Returns: - * Nothing - * Parms: - * dev A pointer to a device structure of the - * adapter holding the PHY to be serviced. - * - * This function services an interrupt generated by the - * internal PHY. It can turn on/off the link LED. See - * Chap. 7, "Physical Interface (PHY)" of "ThunderLAN - * Programmer's Guide". - * - **************************************************************/ -int TLan_PhyInternalService( struct device *dev ) +void TLan_PhyReset( struct device *dev ) { TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; - u16 tlphy_sts; - u16 gen_sts; - u16 an_exp; - u32 io; - u16 phy; - - io = dev->base_addr; - phy = priv->phyAddr; - - TLan_MiiReadReg( io, phy, TLAN_TLPHY_STS, &tlphy_sts ); - TLan_MiiReadReg( io, phy, MII_GEN_STS, &gen_sts ); - TLan_MiiReadReg( io, phy, MII_AN_EXP, &an_exp ); - if ( ( gen_sts & MII_GS_LINK ) || aui ) { - priv->phyOnline = 1; - TLan_DioWrite8( io, TLAN_LED_REG, TLAN_LED_LINK ); - } else { - priv->phyOnline = 0; - TLan_DioWrite8( io, TLAN_LED_REG, 0 ); + u16 phy; + u16 value; + + phy = priv->phy[priv->phyNum]; + + TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: %s: Reseting PHY.\n", dev->name ); + TLan_MiiSync( dev->base_addr ); + value = MII_GC_LOOPBK | MII_GC_RESET; + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, value ); + TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value ); + while ( value & MII_GC_RESET ) { + TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value ); } + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0 ); - if ( ( tlphy_sts & TLAN_TS_POLOK ) == 0) { - u16 value; - TLan_MiiReadReg( io, phy, TLAN_TLPHY_CTL, &value); - value |= TLAN_TC_SWAPOL; - TLan_MiiWriteReg( io, phy, TLAN_TLPHY_CTL, value); - } + /* Wait for 50 jiffies (500 ms) and initialize. + * I don't remember why I wait this long. + */ + TLan_SetTimer( dev, 50, TLAN_TIMER_PHY_START_LINK ); - return 0; +} /* TLan_PhyReset */ -} /* TLan_PhyInternalService */ +void TLan_PhyStartLink( struct device *dev ) +{ + TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; + u16 ability; + u16 control; + u16 data; + u16 phy; + u16 status; + u16 tctl; + + phy = priv->phy[priv->phyNum]; + + TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN: %s: Trying to activate link.\n", dev->name ); + TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status ); + if ( ( status & MII_GS_AUTONEG ) && + ( priv->duplex == TLAN_DUPLEX_DEFAULT ) && + ( priv->speed == TLAN_SPEED_DEFAULT ) && + ( ! priv->aui ) ) { + ability = status >> 11; + + if ( priv->speed == TLAN_SPEED_10 ) { + ability &= 0x0003; + } else if ( priv->speed == TLAN_SPEED_100 ) { + ability &= 0x001C; + } + + if ( priv->duplex == TLAN_DUPLEX_FULL ) { + ability &= 0x000A; + } else if ( priv->duplex == TLAN_DUPLEX_HALF ) { + ability &= 0x0005; + } + + TLan_MiiWriteReg( dev, phy, MII_AN_ADV, ( ability << 5 ) | 1 ); + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 ); + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1200 ); + + /* Wait for 400 jiffies (4 sec) for autonegotiation + * to complete. The max spec time is less than this + * but the card need additional time to start AN. + * .5 sec should be plenty extra. + */ + printk( "TLAN: %s: Starting autonegotiation.\n", dev->name ); + TLan_SetTimer( dev, 400, TLAN_TIMER_PHY_FINISH_AN ); + return; + } + + if ( ( priv->aui ) && ( priv->phyNum != 0 ) ) { + priv->phyNum = 0; + data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN; + TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data ); + TLan_SetTimer( dev, 4, TLAN_TIMER_PHY_PDOWN ); + return; + } else if ( priv->phyNum == 0 ) { + TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tctl ); + if ( priv->aui ) { + tctl |= TLAN_TC_AUISEL; + } else { + tctl &= ~TLAN_TC_AUISEL; + control = 0; + if ( priv->duplex == TLAN_DUPLEX_FULL ) { + control |= MII_GC_DUPLEX; + priv->tlanFullDuplex = TRUE; + } + if ( priv->speed == TLAN_SPEED_100 ) { + control |= MII_GC_SPEEDSEL; + } + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, control ); + } + TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl ); + } + + /* Wait for 100 jiffies (1 sec) to give the tranceiver time + * to establish link. + */ + TLan_SetTimer( dev, 100, TLAN_TIMER_FINISH_RESET ); + +} /* TLan_PhyStartLink */ - /*************************************************************** - * TLan_PhyDp83840aCheck - * - * Returns: - * Nothing - * Parms: - * dev A pointer to a device structure of the - * adapter holding the PHY to be reset. - * - * This function resets a National Semiconductor DP83840A - * 10/100 Mb/s PHY device. See National Semiconductor's - * data sheet for more info. This PHY is used on Compaq - * Netelligent 10/100 cards. - * - **************************************************************/ -static int TLan_PhyDp83840aCheck( struct device *dev ) + + +void TLan_PhyFinishAutoNeg( struct device *dev ) { TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; - u16 gen_ctl; - u32 io; - u16 phy; - u16 value; - u8 sio; - - io = dev->base_addr; - phy = priv->phyAddr; - - TLan_MiiReadReg( io, phy, MII_GEN_CTL, &gen_ctl ); - if ( gen_ctl & MII_GC_PDOWN ) { - TLan_MiiSync( io ); - TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE ); - TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK ); - mdelay(500); - TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_RESET | MII_GC_LOOPBK ); - TLan_MiiSync( io ); - } - - TLan_MiiReadReg( io, phy, MII_GEN_CTL, &value ); - while ( value & MII_GC_RESET ) - TLan_MiiReadReg( io, phy, MII_GEN_CTL, &value ); - - /* TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_LOOPBK | MII_GC_DUPLEX ); */ - /* TLan_MiiWriteReg( io, phy, MII_GEN_CTL, MII_GC_DUPLEX ); */ - TLan_MiiWriteReg( io, phy, MII_GEN_CTL, 0 ); - TLan_MiiReadReg( io, phy, MII_AN_ADV, &value ); - value &= ~0x0140; - TLan_MiiWriteReg( io, phy, MII_AN_ADV, value ); - TLan_MiiWriteReg( io, phy, MII_GEN_CTL, 0x1000 ); - TLan_MiiWriteReg( io, phy, MII_GEN_CTL, 0x1200 ); - - mdelay(50); -#if 0 - /* Read Possible Latched Link Status */ - TLan_MiiReadReg( io, phy, MII_GEN_STS, &value ); - /* Read Real Link Status */ - TLan_MiiReadReg( io, phy, MII_GEN_STS, &value ); - if ( value & MII_GS_LINK ) { - priv->phyOnline = 1; - TLan_DioWrite8( io, TLAN_LED_REG, TLAN_LED_LINK ); - } else { - priv->phyOnline = 0; - TLan_DioWrite8( io, TLAN_LED_REG, 0 ); + u16 an_adv; + u16 an_lpa; + u16 data; + u16 mode; + u16 phy; + u16 status; + + phy = priv->phy[priv->phyNum]; + + TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status ); + if ( ! ( status & MII_GS_AUTOCMPLT ) ) { + /* Wait for 800 jiffies (8 sec) to give the process + * more time. Perhaps we should fail after a while. + */ + printk( "TLAN: Giving autonegotiation more time.\n" ); + TLan_SetTimer( dev, 800, TLAN_TIMER_PHY_FINISH_AN ); + return; } - /* Enable Interrupts */ - TLan_MiiReadReg( io, phy, TLAN_TLPHY_CTL, &value ); - value |= TLAN_TC_INTEN; - TLan_MiiWriteReg( io, phy, TLAN_TLPHY_CTL, value ); -#endif - sio = TLan_DioRead8( dev->base_addr, TLAN_NET_SIO ); - sio &= ~TLAN_NET_SIO_MINTEN; - TLan_DioWrite8( dev->base_addr, TLAN_NET_SIO, sio ); -/* priv->phyOnline = 1; */ - - return 0; + printk( "TLAN: %s: Autonegotiation complete.\n", dev->name ); + TLan_MiiReadReg( dev, phy, MII_AN_ADV, &an_adv ); + TLan_MiiReadReg( dev, phy, MII_AN_LPA, &an_lpa ); + mode = an_adv & an_lpa & 0x03E0; + if ( mode & 0x0100 ) { + priv->tlanFullDuplex = TRUE; + } else if ( ! ( mode & 0x0080 ) && ( mode & 0x0040 ) ) { + priv->tlanFullDuplex = TRUE; + } + + if ( ( ! ( mode & 0x0180 ) ) && ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) && ( priv->phyNum != 0 ) ) { + priv->phyNum = 0; + data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN; + TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data ); + TLan_SetTimer( dev, 40, TLAN_TIMER_PHY_PDOWN ); + return; + } + + if ( priv->phyNum == 0 ) { + if ( ( priv->duplex == TLAN_DUPLEX_FULL ) || ( an_adv & an_lpa & 0x0040 ) ) { + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, MII_GC_AUTOENB | MII_GC_DUPLEX ); + printk( "TLAN: Starting internal PHY with DUPLEX\n" ); + } else { + TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, MII_GC_AUTOENB ); + printk( "TLAN: Starting internal PHY with HALF-DUPLEX\n" ); + } + } -} /* TLan_PhyDp83840aCheck */ + /* Wait for 10 jiffies (100 ms). No reason in partiticular. + */ + TLan_SetTimer( dev, 10, TLAN_TIMER_FINISH_RESET ); + +} /* TLan_PhyFinishAutoNeg */ @@ -2266,9 +2412,10 @@ static int TLan_PhyDp83840aCheck( struct device *dev ) * 1 otherwise. * * Parms: - * base_port The base IO port of the adapter in - * question. - * dev The address of the PHY to be queried. + * dev The device structure containing + * The io address and interrupt count + * for this device. + * phy The address of the PHY to be queried. * reg The register whose contents are to be * retreived. * val A pointer to a variable to store the @@ -2281,30 +2428,32 @@ static int TLan_PhyDp83840aCheck( struct device *dev ) * **************************************************************/ -int TLan_MiiReadReg(u16 base_port, u16 dev, u16 reg, u16 *val) +int TLan_MiiReadReg( struct device *dev, u16 phy, u16 reg, u16 *val ) { u8 nack; - u16 sio, tmp; - u32 i; + u16 sio, tmp; + u32 i; int err; - int minten; + int minten; err = FALSE; - outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR); - sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO; + outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR); + sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO; - cli(); + if ( dev->interrupt == 0 ) + cli(); + dev->interrupt++; - TLan_MiiSync(base_port); + TLan_MiiSync(dev->base_addr); minten = TLan_GetBit( TLAN_NET_SIO_MINTEN, sio ); if ( minten ) TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio); - TLan_MiiSendData( base_port, 0x1, 2 ); /* Start ( 01b ) */ - TLan_MiiSendData( base_port, 0x2, 2 ); /* Read ( 10b ) */ - TLan_MiiSendData( base_port, dev, 5 ); /* Device # */ - TLan_MiiSendData( base_port, reg, 5 ); /* Register # */ + TLan_MiiSendData( dev->base_addr, 0x1, 2 ); /* Start ( 01b ) */ + TLan_MiiSendData( dev->base_addr, 0x2, 2 ); /* Read ( 10b ) */ + TLan_MiiSendData( dev->base_addr, phy, 5 ); /* Device # */ + TLan_MiiSendData( dev->base_addr, reg, 5 ); /* Register # */ TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio); /* Change direction */ @@ -2340,7 +2489,9 @@ int TLan_MiiReadReg(u16 base_port, u16 dev, u16 reg, u16 *val) *val = tmp; - sti(); + dev->interrupt--; + if ( dev->interrupt == 0 ) + sti(); return err; @@ -2434,9 +2585,9 @@ void TLan_MiiSync( u16 base_port ) * Returns: * Nothing * Parms: - * base_port The base IO port of the adapter in - * question. - * dev The address of the PHY to be written to. + * dev The device structure for the device + * to write to. + * phy The address of the PHY to be written to. * reg The register whose contents are to be * written. * val The value to be written to the register. @@ -2448,29 +2599,31 @@ void TLan_MiiSync( u16 base_port ) * **************************************************************/ -void TLan_MiiWriteReg(u16 base_port, u16 dev, u16 reg, u16 val) +void TLan_MiiWriteReg( struct device *dev, u16 phy, u16 reg, u16 val ) { - u16 sio; + u16 sio; int minten; - outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR); - sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO; + outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR); + sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO; - cli(); + if ( dev->interrupt == 0 ) + cli(); + dev->interrupt++; - TLan_MiiSync( base_port ); + TLan_MiiSync( dev->base_addr ); minten = TLan_GetBit( TLAN_NET_SIO_MINTEN, sio ); if ( minten ) TLan_ClearBit( TLAN_NET_SIO_MINTEN, sio ); - TLan_MiiSendData( base_port, 0x1, 2 ); /* Start ( 01b ) */ - TLan_MiiSendData( base_port, 0x1, 2 ); /* Write ( 01b ) */ - TLan_MiiSendData( base_port, dev, 5 ); /* Device # */ - TLan_MiiSendData( base_port, reg, 5 ); /* Register # */ + TLan_MiiSendData( dev->base_addr, 0x1, 2 ); /* Start ( 01b ) */ + TLan_MiiSendData( dev->base_addr, 0x1, 2 ); /* Write ( 01b ) */ + TLan_MiiSendData( dev->base_addr, phy, 5 ); /* Device # */ + TLan_MiiSendData( dev->base_addr, reg, 5 ); /* Register # */ - TLan_MiiSendData( base_port, 0x2, 2 ); /* Send ACK */ - TLan_MiiSendData( base_port, val, 16 ); /* Send Data */ + TLan_MiiSendData( dev->base_addr, 0x2, 2 ); /* Send ACK */ + TLan_MiiSendData( dev->base_addr, val, 16 ); /* Send Data */ TLan_ClearBit( TLAN_NET_SIO_MCLK, sio ); /* Idle cycle */ TLan_SetBit( TLAN_NET_SIO_MCLK, sio ); @@ -2478,10 +2631,15 @@ void TLan_MiiWriteReg(u16 base_port, u16 dev, u16 reg, u16 val) if ( minten ) TLan_SetBit( TLAN_NET_SIO_MINTEN, sio ); - sti(); + dev->interrupt--; + if ( dev->interrupt == 0 ) + sti(); } /* TLan_MiiWriteReg */ + + + /***************************************************************************** ****************************************************************************** @@ -2654,7 +2812,7 @@ void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop ) * * Returns: * No error = 0, else, the stage at which the error - * occurred. + * occured. * Parms: * io_base The IO port base address for the * TLAN device with the EEPROM to @@ -2670,26 +2828,30 @@ void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop ) * **************************************************************/ -int TLan_EeReadByte( u16 io_base, u8 ee_addr, u8 *data ) +int TLan_EeReadByte( struct device *dev, u8 ee_addr, u8 *data ) { int err; - cli(); + if ( dev->interrupt == 0 ) + cli(); + dev->interrupt++; - TLan_EeSendStart( io_base ); - err = TLan_EeSendByte( io_base, 0xA0, TLAN_EEPROM_ACK ); + TLan_EeSendStart( dev->base_addr ); + err = TLan_EeSendByte( dev->base_addr, 0xA0, TLAN_EEPROM_ACK ); if (err) return 1; - err = TLan_EeSendByte( io_base, ee_addr, TLAN_EEPROM_ACK ); + err = TLan_EeSendByte( dev->base_addr, ee_addr, TLAN_EEPROM_ACK ); if (err) return 2; - TLan_EeSendStart( io_base ); - err = TLan_EeSendByte( io_base, 0xA1, TLAN_EEPROM_ACK ); + TLan_EeSendStart( dev->base_addr ); + err = TLan_EeSendByte( dev->base_addr, 0xA1, TLAN_EEPROM_ACK ); if (err) return 3; - TLan_EeReceiveByte( io_base, data, TLAN_EEPROM_STOP ); + TLan_EeReceiveByte( dev->base_addr, data, TLAN_EEPROM_STOP ); - sti(); + dev->interrupt--; + if ( dev->interrupt == 0 ) + sti(); return 0; diff --git a/drivers/net/tlan.h b/drivers/net/tlan.h index 94613d3a6493..a66e26c2873c 100644 --- a/drivers/net/tlan.h +++ b/drivers/net/tlan.h @@ -5,9 +5,9 @@ * Linux ThunderLAN Driver * * tlan.h - * by James Banks, james.banks@caldera.com + * by James Banks * - * (C) 1997 Caldera, Inc. + * (C) 1997-1998 Caldera, Inc. * * This software may be used and distributed according to the terms * of the GNU Public License, incorporated herein by reference. @@ -33,23 +33,23 @@ * ****************************************************************/ -#define FALSE 0 -#define TRUE 1 +#define FALSE 0 +#define TRUE 1 #define TLAN_MIN_FRAME_SIZE 64 #define TLAN_MAX_FRAME_SIZE 1600 -#define TLAN_NUM_RX_LISTS 4 -#define TLAN_NUM_TX_LISTS 8 +#define TLAN_NUM_RX_LISTS 4 +#define TLAN_NUM_TX_LISTS 8 -#define TLAN_IGNORE 0 -#define TLAN_RECORD 1 +#define TLAN_IGNORE 0 +#define TLAN_RECORD 1 #define TLAN_DBG(lvl, format, args...) if (debug&lvl) printk( format, ##args ); -#define TLAN_DEBUG_GNRL 0x0001 -#define TLAN_DEBUG_TX 0x0002 -#define TLAN_DEBUG_RX 0x0004 -#define TLAN_DEBUG_LIST 0x0008 +#define TLAN_DEBUG_GNRL 0x0001 +#define TLAN_DEBUG_TX 0x0002 +#define TLAN_DEBUG_RX 0x0004 +#define TLAN_DEBUG_LIST 0x0008 @@ -59,23 +59,47 @@ * ****************************************************************/ - /* NOTE: These have been moved to pci.h, will use them - eventually */ -#define PCI_DEVICE_ID_NETELLIGENT_10 0xAE34 -#define PCI_DEVICE_ID_NETELLIGENT_10_100 0xAE32 -#define PCI_DEVICE_ID_NETFLEX_3P_INTEGRATED 0xAE35 -#define PCI_DEVICE_ID_NETFLEX_3P 0xF130 -#define PCI_DEVICE_ID_NETFLEX_3P_BNC 0xF150 -#define PCI_DEVICE_ID_NETELLIGENT_10_100_PROLIANT 0xAE43 -#define PCI_DEVICE_ID_NETELLIGENT_10_100_DUAL 0xAE40 -#define PCI_DEVICE_ID_DESKPRO_4000_5233MMX 0xB011 - - -typedef struct tlan_pci_id { +#define PCI_DEVICE_ID_NETELLIGENT_10 0xAE34 +#define PCI_DEVICE_ID_NETELLIGENT_10_100 0xAE32 +#define PCI_DEVICE_ID_NETFLEX_3P_INTEGRATED 0xAE35 +#define PCI_DEVICE_ID_NETFLEX_3P 0xF130 +#define PCI_DEVICE_ID_NETFLEX_3P_BNC 0xF150 +#define PCI_DEVICE_ID_NETELLIGENT_10_100_PROLIANT 0xAE43 +#define PCI_DEVICE_ID_NETELLIGENT_10_100_DUAL 0xAE40 +#define PCI_DEVICE_ID_DESKPRO_4000_5233MMX 0xB011 +#define PCI_DEVICE_ID_NETELLIGENT_10_T2 0xB012 +#define PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100 0xB030 +#ifndef PCI_DEVICE_ID_OLICOM_OC2183 +#define PCI_DEVICE_ID_OLICOM_OC2183 0x0013 +#endif +#ifndef PCI_DEVICE_ID_OLICOM_OC2325 +#define PCI_DEVICE_ID_OLICOM_OC2325 0x0012 +#endif +#ifndef PCI_DEVICE_ID_OLICOM_OC2326 +#define PCI_DEVICE_ID_OLICOM_OC2326 0x0014 +#endif + +typedef struct tlan_adapter_entry { u16 vendorId; u16 deviceId; - char *deviceName; -} TLanPciId; + char *deviceLabel; + u32 flags; + u16 addrOfs; +} TLanAdapterEntry; + +#define TLAN_ADAPTER_NONE 0x00000000 +#define TLAN_ADAPTER_UNMANAGED_PHY 0x00000001 +#define TLAN_ADAPTER_BIT_RATE_PHY 0x00000002 +#define TLAN_ADAPTER_USE_INTERN_10 0x00000004 +#define TLAN_ADAPTER_ACTIVITY_LED 0x00000008 + +#define TLAN_SPEED_DEFAULT 0 +#define TLAN_SPEED_10 10 +#define TLAN_SPEED_100 100 + +#define TLAN_DUPLEX_DEFAULT 0 +#define TLAN_DUPLEX_HALF 1 +#define TLAN_DUPLEX_FULL 2 @@ -121,25 +145,7 @@ typedef u8 TLanBuffer[TLAN_MAX_FRAME_SIZE]; ****************************************************************/ #define TLAN_PHY_MAX_ADDR 0x1F - -#define TLAN_PHY_ACTIVITY 0x00000001 -#define TLAN_PHY_AUTONEG 0x00000002 -#define TLAN_PHY_INTS 0x00000004 -#define TLAN_PHY_BIT_RATE 0x00000008 -#define TLAN_PHY_UNMANAGED 0x00000010 -#define TLAN_PHY_INTERNAL 0x00000020 - - -typedef int (TLanPhyFunc)( struct device * ); - - -typedef struct tlan_phy_id_entry_tag { - u16 idHi; - u16 idLo; - TLanPhyFunc *check; - TLanPhyFunc *service; - u32 flags; -} TLanPhyIdEntry; +#define TLAN_PHY_NONE 0x20 @@ -164,21 +170,22 @@ typedef struct tlan_private_tag { u32 txInProgress; u32 txTail; u32 txBusyCount; - u32 phyAddr; - u32 phyEntry; u32 phyOnline; - u32 phyFlags; - TLanPhyFunc *phyCheck; - TLanPhyFunc *phyService; u32 timerSetAt; u32 timerType; struct timer_list timer; struct net_device_stats stats; - u32 pciEntry; - u8 pciRevision; - u8 pciBus; - u8 pciDeviceFn; + TLanAdapterEntry *adapter; + u32 adapterRev; + u32 aui; + u32 debug; + u32 duplex; + u32 phy[2]; + u32 phyNum; + u32 sa_int; + u32 speed; u8 tlanRev; + u8 tlanFullDuplex; char devName[8]; } TLanPrivateInfo; @@ -191,10 +198,15 @@ typedef struct tlan_private_tag { ****************************************************************/ #define TLAN_TIMER_LINK 1 -#define TLAN_TIMER_ACT 2 +#define TLAN_TIMER_ACTIVITY 2 +#define TLAN_TIMER_PHY_PDOWN 3 +#define TLAN_TIMER_PHY_PUP 4 +#define TLAN_TIMER_PHY_RESET 5 +#define TLAN_TIMER_PHY_START_LINK 6 +#define TLAN_TIMER_PHY_FINISH_AN 7 +#define TLAN_TIMER_FINISH_RESET 8 -#define TLAN_TIMER_LINK_DELAY 230 -#define TLAN_TIMER_ACT_DELAY 10 +#define TLAN_TIMER_ACT_DELAY 10 @@ -215,29 +227,29 @@ typedef struct tlan_private_tag { * ****************************************************************/ -#define TLAN_HOST_CMD 0x00 +#define TLAN_HOST_CMD 0x00 #define TLAN_HC_GO 0x80000000 -#define TLAN_HC_STOP 0x40000000 +#define TLAN_HC_STOP 0x40000000 #define TLAN_HC_ACK 0x20000000 -#define TLAN_HC_CS_MASK 0x1FE00000 +#define TLAN_HC_CS_MASK 0x1FE00000 #define TLAN_HC_EOC 0x00100000 #define TLAN_HC_RT 0x00080000 #define TLAN_HC_NES 0x00040000 -#define TLAN_HC_AD_RST 0x00008000 -#define TLAN_HC_LD_TMR 0x00004000 -#define TLAN_HC_LD_THR 0x00002000 -#define TLAN_HC_REQ_INT 0x00001000 -#define TLAN_HC_INT_OFF 0x00000800 -#define TLAN_HC_INT_ON 0x00000400 -#define TLAN_HC_AC_MASK 0x000000FF -#define TLAN_CH_PARM 0x04 -#define TLAN_DIO_ADR 0x08 -#define TLAN_DA_ADR_INC 0x8000 -#define TLAN_DA_RAM_ADR 0x4000 -#define TLAN_HOST_INT 0x0A -#define TLAN_HI_IV_MASK 0x1FE0 -#define TLAN_HI_IT_MASK 0x001C -#define TLAN_DIO_DATA 0x0C +#define TLAN_HC_AD_RST 0x00008000 +#define TLAN_HC_LD_TMR 0x00004000 +#define TLAN_HC_LD_THR 0x00002000 +#define TLAN_HC_REQ_INT 0x00001000 +#define TLAN_HC_INT_OFF 0x00000800 +#define TLAN_HC_INT_ON 0x00000400 +#define TLAN_HC_AC_MASK 0x000000FF +#define TLAN_CH_PARM 0x04 +#define TLAN_DIO_ADR 0x08 +#define TLAN_DA_ADR_INC 0x8000 +#define TLAN_DA_RAM_ADR 0x4000 +#define TLAN_HOST_INT 0x0A +#define TLAN_HI_IV_MASK 0x1FE0 +#define TLAN_HI_IT_MASK 0x001C +#define TLAN_DIO_DATA 0x0C /* ThunderLAN Internal Register DIO Offsets */ @@ -264,7 +276,7 @@ typedef struct tlan_private_tag { #define TLAN_NET_STS_MIRQ 0x80 #define TLAN_NET_STS_HBEAT 0x40 #define TLAN_NET_STS_TXSTOP 0x20 -#define TLAN_NET_STS_RXSTOP 0x10 +#define TLAN_NET_STS_RXSTOP 0x10 #define TLAN_NET_STS_RSRVD 0x0F #define TLAN_NET_MASK 0x03 #define TLAN_NET_MASK_MASK7 0x80 @@ -283,36 +295,36 @@ typedef struct tlan_private_tag { #define TLAN_NET_CFG_MTEST 0x0100 #define TLAN_NET_CFG_PHY_EN 0x0080 #define TLAN_NET_CFG_MSMASK 0x007F -#define TLAN_MAN_TEST 0x06 -#define TLAN_DEF_VENDOR_ID 0x08 -#define TLAN_DEF_DEVICE_ID 0x0A -#define TLAN_DEF_REVISION 0x0C -#define TLAN_DEF_SUBCLASS 0x0D -#define TLAN_DEF_MIN_LAT 0x0E -#define TLAN_DEF_MAX_LAT 0x0F +#define TLAN_MAN_TEST 0x06 +#define TLAN_DEF_VENDOR_ID 0x08 +#define TLAN_DEF_DEVICE_ID 0x0A +#define TLAN_DEF_REVISION 0x0C +#define TLAN_DEF_SUBCLASS 0x0D +#define TLAN_DEF_MIN_LAT 0x0E +#define TLAN_DEF_MAX_LAT 0x0F #define TLAN_AREG_0 0x10 #define TLAN_AREG_1 0x16 #define TLAN_AREG_2 0x1C #define TLAN_AREG_3 0x22 #define TLAN_HASH_1 0x28 #define TLAN_HASH_2 0x2C -#define TLAN_GOOD_TX_FRMS 0x30 -#define TLAN_TX_UNDERUNS 0x33 -#define TLAN_GOOD_RX_FRMS 0x34 -#define TLAN_RX_OVERRUNS 0x37 -#define TLAN_DEFERRED_TX 0x38 -#define TLAN_CRC_ERRORS 0x3A -#define TLAN_CODE_ERRORS 0x3B -#define TLAN_MULTICOL_FRMS 0x3C -#define TLAN_SINGLECOL_FRMS 0x3E -#define TLAN_EXCESSCOL_FRMS 0x40 -#define TLAN_LATE_COLS 0x41 -#define TLAN_CARRIER_LOSS 0x42 -#define TLAN_ACOMMIT 0x43 -#define TLAN_LED_REG 0x44 -#define TLAN_LED_ACT 0x10 -#define TLAN_LED_LINK 0x01 -#define TLAN_BSIZE_REG 0x45 +#define TLAN_GOOD_TX_FRMS 0x30 +#define TLAN_TX_UNDERUNS 0x33 +#define TLAN_GOOD_RX_FRMS 0x34 +#define TLAN_RX_OVERRUNS 0x37 +#define TLAN_DEFERRED_TX 0x38 +#define TLAN_CRC_ERRORS 0x3A +#define TLAN_CODE_ERRORS 0x3B +#define TLAN_MULTICOL_FRMS 0x3C +#define TLAN_SINGLECOL_FRMS 0x3E +#define TLAN_EXCESSCOL_FRMS 0x40 +#define TLAN_LATE_COLS 0x41 +#define TLAN_CARRIER_LOSS 0x42 +#define TLAN_ACOMMIT 0x43 +#define TLAN_LED_REG 0x44 +#define TLAN_LED_ACT 0x10 +#define TLAN_LED_LINK 0x01 +#define TLAN_BSIZE_REG 0x45 #define TLAN_MAX_RX 0x46 #define TLAN_INT_DIS 0x48 #define TLAN_ID_TX_EOC 0x04 @@ -327,11 +339,11 @@ typedef struct tlan_private_tag { #define TLAN_INT_NONE 0x0000 #define TLAN_INT_TX_EOF 0x0001 -#define TLAN_INT_STAT_OVERFLOW 0x0002 +#define TLAN_INT_STAT_OVERFLOW 0x0002 #define TLAN_INT_RX_EOF 0x0003 #define TLAN_INT_DUMMY 0x0004 #define TLAN_INT_TX_EOC 0x0005 -#define TLAN_INT_STATUS_CHECK 0x0006 +#define TLAN_INT_STATUS_CHECK 0x0006 #define TLAN_INT_RX_EOC 0x0007 @@ -340,7 +352,7 @@ typedef struct tlan_private_tag { /* Generic MII/PHY Registers */ -#define MII_GEN_CTL 0x00 +#define MII_GEN_CTL 0x00 #define MII_GC_RESET 0x8000 #define MII_GC_LOOPBK 0x4000 #define MII_GC_SPEEDSEL 0x2000 @@ -351,7 +363,7 @@ typedef struct tlan_private_tag { #define MII_GC_DUPLEX 0x0100 #define MII_GC_COLTEST 0x0080 #define MII_GC_RESERVED 0x007F -#define MII_GEN_STS 0x01 +#define MII_GEN_STS 0x01 #define MII_GS_100BT4 0x8000 #define MII_GS_100BTXFD 0x4000 #define MII_GS_100BTXHD 0x2000 @@ -359,19 +371,19 @@ typedef struct tlan_private_tag { #define MII_GS_10BTHD 0x0800 #define MII_GS_RESERVED 0x07C0 #define MII_GS_AUTOCMPLT 0x0020 -#define MII_GS_RFLT 0x0010 +#define MII_GS_RFLT 0x0010 #define MII_GS_AUTONEG 0x0008 -#define MII_GS_LINK 0x0004 +#define MII_GS_LINK 0x0004 #define MII_GS_JABBER 0x0002 #define MII_GS_EXTCAP 0x0001 #define MII_GEN_ID_HI 0x02 #define MII_GEN_ID_LO 0x03 -#define MII_GIL_OUI 0xFC00 +#define MII_GIL_OUI 0xFC00 #define MII_GIL_MODEL 0x03F0 #define MII_GIL_REVISION 0x000F -#define MII_AN_ADV 0x04 -#define MII_AN_LPA 0x05 -#define MII_AN_EXP 0x06 +#define MII_AN_ADV 0x04 +#define MII_AN_LPA 0x05 +#define MII_AN_EXP 0x06 /* ThunderLAN Specific MII/PHY Registers */ @@ -394,6 +406,7 @@ typedef struct tlan_private_tag { #define TLAN_TS_RESERVED 0x0FFF +#define CIRC_INC( a, b ) if ( ++a >= b ) a = 0 /* Routines to access internal registers. */ @@ -456,7 +469,7 @@ inline void TLan_DioWrite32(u16 base_addr, u16 internal_addr, u32 data) - +#if 0 inline void TLan_ClearBit(u8 bit, u16 port) { outb_p(inb_p(port) & ~bit, port); @@ -477,6 +490,11 @@ inline void TLan_SetBit(u8 bit, u16 port) { outb_p(inb_p(port) | bit, port); } +#endif + +#define TLan_ClearBit( bit, port ) outb_p(inb_p(port) & ~bit, port) +#define TLan_GetBit( bit, port ) ((int) (inb_p(port) & bit)) +#define TLan_SetBit( bit, port ) outb_p(inb_p(port) | bit, port) inline u32 xor( u32 a, u32 b ) diff --git a/drivers/pnp/parport_probe.c b/drivers/pnp/parport_probe.c index 8b735fb52511..00f3c1f3ceea 100644 --- a/drivers/pnp/parport_probe.c +++ b/drivers/pnp/parport_probe.c @@ -173,11 +173,18 @@ static void parse_data(struct parport *port, char *str) u++; } if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) { + if (port->probe_info.mfr) + kfree (port->probe_info.mfr); port->probe_info.mfr = strdup(sep); } else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) { + if (port->probe_info.model) + kfree (port->probe_info.model); port->probe_info.model = strdup(sep); } else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) { int i; + if (port->probe_info.class_name) + kfree (port->probe_info.class_name); + port->probe_info.class_name = strdup(sep); for (u = sep; *u; u++) *u = toupper(*u); for (i = 0; classes[i].token; i++) { @@ -189,11 +196,16 @@ static void parse_data(struct parport *port, char *str) printk(KERN_WARNING "%s probe: warning, class '%s' not understood.\n", port->name, sep); port->probe_info.class = PARPORT_CLASS_OTHER; } else if (!strcmp(p, "CMD") || !strcmp(p, "COMMAND SET")) { + if (port->probe_info.cmdset) + kfree (port->probe_info.cmdset); + port->probe_info.cmdset = strdup(sep); /* if it speaks printer language, it's probably a printer */ if (strstr(sep, "PJL") || strstr(sep, "PCL")) guessed_class = PARPORT_CLASS_PRINTER; } else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) { + if (port->probe_info.description) + kfree (port->probe_info.description); port->probe_info.description = strdup(sep); } } @@ -226,10 +238,11 @@ void parport_probe_one(struct parport *port) int r; MOD_INC_USE_COUNT; - port->probe_info.model = "Unknown device"; - port->probe_info.mfr = "Unknown vendor"; - port->probe_info.description = NULL; + port->probe_info.model = strdup ("Unknown device"); + port->probe_info.mfr = strdup ("Unknown vendor"); + port->probe_info.description = port->probe_info.cmdset = NULL; port->probe_info.class = PARPORT_CLASS_UNSPEC; + port->probe_info.class_name = NULL; if (!buffer) { printk(KERN_ERR "%s probe: Memory squeeze.\n", port->name); diff --git a/drivers/scsi/ChangeLog.ncr53c8xx b/drivers/scsi/ChangeLog.ncr53c8xx index 5b4bc482913f..3033cf972e27 100644 --- a/drivers/scsi/ChangeLog.ncr53c8xx +++ b/drivers/scsi/ChangeLog.ncr53c8xx @@ -1,3 +1,21 @@ +Sar Jul 18 13:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.0g + - Preliminary fixes for Big Endian (sent by Eddie C. Dost). + Big Endian architectures should work again with the driver. + Eddie's patch has been partially applied since current 2.1.109 + does not have all the Sparc changes of the vger tree. + - Use of BITS_PER_LONG instead of (~0UL == 0xffffffffUL) has fixed + the problem observed when the driver was compiled using EGCS or + PGCC. + +Mon Jul 13 20:00 1998 Gerard Roudier (groudier@club-internet.fr) + * revision 3.0f + - Some spelling fixes. + - linux/config.h misplaced in ncr53c8xx.h + - MODULE_PARM stuff added for linux 2.1. + - check INQUIRY response data format is exactly 2. + - use BITS_PER_LONG if defined. + Sun Jun 28 12:00 1998 Gerard Roudier (groudier@club-internet.fr) * revision 3.0e - Some cleanup, spelling fixes, version checks, documentations diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index ddde013e7e81..d614ac7fb79e 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -73,7 +73,7 @@ */ /* -** 28 June 1998, version 3.0e +** 16 July 1998, version 3.0g ** ** Supported SCSI-II features: ** Synchronous negotiation @@ -157,6 +157,17 @@ #include +/* +** Define BITS_PER_LONG for earlier linux versions. +*/ +#ifndef BITS_PER_LONG +#if (~0UL) == 0xffffffffUL +#define BITS_PER_LONG 32 +#else +#define BITS_PER_LONG 64 +#endif +#endif + /* ** Define the BSD style u_int32 type */ @@ -278,7 +289,7 @@ static inline struct xpt_quehead *xpt_remque_tail(struct xpt_quehead *head) #define CCB_DONE_EMPTY 0xffffffffUL /* All 32 bit architectures */ -#if (~0UL) == 0xffffffffUL +#if BITS_PER_LONG == 32 #define CCB_DONE_VALID(cp) (((u_long) cp) != CCB_DONE_EMPTY) /* All > 32 bit (64 bit) architectures regardless endian-ness */ @@ -760,9 +771,12 @@ static struct ncr_driver_setup #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT static struct ncr_driver_setup driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP; -#ifdef MODULE +# ifdef MODULE char *ncr53c8xx = 0; /* command line passed by insmod */ -#endif +# if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30) +MODULE_PARM(ncr53c8xx, "s"); +# endif +# endif #endif /* @@ -5276,7 +5290,7 @@ static void ncr_start_next_ccb(ncb_p np, lcb_p lp, int maxn) cp = xpt_que_entry(qp, struct ccb, link_ccbq); xpt_insque_tail(qp, &lp->busy_ccbq); lp->jump_ccb[cp->tag == NO_TAG ? 0 : cp->tag].l_paddr = - cpu_to_scr(cp->p_ccb + offsetof(struct ccb, restart)); + cpu_to_scr(CCB_PHYS (cp, restart)); ncr_put_start_queue(np, cp); } } @@ -6855,7 +6869,7 @@ static void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat) if (((script_ofs & 3) == 0) && (unsigned)script_ofs < script_size) { printk ("%s: script cmd = %08x\n", ncr_name(np), - (int) *(ncrcmd *)(script_base + script_ofs)); + scr_to_cpu((int) *(ncrcmd *)(script_base + script_ofs))); } printk ("%s: regdump:", ncr_name(np)); @@ -7732,7 +7746,7 @@ void ncr_int_sir (ncb_p np) ** We just assume lun=0, 1 CCB, no tag. */ if (tp->lp[0]) { - OUTL (nc_dsp, tp->lp[0]->jump_ccb[0].l_paddr); + OUTL (nc_dsp, scr_to_cpu(tp->lp[0]->jump_ccb[0].l_paddr)); return; } case SIR_RESEL_BAD_TARGET: /* Will send a TARGET RESET message */ @@ -8398,7 +8412,7 @@ static void ncr_init_ccb(ncb_p np, ccb_p cp) cp->start.setup_dsa[1] = cpu_to_scr(vtophys(&cp->start.p_phys)); cp->start.setup_dsa[2] = cpu_to_scr(ncr_reg_bus_addr(nc_dsa)); cp->start.schedule.l_cmd = cpu_to_scr(SCR_JUMP); - cp->start.p_phys = vtophys(&cp->phys); + cp->start.p_phys = cpu_to_scr(vtophys(&cp->phys)); bcopy(&cp->start, &cp->restart, sizeof(cp->restart)); @@ -8543,7 +8557,7 @@ static void ncr_setup_jump_ccb(ncb_p np, lcb_p lp) { int i; - lp->p_jump_ccb = vtophys(lp->jump_ccb); + lp->p_jump_ccb = cpu_to_scr(vtophys(lp->jump_ccb)); for (i = 0 ; i < lp->maxnxs ; i++) { #if SCSI_NCR_MAX_TAGS <= 32 lp->jump_ccb[i].l_cmd = cpu_to_scr(SCR_JUMP); @@ -8680,10 +8694,10 @@ static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln, u_char *inq_data) /* ** Evaluate trustable target/unit capabilities. ** We only believe device version >= SCSI-2 that - ** use appropriate response data format. + ** use appropriate response data format (2). */ inq_byte7 = 0; - if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0x7) >= 2) + if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2) inq_byte7 = inq_data[7]; /* diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h index 8a8403ed207c..9dcd08a01a95 100644 --- a/drivers/scsi/ncr53c8xx.h +++ b/drivers/scsi/ncr53c8xx.h @@ -42,20 +42,10 @@ #ifndef NCR53C8XX_H #define NCR53C8XX_H -#include - -#if 0 -#define CONFIG_SCSI_NCR53C8XX_PROFILE -#endif - -#ifndef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT -#define CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT -#endif - /* ** Name and revision of the driver */ -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 3.0e" +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 3.0g" /* ** Check supported Linux versions @@ -64,11 +54,19 @@ #if !defined(LINUX_VERSION_CODE) #include #endif +#include #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) /* -** These options are'nt tunable from 'make config' + * No more an option, enabled by default. + */ +#ifndef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT +#define CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT +#endif + +/* +** These options are not tunable from 'make config' */ #define SCSI_NCR_PROC_INFO_SUPPORT #define SCSI_NCR_SHARE_IRQ diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index c4708f617781..eef5f79c3afa 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -199,10 +199,10 @@ wavefront.o: $(wavefront-objs) # First make the utilities. bin2hex: bin2hex.c - $(HOSTCC) -o bin2hex bin2hex.c + $(HOSTCC) $(HOSTCFLAGS) -o bin2hex bin2hex.c hex2hex: hex2hex.c - $(HOSTCC) -o hex2hex hex2hex.c + $(HOSTCC) $(HOSTCFLAGS) -o hex2hex hex2hex.c diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c index 9b3b667fcccc..bc12097312b0 100644 --- a/drivers/video/macmodes.c +++ b/drivers/video/macmodes.c @@ -9,7 +9,6 @@ */ -#include #include #include #include diff --git a/drivers/video/promcon.c b/drivers/video/promcon.c index a0be44dfaef5..fadf8876c2fa 100644 --- a/drivers/video/promcon.c +++ b/drivers/video/promcon.c @@ -5,7 +5,6 @@ * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) */ -#include #include #include #include diff --git a/drivers/video/vgacon.c b/drivers/video/vgacon.c index 9d1f03bb0b92..7a191efd69f1 100644 --- a/drivers/video/vgacon.c +++ b/drivers/video/vgacon.c @@ -42,6 +42,7 @@ * KNOWN PROBLEMS/TO DO ==================================================== */ +#include #include #include #include diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c index 7726ce9c6540..73fa6ddfe0f1 100644 --- a/fs/coda/psdev.c +++ b/fs/coda/psdev.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -401,15 +402,7 @@ static struct file_operations coda_psdev_fops = { #ifdef CONFIG_PROC_FS -struct proc_dir_entry proc_sys_root = { - PROC_SYS, 3, "sys", /* inode, name */ - S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, /* mode, nlink, uid, gid */ - 0, &proc_dir_inode_operations, /* size, ops */ - NULL, NULL, /* get_info, fill_inode */ - NULL, /* next */ - NULL, NULL /* parent, subdir */ -}; - +extern struct proc_dir_entry proc_sys_root; struct proc_dir_entry proc_sys_coda = { 0, 4, "coda", diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 0d533e621850..049ca25b9bd8 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c @@ -39,6 +39,8 @@ #include #include +extern void coda_purge_dentries(struct inode *inode); +extern void coda_purge_children(struct inode *inode); static int coda_upcall(struct coda_sb_info *mntinfo, int inSize, int *outSize, union inputArgs *buffer); diff --git a/fs/dcache.c b/fs/dcache.c index 0ef962687b27..f3e6245c7763 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -438,9 +438,13 @@ void shrink_dcache_parent(struct dentry * parent) */ void shrink_dcache_memory(int priority, unsigned int gfp_mask) { +#if 0 int count = select_dcache(32, 8); if (count) prune_dcache((count << 6) >> priority); +#else + prune_dcache(0); +#endif } #define NAME_ALLOC_LEN(len) ((len+16) & ~15) diff --git a/include/asm-alpha/apecs.h b/include/asm-alpha/apecs.h index e65cdc763a8b..3c7b9e09a34b 100644 --- a/include/asm-alpha/apecs.h +++ b/include/asm-alpha/apecs.h @@ -211,6 +211,7 @@ extern unsigned int APECS_DMA_WIN_SIZE; #define APECS_IO (IDENT_ADDR + 0x1c0000000UL) #define APECS_SPARSE_MEM (IDENT_ADDR + 0x200000000UL) #define APECS_DENSE_MEM (IDENT_ADDR + 0x300000000UL) +#define DENSE_MEM(addr) APECS_DENSE_MEM /* * Bit definitions for I/O Controller status register 0: @@ -286,6 +287,7 @@ extern inline void * bus_to_virt(unsigned long address) */ #define vuip volatile unsigned int * +#define vulp volatile unsigned long * extern inline unsigned int __inb(unsigned long addr) { @@ -374,6 +376,11 @@ extern inline unsigned long __readl(unsigned long addr) return *(vuip) (addr + APECS_DENSE_MEM); } +extern inline unsigned long __readq(unsigned long addr) +{ + return *(vulp) (addr + APECS_DENSE_MEM); +} + extern inline void __writeb(unsigned char b, unsigned long addr) { unsigned long msb; @@ -407,6 +414,11 @@ extern inline void __writel(unsigned int b, unsigned long addr) *(vuip) (addr + APECS_DENSE_MEM) = b; } +extern inline void __writeq(unsigned long b, unsigned long addr) +{ + *(vulp) (addr + APECS_DENSE_MEM) = b; +} + #define inb(port) \ (__builtin_constant_p((port))?__inb(port):_inb(port)) @@ -414,9 +426,12 @@ extern inline void __writel(unsigned int b, unsigned long addr) (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) #define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) #define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) #undef vuip +#undef vulp extern unsigned long apecs_init (unsigned long mem_start, unsigned long mem_end); diff --git a/include/asm-alpha/cia.h b/include/asm-alpha/cia.h index 8211e0d6b391..93f044b2d883 100644 --- a/include/asm-alpha/cia.h +++ b/include/asm-alpha/cia.h @@ -178,6 +178,7 @@ extern unsigned int CIA_DMA_WIN_SIZE; #define CIA_SPARSE_MEM_R2 (IDENT_ADDR + 0x8400000000UL) #define CIA_SPARSE_MEM_R3 (IDENT_ADDR + 0x8500000000UL) #define CIA_DENSE_MEM (IDENT_ADDR + 0x8600000000UL) +#define DENSE_MEM(addr) CIA_DENSE_MEM /* * ALCOR's GRU ASIC registers @@ -241,6 +242,7 @@ extern inline void * bus_to_virt(unsigned long address) */ #define vuip volatile unsigned int * +#define vulp volatile unsigned long * extern inline unsigned int __inb(unsigned long addr) { @@ -491,11 +493,21 @@ extern inline unsigned long __readl(unsigned long addr) return *(vuip) (addr + CIA_DENSE_MEM); } +extern inline unsigned long __readq(unsigned long addr) +{ + return *(vulp) (addr + CIA_DENSE_MEM); +} + extern inline void __writel(unsigned int b, unsigned long addr) { *(vuip) (addr + CIA_DENSE_MEM) = b; } +extern inline void __writeq(unsigned long b, unsigned long addr) +{ + *(vulp) (addr + CIA_DENSE_MEM) = b; +} + #define inb(port) \ (__builtin_constant_p((port))?__inb(port):_inb(port)) @@ -503,9 +515,12 @@ extern inline void __writel(unsigned int b, unsigned long addr) (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) #define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) #define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) #undef vuip +#undef vulp extern unsigned long cia_init (unsigned long mem_start, unsigned long mem_end); diff --git a/include/asm-alpha/io.h b/include/asm-alpha/io.h index 176af8744f22..e65a7308f0cf 100644 --- a/include/asm-alpha/io.h +++ b/include/asm-alpha/io.h @@ -133,9 +133,11 @@ extern void _outl (unsigned int l,unsigned long port); extern unsigned long _readb(unsigned long addr); extern unsigned long _readw(unsigned long addr); extern unsigned long _readl(unsigned long addr); +extern unsigned long _readq(unsigned long addr); extern void _writeb(unsigned char b, unsigned long addr); extern void _writew(unsigned short b, unsigned long addr); extern void _writel(unsigned int b, unsigned long addr); +extern void _writeq(unsigned long b, unsigned long addr); /* * The platform header files may define some of these macros to use @@ -206,6 +208,9 @@ extern inline void iounmap(void *addr) #ifndef readl # define readl(a) _readl((unsigned long)(a)) #endif +#ifndef readq +# define readq(a) _readq((unsigned long)(a)) +#endif #ifndef writeb # define writeb(v,a) _writeb((v),(unsigned long)(a)) #endif @@ -215,19 +220,29 @@ extern inline void iounmap(void *addr) #ifndef writel # define writel(v,a) _writel((v),(unsigned long)(a)) #endif +#ifndef writeq +# define writeq(v,a) _writeq((v),(unsigned long)(a)) +#endif #ifdef __KERNEL__ /* * String version of IO memory access ops: */ -extern void _memcpy_fromio(void *, unsigned long, unsigned long); -extern void _memcpy_toio(unsigned long, void *, unsigned long); -extern void _memset_io(unsigned long, int, unsigned long); +extern void _memcpy_fromio(void *, unsigned long, long); +extern void _memcpy_toio(unsigned long, void *, long); +extern void _memset_c_io(unsigned long, unsigned long, long); + +#define memcpy_fromio(to,from,len) \ + _memcpy_fromio((to),(unsigned long)(from),(len)) +#define memcpy_toio(to,from,len) \ + _memcpy_toio((unsigned long)(to),(from),(len)) +#define memset_io(addr,c,len) \ + _memset_c_io((unsigned long)(addr),0x0101010101010101UL*(u8)(c),(len)) -#define memcpy_fromio(to,from,len) _memcpy_fromio((to),(unsigned long)(from),(len)) -#define memcpy_toio(to,from,len) _memcpy_toio((unsigned long)(to),(from),(len)) -#define memset_io(addr,c,len) _memset_io((unsigned long)(addr),(c),(len)) +#define __HAVE_ARCH_MEMSETW_IO +#define memsetw_io(addr,c,len) \ + _memset_c_io((unsigned long)(addr),0x0001000100010001UL*(u16)(c),(len)) /* * String versions of in/out ops: @@ -245,7 +260,8 @@ extern void outsl (unsigned long port, const void *src, unsigned long count); * only used by some shared memory 8390 Ethernet cards anyway. */ -#define eth_io_copy_and_sum(skb,src,len,unused) memcpy_fromio((skb)->data,(src),(len)) +#define eth_io_copy_and_sum(skb,src,len,unused) \ + memcpy_fromio((skb)->data,(src),(len)) static inline int check_signature(unsigned long io_addr, const unsigned char *signature, int length) diff --git a/include/asm-alpha/jensen.h b/include/asm-alpha/jensen.h index 7a3b0785143e..ff0ad54b5886 100644 --- a/include/asm-alpha/jensen.h +++ b/include/asm-alpha/jensen.h @@ -230,6 +230,17 @@ extern inline unsigned long __readl(unsigned long addr) return *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x60); } +extern inline unsigned long __readq(unsigned long addr) +{ + unsigned long r0, r1; + __set_hae(addr); + addr &= __HAE_MASK; + addr = (addr << 7) + EISA_MEM + 0x60; + r0 = *(volatile unsigned int *) (addr); + r1 = *(volatile unsigned int *) (addr + (4 << 7)); + return r1 << 32 | r0; +} + extern inline void __writeb(unsigned short b, unsigned long addr) { __set_hae(addr); @@ -251,6 +262,15 @@ extern inline void __writel(unsigned int b, unsigned long addr) *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x60) = b; } +extern inline void __writeq(unsigned long b, unsigned long addr) +{ + __set_hae(addr); + addr &= __HAE_MASK; + addr = (addr << 7) + EISA_MEM + 0x60; + *(volatile unsigned int *) (addr) = b; + *(volatile unsigned int *) (addr + (4 << 7)) = b >> 32; +} + /* * The above have so much overhead that it probably doesn't make * sense to have them inlined (better icache behaviour). diff --git a/include/asm-alpha/lca.h b/include/asm-alpha/lca.h index 429077e8a506..7eb85b87a061 100644 --- a/include/asm-alpha/lca.h +++ b/include/asm-alpha/lca.h @@ -125,6 +125,7 @@ extern unsigned int LCA_DMA_WIN_SIZE; #define LCA_IO (IDENT_ADDR + 0x1c0000000UL) #define LCA_SPARSE_MEM (IDENT_ADDR + 0x200000000UL) #define LCA_DENSE_MEM (IDENT_ADDR + 0x300000000UL) +#define DENSE_MEM(addr) LCA_DENSE_MEM /* * Bit definitions for I/O Controller status register 0: @@ -208,6 +209,7 @@ extern inline void * bus_to_virt(unsigned long address) */ #define vuip volatile unsigned int * +#define vulp volatile unsigned long * extern inline unsigned int __inb(unsigned long addr) { @@ -296,6 +298,11 @@ extern inline unsigned long __readl(unsigned long addr) return *(vuip) (addr + LCA_DENSE_MEM); } +extern inline unsigned long __readq(unsigned long addr) +{ + return *(vulp) (addr + LCA_DENSE_MEM); +} + extern inline void __writeb(unsigned char b, unsigned long addr) { unsigned long msb; @@ -333,6 +340,11 @@ extern inline void __writel(unsigned int b, unsigned long addr) *(vuip) (addr + LCA_DENSE_MEM) = b; } +extern inline void __writeq(unsigned long b, unsigned long addr) +{ + *(vulp) (addr + LCA_DENSE_MEM) = b; +} + /* * Most of the above have so much overhead that it probably doesn't * make sense to have them inlined (better icache behavior). @@ -345,9 +357,12 @@ extern inline void __writel(unsigned int b, unsigned long addr) (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) #define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) #define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) #undef vuip +#undef vulp extern unsigned long lca_init (unsigned long mem_start, unsigned long mem_end); diff --git a/include/asm-alpha/mcpcia.h b/include/asm-alpha/mcpcia.h index f284e083ee51..116fde5350ed 100644 --- a/include/asm-alpha/mcpcia.h +++ b/include/asm-alpha/mcpcia.h @@ -167,6 +167,8 @@ extern unsigned int MCPCIA_DMA_WIN_SIZE; #define MCPCIA_DENSE(h) (IDENT_ADDR + 0xf900000000UL + HOSE(h)) #define MCPCIA_IACK_SC(h) (IDENT_ADDR + 0xf9f0003f00UL + HOSE(h)) +#define DENSE_MEM(addr) MCPCIA_DENSE(((unsigned long)(addr) >> 32) & 3) + #define HAE_ADDRESS MCPCIA_HAE_MEM(0) #ifdef __KERNEL__ @@ -197,6 +199,7 @@ extern inline void * bus_to_virt(unsigned long address) */ #define vuip volatile unsigned int * +#define vulp volatile unsigned long * #ifdef DISABLE_BWIO_ENABLED @@ -375,7 +378,7 @@ extern inline unsigned long __readb(unsigned long addr) __asm__ __volatile__ ( "ldbu %0,%1" : "=r" (result) - : "m" (*(unsigned char *)(addr+MCPCIA_BW_MEM))); + : "m" (*(volatile unsigned char *)(addr+MCPCIA_BW_MEM))); return result; } @@ -387,21 +390,19 @@ extern inline unsigned long __readw(unsigned long addr) __asm__ __volatile__ ( "ldwu %0,%1" : "=r" (result) - : "m" (*(unsigned short *)(addr+MCPCIA_BW_MEM))); + : "m" (*(volatile unsigned short *)(addr+MCPCIA_BW_MEM))); return result; } extern inline unsigned long __readl(unsigned long addr) { - register unsigned long result; - - __asm__ __volatile__ ( - "ldl %0,%1" - : "=r" (result) - : "m" (*(unsigned int *)(addr+MCPCIA_BW_MEM))); + return *(vuip)(addr + MCPCIA_BW_MEM); +} - return result; +extern inline unsigned long __readq(unsigned long addr) +{ + return *(vulp)(addr + MCPCIA_BW_MEM); } extern inline void __writeb(unsigned char b, unsigned long addr) @@ -409,7 +410,8 @@ extern inline void __writeb(unsigned char b, unsigned long addr) __asm__ __volatile__ ( "stb %1,%0\n\t" "mb" - : : "m" (*(unsigned char *)(addr+MCPCIA_BW_MEM)), "r" (b)); + : "m" (*(volatile unsigned char *)(addr+MCPCIA_BW_MEM)) + : "r" (b)); } extern inline void __writew(unsigned short b, unsigned long addr) @@ -417,15 +419,20 @@ extern inline void __writew(unsigned short b, unsigned long addr) __asm__ __volatile__ ( "stw %1,%0\n\t" "mb" - : : "m" (*(unsigned short *)(addr+MCPCIA_BW_MEM)), "r" (b)); + : "m" (*(volatile unsigned short *)(addr+MCPCIA_BW_MEM)) + : "r" (b)); } extern inline void __writel(unsigned int b, unsigned long addr) { - __asm__ __volatile__ ( - "stl %1,%0\n\t" - "mb" - : : "m" (*(unsigned int *)(addr+MCPCIA_BW_MEM)), "r" (b)); + *(vuip)(addr+MCPCIA_BW_MEM) = b; + mb(); +} + +extern inline void __writeq(unsigned long b, unsigned long addr) +{ + *(vulp)(addr+MCPCIA_BW_MEM) = b; + mb(); } #define readb(addr) __readb((addr)) @@ -620,6 +627,13 @@ extern inline unsigned long __readl(unsigned long in_addr) return *(vuip) (addr + MCPCIA_DENSE(hose)); } +extern inline unsigned long __readq(unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + return *(vulp) (addr + MCPCIA_DENSE(hose)); +} + extern inline void __writel(unsigned int b, unsigned long in_addr) { unsigned long addr = in_addr & 0xffffffffUL; @@ -627,12 +641,22 @@ extern inline void __writel(unsigned int b, unsigned long in_addr) *(vuip) (addr + MCPCIA_DENSE(hose)) = b; } +extern inline void __writeq(unsigned long b, unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + *(vulp) (addr + MCPCIA_DENSE(hose)) = b; +} + #endif /* BWIO_ENABLED */ #define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) #define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) #undef vuip +#undef vulp struct linux_hose_info { struct pci_bus pci_bus; @@ -646,10 +670,8 @@ struct linux_hose_info { unsigned int pci_hose_index; }; -extern unsigned long mcpcia_init (unsigned long mem_start, - unsigned long mem_end); -extern unsigned long mcpcia_fixup (unsigned long mem_start, - unsigned long mem_end); +extern unsigned long mcpcia_init (unsigned long, unsigned long); +extern void mcpcia_fixup (void); #endif /* __KERNEL__ */ diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h index 96eccb99e73d..8c59a82e2960 100644 --- a/include/asm-alpha/pgtable.h +++ b/include/asm-alpha/pgtable.h @@ -30,10 +30,11 @@ static inline void reload_context(struct task_struct *task) { __asm__ __volatile__( - "bis %0,%0,$16\n\t" #ifdef CONFIG_ALPHA_DP264 - "zap $16,0xe0,$16\n\t" -#endif /* DP264 */ + "zap %0,0xe0,$16\n\t" +#else + "bis %0,%0,$16\n\t" +#endif "call_pal %1" : /* no outputs */ : "r" (&task->tss), "i" (PAL_swpctx) diff --git a/include/asm-alpha/pyxis.h b/include/asm-alpha/pyxis.h index f0fb43ac0884..0369f4858eb3 100644 --- a/include/asm-alpha/pyxis.h +++ b/include/asm-alpha/pyxis.h @@ -165,6 +165,7 @@ extern unsigned int PYXIS_DMA_WIN_SIZE; #define PYXIS_SPARSE_MEM_R2 (IDENT_ADDR + 0x8400000000UL) #define PYXIS_SPARSE_MEM_R3 (IDENT_ADDR + 0x8500000000UL) #define PYXIS_DENSE_MEM (IDENT_ADDR + 0x8600000000UL) +#define DENSE_MEM(addr) PYXIS_DENSE_MEM /* * Byte/Word PCI Memory Spaces: @@ -242,6 +243,7 @@ extern inline void * bus_to_virt(unsigned long address) */ #define vuip volatile unsigned int * +#define vulp volatile unsigned long * #ifdef BWIO_ENABLED @@ -252,7 +254,7 @@ extern inline unsigned int __inb(unsigned long addr) __asm__ __volatile__ ( "ldbu %0,%1" : "=r" (result) - : "m" (*(unsigned char *)(addr+PYXIS_BW_IO))); + : "m" (*(volatile unsigned char *)(addr+PYXIS_BW_IO))); return result; } @@ -262,7 +264,8 @@ extern inline void __outb(unsigned char b, unsigned long addr) __asm__ __volatile__ ( "stb %1,%0\n\t" "mb" - : : "m" (*(unsigned char *)(addr+PYXIS_BW_IO)), "r" (b)); + : "=m" (*(volatile unsigned char *)(addr+PYXIS_BW_IO)) + : "r" (b)); } extern inline unsigned int __inw(unsigned long addr) @@ -272,7 +275,7 @@ extern inline unsigned int __inw(unsigned long addr) __asm__ __volatile__ ( "ldwu %0,%1" : "=r" (result) - : "m" (*(unsigned short *)(addr+PYXIS_BW_IO))); + : "m" (*(volatile unsigned short *)(addr+PYXIS_BW_IO))); return result; } @@ -282,27 +285,19 @@ extern inline void __outw(unsigned short b, unsigned long addr) __asm__ __volatile__ ( "stw %1,%0\n\t" "mb" - : : "m" (*(unsigned short *)(addr+PYXIS_BW_IO)), "r" (b)); + : "=m" (*(volatile unsigned short *)(addr+PYXIS_BW_IO)) + : "r" (b)); } extern inline unsigned int __inl(unsigned long addr) { - register unsigned long result; - - __asm__ __volatile__ ( - "ldl %0,%1" - : "=r" (result) - : "m" (*(unsigned int *)(addr+PYXIS_BW_IO))); - - return result; + return *(vuip)(addr+PYXIS_BW_IO); } extern inline void __outl(unsigned int b, unsigned long addr) { - __asm__ __volatile__ ( - "stl %1,%0\n\t" - "mb" - : : "m" (*(unsigned int *)(addr+PYXIS_BW_IO)), "r" (b)); + *(vuip)(addr+PYXIS_BW_IO) = b; + mb(); } #define inb(port) __inb((port)) @@ -408,7 +403,7 @@ extern inline unsigned long __readb(unsigned long addr) __asm__ __volatile__ ( "ldbu %0,%1" : "=r" (result) - : "m" (*(unsigned char *)(addr+PYXIS_BW_MEM))); + : "m" (*(volatile unsigned char *)(addr+PYXIS_BW_MEM))); return result; } @@ -420,21 +415,19 @@ extern inline unsigned long __readw(unsigned long addr) __asm__ __volatile__ ( "ldwu %0,%1" : "=r" (result) - : "m" (*(unsigned short *)(addr+PYXIS_BW_MEM))); + : "m" (*(volatile unsigned short *)(addr+PYXIS_BW_MEM))); return result; } extern inline unsigned long __readl(unsigned long addr) { - register unsigned long result; - - __asm__ __volatile__ ( - "ldl %0,%1" - : "=r" (result) - : "m" (*(unsigned int *)(addr+PYXIS_BW_MEM))); + return *(vuip)(addr+PYXIS_BW_MEM); +} - return result; +extern inline unsigned long __readq(unsigned long addr) +{ + return *(vulp)(addr+PYXIS_BW_MEM); } extern inline void __writeb(unsigned char b, unsigned long addr) @@ -442,7 +435,8 @@ extern inline void __writeb(unsigned char b, unsigned long addr) __asm__ __volatile__ ( "stb %1,%0\n\t" "mb" - : : "m" (*(unsigned char *)(addr+PYXIS_BW_MEM)), "r" (b)); + : "=m" (*(volatile unsigned char *)(addr+PYXIS_BW_MEM)) + : "r" (b)); } extern inline void __writew(unsigned short b, unsigned long addr) @@ -450,15 +444,18 @@ extern inline void __writew(unsigned short b, unsigned long addr) __asm__ __volatile__ ( "stw %1,%0\n\t" "mb" - : : "m" (*(unsigned short *)(addr+PYXIS_BW_MEM)), "r" (b)); + : "=m" (*(volatile unsigned short *)(addr+PYXIS_BW_MEM)) + : "r" (b)); } extern inline void __writel(unsigned int b, unsigned long addr) { - __asm__ __volatile__ ( - "stl %1,%0\n\t" - "mb" - : : "m" (*(unsigned int *)(addr+PYXIS_BW_MEM)), "r" (b)); + *(vuip)(addr+PYXIS_BW_MEM) = b; +} + +extern inline void __writeq(unsigned long b, unsigned long addr) +{ + *(vulp)(addr+PYXIS_BW_MEM) = b; } #define readb(addr) __readb((addr)) @@ -643,17 +640,30 @@ extern inline unsigned long __readl(unsigned long addr) return *(vuip) (addr + PYXIS_DENSE_MEM); } +extern inline unsigned long __readq(unsigned long addr) +{ + return *(vulp) (addr + PYXIS_DENSE_MEM); +} + extern inline void __writel(unsigned int b, unsigned long addr) { *(vuip) (addr + PYXIS_DENSE_MEM) = b; } +extern inline void __writeq(unsigned long b, unsigned long addr) +{ + *(vulp) (addr + PYXIS_DENSE_MEM) = b; +} + #endif /* BWIO_ENABLED */ #define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) #define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) #undef vuip +#undef vulp extern unsigned long pyxis_init (unsigned long mem_start, unsigned long mem_end); diff --git a/include/asm-alpha/string.h b/include/asm-alpha/string.h index b956106407c8..e21e56eb1de7 100644 --- a/include/asm-alpha/string.h +++ b/include/asm-alpha/string.h @@ -19,8 +19,8 @@ extern void * __memcpy(void *, const void *, size_t); #endif #define __HAVE_ARCH_MEMSET -extern void * __constant_c_memset(void *, unsigned long, long); -extern void * __memset(void *, char, size_t); +extern void * __constant_c_memset(void *, unsigned long, size_t); +extern void * __memset(void *, int, size_t); #if __GNUC__ > 2 || __GNUC_MINOR__ >= 91 #define memset(s, c, n) \ @@ -44,6 +44,18 @@ extern void * __memset(void *, char, size_t); #define __HAVE_ARCH_STRRCHR #define __HAVE_ARCH_STRLEN +/* The following routine is like memset except that it writes 16-bit + aligned values. The DEST and COUNT parameters must be even for + correct operation. */ + +#define __HAVE_ARCH_MEMSETW +extern void * __memsetw(void *dest, unsigned short, size_t count); + +#define memsetw(s, c, n) \ +(__builtin_constant_p(c) \ + ? __constant_c_memset((s),0x0001000100010001UL*(unsigned short)(c),(n)) \ + : __memsetw((s),(c),(n))) + #endif /* __KERNEL__ */ #endif /* __ALPHA_STRING_H__ */ diff --git a/include/asm-alpha/t2.h b/include/asm-alpha/t2.h index 09face466687..ec7100ab89a8 100644 --- a/include/asm-alpha/t2.h +++ b/include/asm-alpha/t2.h @@ -48,6 +48,7 @@ extern unsigned int T2_DMA_WIN_SIZE; #define T2_IO (IDENT_ADDR + GAMMA_BIAS + 0x3a0000000UL) #define T2_SPARSE_MEM (IDENT_ADDR + GAMMA_BIAS + 0x200000000UL) #define T2_DENSE_MEM (IDENT_ADDR + GAMMA_BIAS + 0x3c0000000UL) +#define DENSE_MEM(addr) T2_DENSE_MEM #define T2_IOCSR (IDENT_ADDR + GAMMA_BIAS + 0x38e000000UL) #define T2_CERR1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000020UL) @@ -219,87 +220,79 @@ extern inline void __outl(unsigned int b, unsigned long addr) extern unsigned long t2_sm_base; +extern int __t2_ioaddr_check(unsigned long addr) +{ + if ((addr >= t2_sm_base && addr <= t2_sm_base + MEM_R1_MASK) + || (addr >= 512*1024 && addr < 1024*1024)) + return 1; +#if 0 + printk("T2: address 0x%lx not covered by HAE\n", addr); +#endif + return 0; +} + + extern inline unsigned long __readb(unsigned long addr) { unsigned long result, shift, work; - if ((addr >= t2_sm_base) && (addr <= (t2_sm_base + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00); - else - if ((addr >= 512*1024) && (addr < 1024*1024)) /* check HOLE */ - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00); - else - { -#if 0 - printk("__readb: address 0x%lx not covered by HAE\n", addr); -#endif - return 0x0ffUL; - } - shift = (addr & 0x3) << 3; + if (!__t2_addr_check(addr)) + return 0xFF; + + work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00); result = *(vuip) work; - result >>= shift; - return 0x0ffUL & result; + shift = (addr & 0x3) << 3; + return (result >> shift) & 0xFF; } extern inline unsigned long __readw(unsigned long addr) { unsigned long result, shift, work; - if ((addr >= t2_sm_base) && (addr <= (t2_sm_base + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08); - else - if ((addr >= 512*1024) && (addr < 1024*1024)) /* check HOLE */ - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08); - else - { -#if 0 - printk("__readw: address 0x%lx not covered by HAE\n", addr); -#endif - return 0x0ffffUL; - } - shift = (addr & 0x3) << 3; + if (!__t2_addr_check(addr)) + return 0xFFFF; + + work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08); result = *(vuip) work; - result >>= shift; - return 0x0ffffUL & result; + shift = (addr & 0x3) << 3; + return (result >> shift) & 0xFF; } -/* on SABLE with T2, we must use SPARSE memory even for 32-bit access */ +/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */ extern inline unsigned long __readl(unsigned long addr) { - unsigned long result, work; - - if ((addr >= t2_sm_base) && (addr <= (t2_sm_base + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); - else - if ((addr >= 512*1024) && (addr < 1024*1024)) /* check HOLE */ - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); - else - { -#if 0 - printk("__readl: address 0x%lx not covered by HAE\n", addr); -#endif - return 0x0ffffffffUL; - } - result = *(vuip) work; - return 0xffffffffUL & result; + unsigned long work; + + if (!__t2_addr_check(addr)) + return 0xFFFFFFFF; + + work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); + return *(vuip) work; +} + +/* ... which makes me wonder why we advertise we have DENSE memory at all. + Anyway, guess that means we should emulate 64-bit access as two cycles. */ +extern inline unsigned long __readq(unsigned long addr) +{ + unsigned long work, r0, r1; + + if (!__t2_addr_check(addr)) + return ~0UL; + + work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); + r0 = *(vuip) work0; + r1 = *(vuip) (work0 + (4 << 5)); + return r1 << 32 | r0; } extern inline void __writeb(unsigned char b, unsigned long addr) { unsigned long work; - if ((addr >= t2_sm_base) && (addr <= (t2_sm_base + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00); - else - if ((addr >= 512*1024) && (addr < 1024*1024)) /* check HOLE */ - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00); - else - { -#if 0 - printk("__writeb: address 0x%lx not covered by HAE\n", addr); -#endif - return; - } + if (!__t2_addr_check(addr)) + return; + + work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00); *(vuip) work = b * 0x01010101; } @@ -307,40 +300,39 @@ extern inline void __writew(unsigned short b, unsigned long addr) { unsigned long work; - if ((addr >= t2_sm_base) && (addr <= (t2_sm_base + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08); - else - if ((addr >= 512*1024) && (addr < 1024*1024)) /* check HOLE */ - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08); - else - { -#if 0 - printk("__writew: address 0x%lx not covered by HAE\n", addr); -#endif - return; - } + if (!__t2_addr_check(addr)) + return; + + work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08); *(vuip) work = b * 0x00010001; } -/* on SABLE with T2, we must use SPARSE memory even for 32-bit access */ +/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */ extern inline void __writel(unsigned int b, unsigned long addr) { unsigned long work; - if ((addr >= t2_sm_base) && (addr <= (t2_sm_base + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); - else - if ((addr >= 512*1024) && (addr < 1024*1024)) /* check HOLE */ - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); - { -#if 0 - printk("__writel: address 0x%lx not covered by HAE\n", addr); -#endif - return; - } + if (!__t2_addr_check(addr)) + return; + + work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); *(vuip) work = b; } +/* ... which makes me wonder why we advertise we have DENSE memory at all. + Anyway, guess that means we should emulate 64-bit access as two cycles. */ +extern inline void __writeq(unsigned long b, unsigned long addr) +{ + unsigned long work; + + if (!__t2_addr_check(addr)) + return; + + work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); + *(vuip) work0 = b; + *(vuip) (work0 + (4 << 5)) = (b >> 32); +} + #else /* SRM_SETUP */ extern inline unsigned long __readb(unsigned long addr) @@ -387,6 +379,20 @@ extern inline unsigned long __readl(unsigned long addr) return 0xffffffffUL & result; } +extern inline unsigned long __readq(unsigned long addr) +{ + unsigned long r0, r1, work, msb; + + msb = addr & 0xE0000000 ; + addr &= MEM_R1_MASK ; + if (msb != hae.cache) { + set_hae(msb); + } + work = (addr << 5) + T2_SPARSE_MEM + 0x18; + r0 = *(vuip)(work); + r1 = *(vuip)(work + (4 << 5)); + return r1 << 32 | r0; +} extern inline void __writeb(unsigned char b, unsigned long addr) { unsigned long msb ; @@ -424,6 +430,20 @@ extern inline void __writel(unsigned int b, unsigned long addr) *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b; } +extern inline void __writeq(unsigned long b, unsigned long addr) +{ + unsigned long msb, work; + + msb = addr & 0xE0000000 ; + addr &= MEM_R1_MASK ; + if (msb != hae.cache) { + set_hae(msb); + } + work = (addr << 5) + T2_SPARSE_MEM + 0x18; + *(vuip)work = b; + *(vuip)(work + (4 << 5)) = b >> 32; +} + #endif /* SRM_SETUP */ #define inb(port) \ @@ -432,9 +452,6 @@ extern inline void __writel(unsigned int b, unsigned long addr) #define outb(x, port) \ (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) -#define readl(a) __readl((unsigned long)(a)) -#define writel(v,a) __writel((v),(unsigned long)(a)) - #undef vuip extern unsigned long t2_init (unsigned long mem_start, diff --git a/include/asm-alpha/tsunami.h b/include/asm-alpha/tsunami.h index 2c6be4e23700..fe48e2861290 100644 --- a/include/asm-alpha/tsunami.h +++ b/include/asm-alpha/tsunami.h @@ -317,70 +317,50 @@ extern inline void * bus_to_virt(unsigned long address) /* only using PCI bus 0 for now in all routines */ +#define DENSE_MEM(addr) TSUNAMI_PCI0_MEM + /* HACK ALERT! HACK ALERT! */ /* HACK ALERT! HACK ALERT! */ +/* Also assume we are optimizing for EV6, and so the compiler knows about + byte/word instructions. */ +#define vucp volatile unsigned char * +#define vusp volatile unsigned short * #define vuip volatile unsigned int * +#define vulp volatile unsigned long * extern inline unsigned int __inb(unsigned long addr) { - register unsigned long result; - - __asm__ __volatile__ ( - "ldbu %0,%1" - : "=r" (result) - : "m" (*(unsigned char *)(addr+TSUNAMI_PCI0_IO))); - - return result; + return *(vucp)(addr + TSUNAMI_PCI0_IO); } extern inline void __outb(unsigned char b, unsigned long addr) { - __asm__ __volatile__ ( - "stb %1,%0\n\t" - "mb" - : : "m" (*(unsigned char *)(addr+TSUNAMI_PCI0_IO)), "r" (b)); + *(vucp)(addr + TSUNAMI_PCI0_IO) = b; + mb(); } extern inline unsigned int __inw(unsigned long addr) { - register unsigned long result; - - __asm__ __volatile__ ( - "ldwu %0,%1" - : "=r" (result) - : "m" (*(unsigned short *)(addr+TSUNAMI_PCI0_IO))); - - return result; + return *(vusp)(addr+TSUNAMI_PCI0_IO); } extern inline void __outw(unsigned short b, unsigned long addr) { - __asm__ __volatile__ ( - "stw %1,%0\n\t" - "mb" - : : "m" (*(unsigned short *)(addr+TSUNAMI_PCI0_IO)), "r" (b)); + *(vusp)(addr+TSUNAMI_PCI0_IO) = b; + mb(); } extern inline unsigned int __inl(unsigned long addr) { - register unsigned long result; - - __asm__ __volatile__ ( - "ldl %0,%1" - : "=r" (result) - : "m" (*(unsigned int *)(addr+TSUNAMI_PCI0_IO))); - - return result; + return *(vuip)(addr+TSUNAMI_PCI0_IO); } extern inline void __outl(unsigned int b, unsigned long addr) { - __asm__ __volatile__ ( - "stl %1,%0\n\t" - "mb" - : : "m" (*(unsigned int *)(addr+TSUNAMI_PCI0_IO)), "r" (b)); + *(vuip)(addr+TSUNAMI_PCI0_IO) = b; + mb(); } /* @@ -389,62 +369,46 @@ extern inline void __outl(unsigned int b, unsigned long addr) extern inline unsigned long __readb(unsigned long addr) { - register unsigned long result; - - __asm__ __volatile__ ( - "ldbu %0,%1" - : "=r" (result) - : "m" (*(unsigned char *)(addr+TSUNAMI_PCI0_MEM))); - - return result; + return *(vucp)(addr+TSUNAMI_PCI0_MEM); } extern inline unsigned long __readw(unsigned long addr) { - register unsigned long result; - - __asm__ __volatile__ ( - "ldwu %0,%1" - : "=r" (result) - : "m" (*(unsigned short *)(addr+TSUNAMI_PCI0_MEM))); - - return result; + return *(vusp)(addr+TSUNAMI_PCI0_MEM); } extern inline unsigned long __readl(unsigned long addr) { - register unsigned long result; - - __asm__ __volatile__ ( - "ldl %0,%1" - : "=r" (result) - : "m" (*(unsigned int *)(addr+TSUNAMI_PCI0_MEM))); + return *(vuip)(addr+TSUNAMI_PCI0_MEM); +} - return result; +extern inline unsigned long __readq(unsigned long addr) +{ + return *(vulp)(addr+TSUNAMI_PCI0_MEM); } extern inline void __writeb(unsigned char b, unsigned long addr) { - __asm__ __volatile__ ( - "stb %1,%0\n\t" - "mb" - : : "m" (*(unsigned char *)(addr+TSUNAMI_PCI0_MEM)), "r" (b)); + *(vucp)(addr+TSUNAMI_PCI0_MEM) = b; + mb(); } extern inline void __writew(unsigned short b, unsigned long addr) { - __asm__ __volatile__ ( - "stw %1,%0\n\t" - "mb" - : : "m" (*(unsigned short *)(addr+TSUNAMI_PCI0_MEM)), "r" (b)); + *(vusp)(addr+TSUNAMI_PCI0_MEM) = b; + mb(); } extern inline void __writel(unsigned int b, unsigned long addr) { - __asm__ __volatile__ ( - "stl %1,%0\n\t" - "mb" - : : "m" (*(unsigned int *)(addr+TSUNAMI_PCI0_MEM)), "r" (b)); + *(vuip)(addr+TSUNAMI_PCI0_MEM) = b; + mb(); +} + +extern inline void __writeq(unsigned long b, unsigned long addr) +{ + *(vulp)(addr+TSUNAMI_PCI0_MEM) = b; + mb(); } #define inb(port) __inb((port)) @@ -458,15 +422,19 @@ extern inline void __writel(unsigned int b, unsigned long addr) #define readb(a) __readb((unsigned long)(a)) #define readw(a) __readw((unsigned long)(a)) #define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) #define writeb(v,a) __writeb((v),(unsigned long)(a)) #define writew(v,a) __writew((v),(unsigned long)(a)) #define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) +#undef vucp +#undef vusp #undef vuip +#undef vulp -extern unsigned long tsunami_init (unsigned long mem_start, - unsigned long mem_end); +extern unsigned long tsunami_init (unsigned long, unsigned long); #endif /* __KERNEL__ */ diff --git a/include/asm-arm/init.h b/include/asm-arm/init.h index 5b5bbd067c9c..6105bbe886d8 100644 --- a/include/asm-arm/init.h +++ b/include/asm-arm/init.h @@ -1,6 +1,8 @@ #ifndef _ASMARM_INIT_H #define _ASMARM_INIT_H +#include + /* C routines */ #ifdef CONFIG_BINUTILS_NEW diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index e21e51f41f45..9183e08416e1 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -10,8 +10,6 @@ */ #define CUR_DEFAULT CUR_UNDERLINE -#include - #define NPAR 16 struct vc_data { diff --git a/include/linux/parport.h b/include/linux/parport.h index 13062e0b4711..269fb574cf44 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -132,10 +132,11 @@ struct parport_operations { struct parport_device_info { parport_device_class class; - char *mfr; - char *model; - char *cmdset; - char *description; + const char *class_name; + const char *mfr; + const char *model; + const char *cmdset; + const char *description; }; /* Each device can have two callback functions: @@ -152,7 +153,7 @@ struct parport_device_info { /* A parallel port device */ struct pardevice { - char *name; + const char *name; struct parport *port; int (*preempt)(void *); void (*wakeup)(void *); @@ -184,7 +185,7 @@ struct parport_dir { struct parport { unsigned long base; /* base address */ unsigned int size; /* IO extent */ - char *name; + const char *name; int irq; /* interrupt (or -1 for none) */ int dma; unsigned int modes; diff --git a/include/linux/pci.h b/include/linux/pci.h index c4dbc828ace3..e9d03e05990b 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1164,5 +1164,79 @@ int pci_write_config_word(struct pci_dev *dev, u8 where, u16 val); int pci_write_config_dword(struct pci_dev *dev, u8 where, u32 val); void pci_set_master(struct pci_dev *dev); +#ifndef CONFIG_PCI +/* If the system does not have PCI, clearly these return errors. Define + these as simple inline functions to avoid hair in drivers. */ +extern inline +int pcibios_present(void) { return 0; } + +extern inline +int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char *val) +{ return PCIBIOS_FUNC_NOT_SUPPORTED; } + +extern inline +int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short *val) +{ return PCIBIOS_FUNC_NOT_SUPPORTED; } + +extern inline +int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int *val) +{ return PCIBIOS_FUNC_NOT_SUPPORTED; } + +extern inline +int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned char val) +{ return PCIBIOS_FUNC_NOT_SUPPORTED; } + +extern inline +int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned short val) +{ return PCIBIOS_FUNC_NOT_SUPPORTED; } + +extern inline +int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn, + unsigned char where, unsigned int val) +{ return PCIBIOS_FUNC_NOT_SUPPORTED; } + +extern inline +int pci_read_config_byte(struct pci_dev *dev, u8 where, u8 *val) +{ return PCIBIOS_FUNC_NOT_SUPPORTED; } + +extern inline +int pci_read_config_word(struct pci_dev *dev, u8 where, u16 *val) +{ return PCIBIOS_FUNC_NOT_SUPPORTED; } + +extern inline +int pci_read_config_dword(struct pci_dev *dev, u8 where, u32 *val) +{ return PCIBIOS_FUNC_NOT_SUPPORTED; } + +extern inline +int pci_write_config_byte(struct pci_dev *dev, u8 where, u8 val) +{ return PCIBIOS_FUNC_NOT_SUPPORTED; } + +extern inline +int pci_write_config_word(struct pci_dev *dev, u8 where, u16 val) +{ return PCIBIOS_FUNC_NOT_SUPPORTED; } + +extern inline +int pci_write_config_dword(struct pci_dev *dev, u8 where, u32 val) +{ return PCIBIOS_FUNC_NOT_SUPPORTED; } + +extern inline struct pci_dev * +pci_find_device (unsigned int vendor, unsigned int device, struct pci_dev *from) +{ return NULL; } + +extern inline +struct pci_dev *pci_find_class (unsigned int class, struct pci_dev *from) +{ return NULL; } + +extern inline +struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn) +{ return NULL; } + +#endif /* !CONFIG_PCI */ + #endif /* __KERNEL__ */ #endif /* LINUX_PCI_H */ diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index 1ebe3e3dd216..a2a00a04c989 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -51,7 +51,7 @@ extern __inline__ void DQUOT_DROP(struct inode *inode) } } -extern __inline__ int DQUOT_PREALLOC_BLOCK(struct super_block *sb, struct inode *inode, int nr) +extern __inline__ int DQUOT_PREALLOC_BLOCK(struct super_block *sb, const struct inode *inode, int nr) { if (sb->dq_op) { if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize), @@ -61,7 +61,7 @@ extern __inline__ int DQUOT_PREALLOC_BLOCK(struct super_block *sb, struct inode return 0; } -extern __inline__ int DQUOT_ALLOC_BLOCK(struct super_block *sb, struct inode *inode, int nr) +extern __inline__ int DQUOT_ALLOC_BLOCK(struct super_block *sb, const struct inode *inode, int nr) { if (sb->dq_op) { if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize), @@ -82,7 +82,7 @@ extern __inline__ int DQUOT_ALLOC_INODE(struct super_block *sb, struct inode *in return 0; } -extern __inline__ void DQUOT_FREE_BLOCK(struct super_block *sb, struct inode *inode, int nr) +extern __inline__ void DQUOT_FREE_BLOCK(struct super_block *sb, const struct inode *inode, int nr) { if (sb->dq_op) sb->dq_op->free_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize)); diff --git a/include/linux/random.h b/include/linux/random.h index cff06f06e66c..58c93b9b6129 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -59,6 +59,10 @@ extern __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport, __u32 sseq, __u32 count, __u32 data); +extern __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, + __u32 daddr, __u16 sport, + __u16 dport, __u32 sseq, + __u32 count, __u32 maxdiff); #ifndef MODULE extern struct file_operations random_fops, urandom_fops; diff --git a/init/main.c b/init/main.c index 19fe9dd1e8bb..e2c7f8a8dd77 100644 --- a/init/main.c +++ b/init/main.c @@ -88,7 +88,9 @@ extern void smp_setup(char *str, int *ints); #ifdef __i386__ extern void ioapic_pirq_setup(char *str, int *ints); #endif +#ifdef CONFIG_VGA_CONSOLE extern void no_scroll(char *str, int *ints); +#endif extern void kbd_reset_setup(char *str, int *ints); extern void panic_setup(char *str, int *ints); extern void bmouse_setup(char *str, int *ints); @@ -536,7 +538,9 @@ static struct kernel_param cooked_params[] __initdata = { { "panic=", panic_setup }, { "console=", console_setup }, #ifdef CONFIG_VT +#ifdef CONFIG_VGA_CONSOLE { "no-scroll", no_scroll }, +#endif { "kbd-reset", kbd_reset_setup }, #endif #ifdef CONFIG_BUGi386 diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2c9900920538..0803820ec0f0 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -312,22 +312,23 @@ __initfunc(unsigned long free_area_init(unsigned long start_mem, unsigned long e { mem_map_t * p; unsigned long mask = PAGE_MASK; - int i; + unsigned long i; /* * Select nr of pages we try to keep free for important stuff - * with a minimum of 48 pages and a maximum of 256 pages, so + * with a minimum of 10 pages and a maximum of 256 pages, so * that we don't waste too much memory on large systems. - * This is totally arbitrary. + * This is fairly arbitrary, but based on some behaviour + * analysis. */ i = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT+7); - if (i < 48) - i = 48; + if (i < 10) + i = 10; if (i > 256) i = 256; freepages.min = i; - freepages.low = i << 1; - freepages.high = freepages.low + i; + freepages.low = i * 2; + freepages.high = i * 3; mem_map = (mem_map_t *) LONG_ALIGN(start_mem); p = mem_map + MAP_NR(end_mem); start_mem = LONG_ALIGN((unsigned long) p); diff --git a/mm/vmscan.c b/mm/vmscan.c index d4bb5367c8b7..fdabc83656d8 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -593,9 +593,10 @@ int try_to_free_pages(unsigned int gfp_mask, int count) int retval; lock_kernel(); - retval = 0; do { - retval |= do_try_to_free_page(gfp_mask); + retval = do_try_to_free_page(gfp_mask); + if (!retval) + break; count--; } while (count > 0); unlock_kernel(); diff --git a/scripts/Makefile b/scripts/Makefile index eaf0db043022..7f21603fd429 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -1,4 +1,3 @@ -HOSTCFLAGS:=$(HOSTCFLAGS) -g -Wall HEADER=header.tk TAIL=tail.tk diff --git a/scripts/lxdialog/Makefile b/scripts/lxdialog/Makefile index fc5ee7ffd52f..90e192a55ace 100644 --- a/scripts/lxdialog/Makefile +++ b/scripts/lxdialog/Makefile @@ -1,8 +1,7 @@ -CC = gcc -CPP = gcc -E -OPTIM = -O2 -Wall -fomit-frame-pointer +CC = $(HOSTCC) +CPP = $(HOSTCC) -E -CFLAGS = $(OPTIM) -DLOCALE +CFLAGS = $(HOSTCFLAGS) -DLOCALE LDFLAGS = -s -L . LDLIBS = -lncurses -- 2.39.5