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
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
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
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.
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.
(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
=========================================
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
==============
--- /dev/null
+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.
+
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
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 =
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
# 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 \
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
# 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
# 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
# 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
# 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
#
# CONFIG_FTAPE is not set
+#
+# Console drivers
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_FB is not set
+
#
# Sound
#
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
#include <asm/dma.h>
#if 0
#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 <linux/pci.h>
#include <linux/malloc.h>
#include <linux/mm.h>
#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
*
#ifdef CONFIG_ALPHA_SRM_SETUP
void reset_for_srm(void)
{
- extern void scrreset(void);
struct pci_dev *dev;
int i;
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 */
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/sched.h>
+#include <linux/delay.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
#include <asm/ptrace.h>
#include <asm/mmu_context.h>
-#include <asm/delay.h>
/*
* NOTE: Herein lie back-to-back mb instructions. They are magic.
} 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;
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.
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 */
}
if (uss) {
- unsigned long ss_sp;
+ void *ss_sp;
error = -EFAULT;
if (get_user(ss_sp, &uss->ss_sp))
/* 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;
}
* files..
*/
#include <linux/kernel.h>
-
+#include <linux/types.h>
#include <asm/io.h>
/*
return __readl(addr);
}
+unsigned long _readq(unsigned long addr)
+{
+ return __readq(addr);
+}
void _writeb(unsigned char 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.
* 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++;
}
}
* 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++;
}
}
* "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++;
}
}
.set noreorder
.text
.globl __memset
+ .globl __memsetw
.globl __constant_c_memset
.ent __memset
.align 5
.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) */
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 */
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
alpha_fp_emul_imprecise = save_emul;
}
+#undef alpha_fp_emul_imprecise
#define alpha_fp_emul_imprecise do_alpha_fp_emul_imprecise
#endif /* MODULE */
*
* Copyright (C) 1998 Russell King, Dave Gilbert.
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/init.h>
# 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
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
# 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 \
ZLINKFLAGS = -Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS)
BZLINKFLAGS = -Ttext $(BZIMAGE_OFFSET) $(ZLDFLAGS)
-ifdef SMP
-CFLAGS := $(CFLAGS) -D__SMP__
-endif
-
all: vmlinux
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; \
#
# 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
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
} 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__
/*
# 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
#
# 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
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
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
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
include $(TOPDIR)/Rules.make
-ifdef SMP
-
hypersparc.o: hypersparc.S
$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o hypersparc.o hypersparc.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
#
# 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
#
# 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
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
-/*
- */
/*
* Hitachi H8/337 Microcontroller driver
*
#include <linux/miscdevice.h>
#include <linux/lists.h>
#include <linux/ioport.h>
+#include <linux/poll.h>
#define __KERNEL_SYSCALLS__
#include <asm/unistd.h>
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
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 */
};
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 *);
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);
}
#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)
{
.PHONY: all
gentbl: gentbl.c
- $(HOSTCC) -Wall $< -o $@ -lm
+ $(HOSTCC) $(HOSTCFLAGS) $< -o $@ -lm
TBLHDR := tables.h
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
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;
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 {
size -= PAGE_SIZE;
} while (size);
+ return size;
+out_up:
+ up(¤t->mm->mmap_sem);
return size;
}
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)
{
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:
#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;
{
#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 */
{
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
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;
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;
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;
}
int flags, void *handle)
{
struct pardevice *tmp;
+ unsigned long flgs;
if (flags & PARPORT_DEV_LURK) {
if (!pf || !kf) {
}
}
- /* 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);
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;
/* 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();
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;
/* 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);
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;
.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
/* 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;
/* 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;
/* 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;
#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. */
/* 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;
/* 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;
/* 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;
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",
* 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
#include "tlan.h"
+#include <linux/bios32.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/etherdevice.h>
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 *);
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] = {
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 */
/*****************************************************************************
*
* 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.
*
**************************************************************/
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
);
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" );
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 );
}
}
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;
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 */
* 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
*
**************************************************************/
-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;
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);
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++;
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;
}
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",
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;
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;
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;
*/
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;
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;
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 ) {
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;
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 */
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;
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 );
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;
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;
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"); */
}
}
* 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.
*
**************************************************************/
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" );
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;
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;
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;
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 */
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;
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 ) {
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;
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;
}
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 )
} /* 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 */
+
+
/***************************************************************
* 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.
*
**************************************************************/
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 );
*
**************************************************************/
-int TLan_Reset( struct device *dev )
+void
+TLan_ResetAdapter( struct device *dev )
{
TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
int i;
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 ) */
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 */
* 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
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
* 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).
*
********************************************************************/
{
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 */
/*********************************************************************
- * TLan_PhySelect
+ * TLan_PhyDetect
*
* Returns:
* Nothing
* 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 */
* 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
*
**************************************************************/
-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 */
*val = tmp;
- sti();
+ dev->interrupt--;
+ if ( dev->interrupt == 0 )
+ sti();
return err;
* 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.
*
**************************************************************/
-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 );
if ( minten )
TLan_SetBit( TLAN_NET_SIO_MINTEN, sio );
- sti();
+ dev->interrupt--;
+ if ( dev->interrupt == 0 )
+ sti();
} /* TLan_MiiWriteReg */
+
+
+
/*****************************************************************************
******************************************************************************
*
* 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
*
**************************************************************/
-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;
* 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.
*
****************************************************************/
-#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
*
****************************************************************/
- /* 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
****************************************************************/
#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
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;
****************************************************************/
#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
*
****************************************************************/
-#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 */
#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
#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
#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
/* 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
#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
#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 */
#define TLAN_TS_RESERVED 0x0FFF
+#define CIRC_INC( a, b ) if ( ++a >= b ) a = 0
/* Routines to access internal registers. */
-
+#if 0
inline void TLan_ClearBit(u8 bit, u16 port)
{
outb_p(inb_p(port) & ~bit, 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 )
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++) {
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);
}
}
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);
+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
*/
/*
-** 28 June 1998, version 3.0e
+** 16 July 1998, version 3.0g
**
** Supported SCSI-II features:
** Synchronous negotiation
#include <linux/types.h>
+/*
+** 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
*/
#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 */
#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
/*
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);
}
}
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));
** 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 */
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));
{
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);
/*
** 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];
/*
#ifndef NCR53C8XX_H
#define NCR53C8XX_H
-#include <linux/config.h>
-
-#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
#if !defined(LINUX_VERSION_CODE)
#include <linux/version.h>
#endif
+#include <linux/config.h>
#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
# 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
*/
-#include <linux/config.h>
#include <linux/tty.h>
#include <linux/fb.h>
#include <linux/string.h>
* Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
* KNOWN PROBLEMS/TO DO ==================================================== */
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/fs.h>
#include <linux/poll.h>
+#include <linux/init.h>
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/system.h>
#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",
#include <linux/coda_cache.h>
#include <linux/coda_proc.h>
+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);
*/
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)
#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:
*/
#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
extern inline unsigned int __inb(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;
*(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))
(__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);
#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
*/
#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
extern inline unsigned int __inb(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))
(__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);
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
#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
#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:
* 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)
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);
*(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).
#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:
*/
#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
extern inline unsigned int __inb(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;
*(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).
(__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);
#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__
*/
#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
#ifdef DISABLE_BWIO_ENABLED
__asm__ __volatile__ (
"ldbu %0,%1"
: "=r" (result)
- : "m" (*(unsigned char *)(addr+MCPCIA_BW_MEM)));
+ : "m" (*(volatile unsigned char *)(addr+MCPCIA_BW_MEM)));
return result;
}
__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)
__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)
__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))
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;
*(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;
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__ */
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)
#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:
*/
#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
#ifdef BWIO_ENABLED
__asm__ __volatile__ (
"ldbu %0,%1"
: "=r" (result)
- : "m" (*(unsigned char *)(addr+PYXIS_BW_IO)));
+ : "m" (*(volatile unsigned char *)(addr+PYXIS_BW_IO)));
return result;
}
__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)
__asm__ __volatile__ (
"ldwu %0,%1"
: "=r" (result)
- : "m" (*(unsigned short *)(addr+PYXIS_BW_IO)));
+ : "m" (*(volatile unsigned short *)(addr+PYXIS_BW_IO)));
return result;
}
__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))
__asm__ __volatile__ (
"ldbu %0,%1"
: "=r" (result)
- : "m" (*(unsigned char *)(addr+PYXIS_BW_MEM)));
+ : "m" (*(volatile unsigned char *)(addr+PYXIS_BW_MEM)));
return result;
}
__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)
__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)
__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))
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);
#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) \
#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__ */
#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)
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;
}
{
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)
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 ;
*(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) \
#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,
/* 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();
}
/*
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))
#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__ */
#ifndef _ASMARM_INIT_H
#define _ASMARM_INIT_H
+#include <linux/config.h>
+
/* C routines */
#ifdef CONFIG_BINUTILS_NEW
*/
#define CUR_DEFAULT CUR_UNDERLINE
-#include <linux/config.h>
-
#define NPAR 16
struct vc_data {
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:
/* A parallel port device */
struct pardevice {
- char *name;
+ const char *name;
struct parport *port;
int (*preempt)(void *);
void (*wakeup)(void *);
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;
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 */
}
}
-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),
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),
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));
__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;
#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);
{ "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
{
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);
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();
-HOSTCFLAGS:=$(HOSTCFLAGS) -g -Wall
HEADER=header.tk
TAIL=tail.tk
-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