diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Documentation/SubmittingDrivers linux.21p1/Documentation/SubmittingDrivers --- linux.vanilla/Documentation/SubmittingDrivers Sat Dec 29 16:57:19 2001 +++ linux.21p1/Documentation/SubmittingDrivers Sat Dec 29 03:19:40 2001 @@ -2,7 +2,7 @@ --------------------------------------- This document is intended to explain how to submit device drivers to the -Linux 2.2 and 2.4test kernel trees. Note that if you are interested in video +Linux 2.2, 2.4 and 2.5 kernel trees. Note that if you are interested in video card drivers you should probably talk to XFree86 (http://wwww.xfree86.org) instead. @@ -10,9 +10,9 @@ ------------------------- Major and minor numbers for devices are allocated by the Linux assigned name -and number authority (currently better known as H Peter Anvin). The -site is http://www.lanana.org/. This also deals with allocating numbers for -devices that are not going to be submitted to the mainstream kernel. +and number authority (currently better known as H Peter Anvin). The site is +http://www.lanana.org/. This also deals with allocating numbers for devices +that are not going to be submitted to the mainstream kernel. If you don't use assigned numbers then when you device is submitted it will get given an assigned number even if that is different from values you may @@ -22,21 +22,28 @@ ------------------------ Linux 2.0: - No new drivers are accepted for this kernel tree + No new drivers are accepted for this kernel tree. If you have any + security or other fixes then please contact David Weinehall + Linux 2.2: If the code area has a general maintainer then please submit it to the maintainer listed in MAINTAINERS in the kernel file. If the maintainer does not respond or you cannot find the appropriate - maintainer then please contact Alan Cox + maintainer then please contact Alan Cox . -Linux 2.4test: +Linux 2.4: + If the code area has a general maintainer then please submit it to + the maintainer listed in MAINTAINERS in the kernel file. If the + maintainer does not respond or you cannot find the appropriate + maintainer then please contact Marcelo Tosatti + . + +Linux 2.5: This kernel tree is under active development. The same rules apply - as 2.2 but you may wish to submit your driver via linux-kernel (see - resources) and follow that list to track changes in API's. These - should no longer be occurring as we are now in a code freeze. - The final contact point for Linux 2.4 submissions is - . + as 2.4 but you may wish to submit your driver via linux-kernel (see + resources) and follow that list to track changes in API's. The final + contact point for Linux 2.5 submissions is . What Criteria Determine Acceptance ---------------------------------- diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/MAINTAINERS linux.21p1/MAINTAINERS --- linux.vanilla/MAINTAINERS Sat Dec 29 16:57:19 2001 +++ linux.21p1/MAINTAINERS Sat Dec 29 03:12:27 2001 @@ -1000,9 +1000,8 @@ S: Maintained USB SUBSYSTEM -P: Johannes Erdfelt -M jerdfelt@valinux.com -M: johannes@erdfelt.com +P: Greg Kroah-Hartman +M: greg@kroah.com L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net W: http://www.linux-usb.org diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/Makefile linux.21p1/Makefile --- linux.vanilla/Makefile Sat Dec 29 16:57:19 2001 +++ linux.21p1/Makefile Sat Dec 29 03:24:20 2001 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 2 -SUBLEVEL = 20 -EXTRAVERSION = +SUBLEVEL = 21 +EXTRAVERSION = pre1 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/boot/compressed/misc.c linux.21p1/arch/i386/boot/compressed/misc.c --- linux.vanilla/arch/i386/boot/compressed/misc.c Sat Dec 29 16:57:19 2001 +++ linux.21p1/arch/i386/boot/compressed/misc.c Sat Dec 29 03:08:33 2001 @@ -297,6 +297,7 @@ if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.\n"); #endif output_data = (char *)0x100000; /* Points to 1M */ + free_mem_end_ptr = (long)real_mode; } struct moveparams { diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/i386/kernel/vm86.c linux.21p1/arch/i386/kernel/vm86.c --- linux.vanilla/arch/i386/kernel/vm86.c Sat Dec 29 16:57:19 2001 +++ linux.21p1/arch/i386/kernel/vm86.c Sat Dec 29 03:24:34 2001 @@ -330,74 +330,176 @@ * Boy are these ugly, but we need to do the correct 16-bit arithmetic. * Gcc makes a mess of it, so we do it inline and use non-obvious calling * conventions.. + * FIXME: is VM86_UNKNOWN really the correct return code? */ -#define pushb(base, ptr, val) \ -__asm__ __volatile__( \ - "decw %w0\n\t" \ - "movb %2,0(%1,%0)" \ - : "=r" (ptr) \ - : "r" (base), "q" (val), "0" (ptr)) - -#define pushw(base, ptr, val) \ -__asm__ __volatile__( \ - "decw %w0\n\t" \ - "movb %h2,0(%1,%0)\n\t" \ - "decw %w0\n\t" \ - "movb %b2,0(%1,%0)" \ - : "=r" (ptr) \ - : "r" (base), "q" (val), "0" (ptr)) - -#define pushl(base, ptr, val) \ -__asm__ __volatile__( \ - "decw %w0\n\t" \ - "rorl $16,%2\n\t" \ - "movb %h2,0(%1,%0)\n\t" \ - "decw %w0\n\t" \ - "movb %b2,0(%1,%0)\n\t" \ - "decw %w0\n\t" \ - "rorl $16,%2\n\t" \ - "movb %h2,0(%1,%0)\n\t" \ - "decw %w0\n\t" \ - "movb %b2,0(%1,%0)" \ - : "=r" (ptr) \ - : "r" (base), "q" (val), "0" (ptr)) - -#define popb(base, ptr) \ -({ unsigned long __res; \ -__asm__ __volatile__( \ - "movb 0(%1,%0),%b2\n\t" \ - "incw %w0" \ - : "=r" (ptr), "=r" (base), "=q" (__res) \ - : "0" (ptr), "1" (base), "2" (0)); \ -__res; }) - -#define popw(base, ptr) \ -({ unsigned long __res; \ -__asm__ __volatile__( \ - "movb 0(%1,%0),%b2\n\t" \ - "incw %w0\n\t" \ - "movb 0(%1,%0),%h2\n\t" \ - "incw %w0" \ - : "=r" (ptr), "=r" (base), "=q" (__res) \ - : "0" (ptr), "1" (base), "2" (0)); \ -__res; }) - -#define popl(base, ptr) \ -({ unsigned long __res; \ -__asm__ __volatile__( \ - "movb 0(%1,%0),%b2\n\t" \ - "incw %w0\n\t" \ - "movb 0(%1,%0),%h2\n\t" \ - "incw %w0\n\t" \ - "rorl $16,%2\n\t" \ - "movb 0(%1,%0),%b2\n\t" \ - "incw %w0\n\t" \ - "movb 0(%1,%0),%h2\n\t" \ - "incw %w0\n\t" \ - "rorl $16,%2" \ - : "=r" (ptr), "=r" (base), "=q" (__res) \ - : "0" (ptr), "1" (base)); \ -__res; }) +#define pushb(base, ptr, val, regs) \ + do { \ + int err; \ + __asm__ __volatile__( \ + "decw %w0\n\t" \ + "1: movb %3,0(%2,%0)\n\t" \ + "xor %1,%1\n\t" \ + "2:\n" \ + ".section .fixup,\"ax\"\n\t" \ + "3: movl $1,%1\n\t" \ + " jmp 2b\n\t" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,3b\n" \ + ".previous" \ + : "=r" (ptr), "=r" (err) \ + : "r" (base), "q" (val), "0" (ptr)); \ + if (err) \ + return_to_32bit(regs, VM86_UNKNOWN); \ + } while(0) + +#define pushw(base, ptr, val, regs) \ + do { \ + int err; \ + __asm__ __volatile__( \ + "decw %w0\n\t" \ + "1: movb %h3,0(%2,%0)\n\t" \ + "decw %w0\n\t" \ + "2: movb %b3,0(%2,%0)\n\t" \ + "xor %1,%1\n\t" \ + "3:\n" \ + ".section .fixup,\"ax\"\n\t" \ + "4: movl $1,%1\n\t" \ + " jmp 3b\n\t" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,4b\n" \ + " .long 2b,4b\n" \ + ".previous" \ + : "=r" (ptr), "=r" (err) \ + : "r" (base), "q" (val), "0" (ptr)); \ + if (err) \ + return_to_32bit(regs, VM86_UNKNOWN); \ + } while(0) + +#define pushl(base, ptr, val, regs) \ + do { \ + int err; \ + __asm__ __volatile__( \ + "decw %w0\n\t" \ + "rorl $16,%3\n\t" \ + "1: movb %h3,0(%2,%0)\n\t" \ + "decw %w0\n\t" \ + "2: movb %b3,0(%2,%0)\n\t" \ + "decw %w0\n\t" \ + "rorl $16,%3\n\t" \ + "3: movb %h3,0(%2,%0)\n\t" \ + "decw %w0\n\t" \ + "4: movb %b3,0(%2,%0)\n\t" \ + "xor %1,%1\n\t" \ + "5:\n" \ + ".section .fixup,\"ax\"\n\t" \ + "6: movl $1,%1\n\t" \ + " jmp 5b\n\t" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,6b\n" \ + " .long 2b,6b\n" \ + " .long 3b,6b\n" \ + " .long 4b,6b\n" \ + ".previous" \ + : "=r" (ptr), "=r" (err) \ + : "r" (base), "q" (val), "0" (ptr)); \ + if (err) \ + return_to_32bit(regs, VM86_UNKNOWN); \ + } while(0) + +#define popb(base, ptr, regs) \ + ({ \ + unsigned long __res; \ + unsigned int err; \ + __asm__ __volatile__( \ + "1:movb 0(%1,%0),%b2\n\t" \ + "incw %w0\n\t" \ + "xor %3,%3\n\t" \ + "2:\n" \ + ".section .fixup,\"ax\"\n\t" \ + "3: movl $1,%1\n\t" \ + " jmp 2b\n\t" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,3b\n" \ + ".previous" \ + : "=r" (ptr), "=r" (base), "=q" (__res), \ + "=r" (err) \ + : "0" (ptr), "1" (base), "2" (0)); \ + if (err) \ + return_to_32bit(regs, VM86_UNKNOWN); \ + __res; \ + }) + +#define popw(base, ptr, regs) \ + ({ \ + unsigned long __res; \ + unsigned int err; \ + __asm__ __volatile__( \ + "1:movb 0(%1,%0),%b2\n\t" \ + "incw %w0\n\t" \ + "2:movb 0(%1,%0),%h2\n\t" \ + "incw %w0\n\t" \ + "xor %3,%3\n\t" \ + "3:\n" \ + ".section .fixup,\"ax\"\n\t" \ + "4: movl $1,%1\n\t" \ + " jmp 3b\n\t" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,4b\n" \ + " .long 2b,4b\n" \ + ".previous" \ + : "=r" (ptr), "=r" (base), "=q" (__res), \ + "=r" (err) \ + : "0" (ptr), "1" (base), "2" (0)); \ + if (err) \ + return_to_32bit(regs, VM86_UNKNOWN); \ + __res; \ + }) + +#define popl(base, ptr, regs) \ + ({ \ + unsigned long __res; \ + unsigned int err; \ + __asm__ __volatile__( \ + "1:movb 0(%1,%0),%b2\n\t" \ + "incw %w0\n\t" \ + "2:movb 0(%1,%0),%h2\n\t" \ + "incw %w0\n\t" \ + "rorl $16,%2\n\t" \ + "3:movb 0(%1,%0),%b2\n\t" \ + "incw %w0\n\t" \ + "4:movb 0(%1,%0),%h2\n\t" \ + "incw %w0\n\t" \ + "rorl $16,%2\n\t" \ + "xor %3,%3\n\t" \ + "5:\n" \ + ".section .fixup,\"ax\"\n\t" \ + "6: movl $1,%1\n\t" \ + " jmp 5b\n\t" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,6b\n" \ + " .long 2b,6b\n" \ + " .long 3b,6b\n" \ + " .long 4b,6b\n" \ + ".previous" \ + : "=r" (ptr), "=r" (base), "=q" (__res), \ + "=r" (err) \ + : "0" (ptr), "1" (base), "2" (0)); \ + if (err) \ + return_to_32bit(regs, VM86_UNKNOWN); \ + __res; \ + }) static void do_int(struct kernel_vm86_regs *regs, int i, unsigned char * ssp, unsigned long sp) { @@ -414,9 +516,9 @@ goto cannot_handle; if ((segoffs >> 16) == BIOSSEG) goto cannot_handle; - pushw(ssp, sp, get_vflags(regs)); - pushw(ssp, sp, regs->cs); - pushw(ssp, sp, IP(regs)); + pushw(ssp, sp, get_vflags(regs), regs); + pushw(ssp, sp, regs->cs, regs); + pushw(ssp, sp, IP(regs), regs); regs->cs = segoffs >> 16; SP(regs) -= 6; IP(regs) = segoffs & 0xffff; @@ -460,7 +562,7 @@ #define CHECK_IF_IN_TRAP \ if (VMPI.vm86dbg_active && VMPI.vm86dbg_TFpendig) \ - pushw(ssp,sp,popw(ssp,sp) | TF_MASK); + pushw(ssp,sp,popw(ssp,sp, regs) | TF_MASK, regs); #define VM86_FAULT_RETURN \ if (VMPI.force_return_for_pic && (VEFLAGS & IF_MASK)) \ return_to_32bit(regs, VM86_PICRETURN); \ @@ -471,17 +573,17 @@ sp = SP(regs); ip = IP(regs); - switch (popb(csp, ip)) { + switch (popb(csp, ip, regs)) { /* operand size override */ case 0x66: - switch (popb(csp, ip)) { + switch (popb(csp, ip, regs)) { /* pushfd */ case 0x9c: SP(regs) -= 4; IP(regs) += 2; - pushl(ssp, sp, get_vflags(regs)); + pushl(ssp, sp, get_vflags(regs), regs); VM86_FAULT_RETURN; /* popfd */ @@ -489,16 +591,16 @@ SP(regs) += 4; IP(regs) += 2; CHECK_IF_IN_TRAP - set_vflags_long(popl(ssp, sp), regs); + set_vflags_long(popl(ssp, sp, regs), regs); VM86_FAULT_RETURN; /* iretd */ case 0xcf: SP(regs) += 12; - IP(regs) = (unsigned short)popl(ssp, sp); - regs->cs = (unsigned short)popl(ssp, sp); + IP(regs) = (unsigned short)popl(ssp, sp, regs); + regs->cs = (unsigned short)popl(ssp, sp, regs); CHECK_IF_IN_TRAP - set_vflags_long(popl(ssp, sp), regs); + set_vflags_long(popl(ssp, sp, regs), regs); VM86_FAULT_RETURN; /* need this to avoid a fallthrough */ default: @@ -509,7 +611,7 @@ case 0x9c: SP(regs) -= 2; IP(regs)++; - pushw(ssp, sp, get_vflags(regs)); + pushw(ssp, sp, get_vflags(regs), regs); VM86_FAULT_RETURN; /* popf */ @@ -517,12 +619,12 @@ SP(regs) += 2; IP(regs)++; CHECK_IF_IN_TRAP - set_vflags_short(popw(ssp, sp), regs); + set_vflags_short(popw(ssp, sp, regs), regs); VM86_FAULT_RETURN; /* int xx */ case 0xcd: { - int intno=popb(csp, ip); + int intno=popb(csp, ip, regs); IP(regs) += 2; if (VMPI.vm86dbg_active) { if ( (1 << (intno &7)) & VMPI.vm86dbg_intxxtab[intno >> 3] ) @@ -535,10 +637,10 @@ /* iret */ case 0xcf: SP(regs) += 6; - IP(regs) = popw(ssp, sp); - regs->cs = popw(ssp, sp); + IP(regs) = popw(ssp, sp, regs); + regs->cs = popw(ssp, sp, regs); CHECK_IF_IN_TRAP - set_vflags_short(popw(ssp, sp), regs); + set_vflags_short(popw(ssp, sp, regs), regs); VM86_FAULT_RETURN; /* cli */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/arch/ppc/kernel/ppc_ksyms.c linux.21p1/arch/ppc/kernel/ppc_ksyms.c --- linux.vanilla/arch/ppc/kernel/ppc_ksyms.c Sun Mar 25 17:37:30 2001 +++ linux.21p1/arch/ppc/kernel/ppc_ksyms.c Sat Dec 29 03:07:41 2001 @@ -73,7 +73,7 @@ EXPORT_SYMBOL(isa_mem_base); EXPORT_SYMBOL(pci_dram_offset); EXPORT_SYMBOL(ISA_DMA_THRESHOLD); -EXPORT_SYMBOL(DMA_MODE_READ); +EXPORT_SYMBOL_NOVERS(DMA_MODE_READ); EXPORT_SYMBOL(DMA_MODE_WRITE); #if defined(CONFIG_PREP) || defined(CONFIG_ALL_PPC) EXPORT_SYMBOL(_prep_type); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/block/ll_rw_blk.c linux.21p1/drivers/block/ll_rw_blk.c --- linux.vanilla/drivers/block/ll_rw_blk.c Sat Dec 29 16:57:20 2001 +++ linux.21p1/drivers/block/ll_rw_blk.c Sat Dec 29 03:07:26 2001 @@ -975,7 +975,7 @@ isp16_init(); #endif CONFIG_ISP16_CDI #ifdef CONFIG_BLK_DEV_IDE -#ifdef CONFIG_POWERMAC +#if defined(CONFIG_BLK_DEV_IDE_PMAC) ide_pmac_init(); #else ide_init(); /* this MUST precede hd_init */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/char/bttv.c linux.21p1/drivers/char/bttv.c --- linux.vanilla/drivers/char/bttv.c Sat Dec 29 16:57:21 2001 +++ linux.21p1/drivers/char/bttv.c Sat Dec 29 03:13:31 2001 @@ -1981,7 +1981,7 @@ } } else if (vw.clipcount > 2048) return -ENOMEM; - else { + else if (vw.clipcount) { if((vcp=vmalloc(sizeof(struct video_clip)* (vw.clipcount))) == NULL) return -ENOMEM; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/8139too.c linux.21p1/drivers/net/8139too.c --- linux.vanilla/drivers/net/8139too.c Sat Dec 29 16:57:21 2001 +++ linux.21p1/drivers/net/8139too.c Sat Dec 29 03:20:08 2001 @@ -137,7 +137,7 @@ */ #define DRV_NAME "8139too" -#define DRV_VERSION "0.9.18-pre4" +#define DRV_VERSION "0.9.18-2.2" #include @@ -342,7 +342,7 @@ #define RX_BUF_PAD 16 #define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */ #define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD) -#define RX_EARLY_THRESH 2 +#define RX_EARLY_THRESH 14 /* Number of Tx descriptor registers. */ #define NUM_TX_DESC 4 diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/net/eepro.c linux.21p1/drivers/net/eepro.c --- linux.vanilla/drivers/net/eepro.c Sat Dec 29 16:57:21 2001 +++ linux.21p1/drivers/net/eepro.c Sat Dec 29 03:14:41 2001 @@ -23,6 +23,8 @@ This is a compatibility hardware problem. Versions: + 0.13 irq sharing, rewrote probe function, fixed a nasty bug in + hardware_send_packet and a major cleanup (aris, 11/08/2001) 0.12d tottaly isolated old code to new code (blue cards). (aris, 12/27/2000) 0.12c fixed other multiple cards bug and other cleanups @@ -105,7 +107,7 @@ */ static const char *version = - "eepro.c: v0.12d 12/27/2000 aris@conectiva.com.br\n"; + "eepro.c: v0.13 11/08/2001 aris@cathedrallabs.org\n"; #include @@ -192,18 +194,22 @@ unsigned tx_end; /* end of the transmit chain (plus 1) */ int eepro; /* 1 for the EtherExpress Pro/10, * 2 for the EtherExpress Pro/10+, - * 3 for the blue cards, + * 3 for the EtherExpress 10 (blue cards), * 0 for other 82595-based lan cards. */ int version; /* a flag to indicate if this is a TX or FX * version of the 82595 chip. */ int stepping; spinlock_t lock; /* Serializing lock */ - unsigned rcv_ram; - unsigned rcv_start; - unsigned xmt_bar; - unsigned xmt_lower_limit_reg; - unsigned xmt_upper_limit_reg; - unsigned eeprom_reg; + unsigned rcv_ram; /* pre-calculated space for rx */ + unsigned xmt_ram; /* pre-calculated space for tx */ + unsigned char xmt_bar; + unsigned char xmt_lower_limit_reg; + unsigned char xmt_upper_limit_reg; + short xmt_lower_limit; + short xmt_upper_limit; + short rcv_lower_limit; + short rcv_upper_limit; + unsigned char eeprom_reg; }; /* The station (ethernet) address prefix, used for IDing the board. */ @@ -305,7 +311,7 @@ static struct enet_statistics *eepro_get_stats(struct device *dev); static void set_multicast_list(struct device *dev); -static int read_eeprom(int ioaddr, int location, struct device *dev); +static int read_eeprom(int ioaddr, int location, struct device *dev); static int hardware_send_packet(struct device *dev, void *buf, short length); static int eepro_grab_irq(struct device *dev); @@ -339,35 +345,25 @@ buffer (transmit-buffer = 32K - receive-buffer). */ - -/* now this section could be used by both boards: the oldies and the ee10: - * ee10 uses tx buffer before of rx buffer and the oldies the inverse. - * (aris) - */ #define RAM_SIZE 0x8000 #define RCV_HEADER 8 #define RCV_DEFAULT_RAM 0x6000 -#define RCV_RAM lp->rcv_ram #define XMT_HEADER 8 -#define XMT_RAM (RAM_SIZE - RCV_RAM) - -#define XMT_START ((lp->rcv_start + RCV_RAM) % RAM_SIZE) - -#define RCV_LOWER_LIMIT (lp->rcv_start >> 8) -#define RCV_UPPER_LIMIT (((lp->rcv_start + RCV_RAM) - 2) >> 8) -#define XMT_LOWER_LIMIT (XMT_START >> 8) -#define XMT_UPPER_LIMIT (((XMT_START + XMT_RAM) - 2) >> 8) +#define XMT_DEFAULT_RAM (RAM_SIZE - RCV_DEFAULT_RAM) -#define RCV_START_PRO 0x00 -#define RCV_START_10 XMT_RAM +#define XMT_START_PRO RCV_DEFAULT_RAM +#define XMT_START_10 0x0000 +#define RCV_START_PRO 0x0000 +#define RCV_START_10 XMT_DEFAULT_RAM #define RCV_DONE 0x0008 #define RX_OK 0x2000 #define RX_ERROR 0x0d81 #define TX_DONE_BIT 0x0080 +#define TX_OK 0x2000 #define CHAIN_BIT 0x8000 #define XMT_STATUS 0x02 #define XMT_CHAIN 0x04 @@ -458,7 +454,7 @@ #define EEDO 0x08 /* do a full reset */ -#define eepro_reset(ioaddr) outb(RESET_CMD, ioaddr); udelay(40); +#define eepro_reset(ioaddr) outb(RESET_CMD, ioaddr) /* do a nice reset */ #define eepro_sel_reset(ioaddr) { \ @@ -515,16 +511,14 @@ /* a complete sel reset */ #define eepro_complete_selreset(ioaddr) { \ - /* eepro_dis_int(ioaddr); */ \ lp->stats.tx_errors++;\ eepro_sel_reset(ioaddr);\ lp->tx_end = \ - (XMT_LOWER_LIMIT << 8);\ + lp->xmt_lower_limit;\ lp->tx_start = lp->tx_end;\ lp->tx_last = 0;\ dev->tbusy=0;\ dev->trans_start = jiffies;\ - /*eepro_en_int(ioaddr); */ \ eepro_en_rx(ioaddr);\ } @@ -541,7 +535,7 @@ return eepro_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ - return ENXIO; + return -ENXIO; for (i = 0; eepro_portlist[i]; i++) { int ioaddr = eepro_portlist[i]; @@ -552,7 +546,7 @@ return 0; } - return ENODEV; + return -ENODEV; } static void printEEPROMInfo(short ioaddr, struct device *dev) @@ -562,7 +556,7 @@ for (i=0, j=ee_Checksum; i IRQ %d;",j++,i); + if (GetBit(Word,i)) printk(KERN_DEBUG " INT%d -> IRQ %d;",j++,i); - printk("\n"); + printk(KERN_DEBUG "\n"); } -/* This is the real probe routine. Linux has a history of friendly device - probes on the ISA bus. A good device probe avoids doing writes, and - verifies that the correct device exists and functions. */ - -int eepro_probe1(struct device *dev, short ioaddr) +/* function to recalculate the limits of buffer based on rcv_ram */ +static void eepro_recalc (struct device *dev) { - unsigned short station_addr[6], id, counter; - int i,j, irqMask; - int eepro = 0; - struct eepro_local *lp; - const char *ifmap[] = {"AUI", "10Base2", "10BaseT"}; - enum iftype { AUI=0, BNC=1, TPE=2 }; + struct eepro_local * lp; - /* Now, we are going to check for the signature of the - ID_REG (register 2 of bank 0) */ + lp = dev->priv; + lp->xmt_ram = RAM_SIZE - lp->rcv_ram; - id=inb(ioaddr + ID_REG); - - if (((id) & ID_REG_MASK) == ID_REG_SIG) { - - /* We seem to have the 82595 signature, let's - play with its counter (last 2 bits of - register 2 of bank 0) to be sure. */ - counter = (id & R_ROBIN_BITS); - if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS) == - (counter + 0x40)) { - - /* Yes, the 82595 has been found */ - printk(KERN_DEBUG " id: %#x ",id); - printk(" io: %#x ",ioaddr); - - /* Initialize the device structure */ - dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct eepro_local)); - - lp = (struct eepro_local *)dev->priv; - - /* default values */ - lp->rcv_start = RCV_START_PRO; - lp->xmt_bar = XMT_BAR_PRO; - lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO; - lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO; - lp->eeprom_reg = EEPROM_REG_PRO; - lp->rcv_ram = RCV_DEFAULT_RAM; - - /* Now, get the ethernet hardware address from - the EEPROM */ - - station_addr[0] = read_eeprom(ioaddr, 2, dev); - - /* FIXME - find another way to know that we've found - * a Etherexpress 10 - */ - if (station_addr[0] == 0x0000 || - station_addr[0] == 0xffff) { - eepro = 3; - lp->eepro = LAN595FX_10ISA; - lp->eeprom_reg = EEPROM_REG_10; - lp->rcv_start = RCV_START_10; - lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10; - lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10; - lp->xmt_bar = XMT_BAR_10; + if (lp->eepro == LAN595FX_10ISA) { + lp->xmt_lower_limit = XMT_START_10; + lp->xmt_upper_limit = (lp->xmt_ram - 2); + lp->rcv_lower_limit = lp->xmt_ram; + lp->rcv_upper_limit = (RAM_SIZE - 2); + } + else { + lp->rcv_lower_limit = RCV_START_PRO; + lp->rcv_upper_limit = (lp->rcv_ram - 2); + lp->xmt_lower_limit = lp->rcv_ram; + lp->xmt_upper_limit = (RAM_SIZE - 2); + } +} - station_addr[0] = read_eeprom(ioaddr, 2, dev); - } +/* prints boot-time info */ +static void eepro_print_info (struct device *dev) +{ + struct eepro_local * lp = dev->priv; + int i; + const char * ifmap[] = {"AUI", "10Base2", "10BaseT"}; + + i = inb(dev->base_addr + ID_REG); + printk(KERN_DEBUG " id: %#x ",i); + printk(KERN_DEBUG " io: %#x ", (unsigned)dev->base_addr); + + switch (lp->eepro) { + case LAN595FX_10ISA: + printk(KERN_INFO "%s: Intel EtherExpress 10 ISA\n at %#x,", + dev->name, (unsigned)dev->base_addr); + break; + case LAN595FX: + printk(KERN_INFO "%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", + dev->name, (unsigned)dev->base_addr); + break; + case LAN595TX: + printk(KERN_INFO "%s: Intel EtherExpress Pro/10 ISA at %#x,", + dev->name, (unsigned)dev->base_addr); + break; + case LAN595: + printk(KERN_INFO "%s: Intel 82595-based lan card at %#x,", + dev->name, (unsigned)dev->base_addr); + } - station_addr[1] = read_eeprom(ioaddr, 3, dev); - station_addr[2] = read_eeprom(ioaddr, 4, dev); + for (i=0; i < 6; i++) + printk(KERN_INFO "%c%02x", i ? ':' : ' ', dev->dev_addr[i]); - if (eepro) { - printk("%s: Intel EtherExpress 10 ISA\n at %#x,", - dev->name, ioaddr); - } else if (read_eeprom(ioaddr,7,dev)== ee_FX_INT2IRQ) { - /* int to IRQ Mask */ - eepro = 2; - printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", - dev->name, ioaddr); - } else if (station_addr[2] == SA_ADDR1) { - eepro = 1; - printk("%s: Intel EtherExpress Pro/10 ISA at %#x,", - dev->name, ioaddr); - } - else { - eepro = 0; - printk("%s: Intel 82595-based lan card at %#x,", - dev->name, ioaddr); - } + if (net_debug > 3) + printk(KERN_DEBUG ", %dK RCV buffer", + (int)(lp->rcv_ram)/1024); - /* Fill in the 'dev' fields. */ - dev->base_addr = ioaddr; - - for (i=0; i < 6; i++) { - dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i]; - printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]); - } + if (dev->irq > 2) + printk(KERN_INFO ", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]); + else + printk(KERN_INFO ", %s.\n", ifmap[dev->if_port]); - dev->mem_start = (RCV_LOWER_LIMIT << 8); + if (net_debug > 3) { + i = read_eeprom(dev->base_addr, 5, dev); + if (i & 0x2000) /* bit 13 of EEPROM word 5 */ + printk(KERN_DEBUG "%s: Concurrent Processing is " + "enabled but not used!\n", dev->name); + } - /* received mem_end as argument */ - if ((dev->mem_end & 0x3f) < 3 || /* RX buffer must be more than 3K */ - (dev->mem_end & 0x3f) > 29) /* and less than 29K */ - dev->mem_end = (RCV_UPPER_LIMIT << 8); - else { - dev->mem_end = (dev->mem_end * 1024) + - (RCV_LOWER_LIMIT << 8); - lp->rcv_ram = dev->mem_end - (RCV_LOWER_LIMIT << 8); - } + /* Check the station address for the manufacturer's code */ + if (net_debug>3) + printEEPROMInfo(dev->base_addr, dev); +} - /* From now on, dev->mem_end - dev->mem_start contains - * the actual size of rx buffer - */ - - if (net_debug > 3) - printk(", %dK RCV buffer", - (int)(dev->mem_end - dev->mem_start)/1024); - - /* ............... */ - - if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE)) - dev->if_port = BNC; - else dev->if_port = TPE; - - /* ............... */ - - - if ((dev->irq < 2) && (eepro!=0)) { - i = read_eeprom(ioaddr, 1, dev); - irqMask = read_eeprom(ioaddr, 7, dev); - i &= 0x07; /* Mask off INT number */ - - for (j=0; ((j<16) && (i>=0)); j++) { - if ((irqMask & (1<irq = j; - break; /* found bit corresponding to irq */ - } - i--; /* count bits set in irqMask */ - } - } - if (dev->irq < 2) { - printk(" Duh! illegal interrupt vector stored in EEPROM.\n"); - return ENODEV; - } else - - if (dev->irq==2) - dev->irq = 9; - } - - if (dev->irq > 2) { - printk(", IRQ %d, %s.\n", dev->irq, - ifmap[dev->if_port]); - } - else printk(", %s.\n", ifmap[dev->if_port]); - - if (net_debug > 3) { - i = read_eeprom(ioaddr, 5, dev); - if (i & 0x2000) /* bit 13 of EEPROM word 5 */ - printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n", - dev->name); - } +/* This is the real probe routine. Linux has a history of friendly device + probes on the ISA bus. A good device probe avoids doing writes, and + verifies that the correct device exists and functions. */ - if (net_debug) - printk(version); +int eepro_probe1(struct device *dev, short ioaddr) +{ + unsigned short station_addr[6], + id, + counter; + int i, + j, + irqMask, + retval = 0; + struct eepro_local * lp; + enum iftype { AUI=0, BNC=1, TPE=2 }; - /* Grab the region so we can find another board if autoIRQ fails. */ - request_region(ioaddr, EEPRO_IO_EXTENT, dev->name); + /* Now, we are going to check for the signature of the + * ID_REG (register 2 of bank 0) */ + id = inb(ioaddr + ID_REG); + if (((id) & ID_REG_MASK) != ID_REG_SIG) { + if (net_debug > 3) + printk (KERN_DEBUG "EtherExpress Pro probed failed!\n"); + retval = -ENODEV; + goto exit; + } + + /* We seem to have the 82595 signature, let's + play with its counter (last 2 bits of + register 2 of bank 0) to be sure. */ + counter = (id & R_ROBIN_BITS); + if (((id = inb(ioaddr+ID_REG)) & R_ROBIN_BITS) != (counter + 0x40)) { + retval = -ENODEV; + goto exit; + } + + /* Initialize the device structure */ + dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL); + if (dev->priv == NULL) { + retval = -ENOMEM; + goto exit; + } + memset(dev->priv, 0, sizeof(struct eepro_local)); + lp = (struct eepro_local *)dev->priv; + + /* default values */ + lp->eepro = 0; + lp->xmt_bar = XMT_BAR_PRO; + lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO; + lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO; + lp->eeprom_reg = EEPROM_REG_PRO; + + /* Now, get the ethernet hardware address from + * the EEPROM */ + station_addr[0] = read_eeprom(ioaddr, 2, dev); + + /* FIXME - find another way to know that we've found + * a Etherexpress 10 */ + if (station_addr[0] == 0x0000 || station_addr[0] == 0xffff) { + lp->eepro = LAN595FX_10ISA; + lp->eeprom_reg = EEPROM_REG_10; + lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10; + lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10; + lp->xmt_bar = XMT_BAR_10; + station_addr[0] = read_eeprom(ioaddr, 2, dev); + } + station_addr[1] = read_eeprom(ioaddr, 3, dev); + station_addr[2] = read_eeprom(ioaddr, 4, dev); + + if (!lp->eepro) { + if (read_eeprom(ioaddr,7,dev)== ee_FX_INT2IRQ) + lp->eepro = 2; + else if (station_addr[2] == SA_ADDR1) + lp->eepro = 1; + } - spin_lock_init(&(((struct eepro_local *)dev->priv)->lock)); - dev->open = eepro_open; - dev->stop = eepro_close; - dev->hard_start_xmit = eepro_send_packet; - dev->get_stats = eepro_get_stats; - dev->set_multicast_list = &set_multicast_list; - - /* Fill in the fields of the device structure with - ethernet generic values */ - - ether_setup(dev); - - /* Check the station address for the manufacturer's code */ - if (net_debug>3) - printEEPROMInfo(ioaddr, dev); + /* Fill in the 'dev' fields. */ + dev->base_addr = ioaddr; + for (i=0; i < 6; i++) + dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i]; + + /* RX buffer must be more than 3K and less than 29K */ + if (dev->mem_end < 3072 || dev->mem_end > 29696) + lp->rcv_ram = RCV_DEFAULT_RAM; - /* reset 82595 */ - eepro_reset(ioaddr); + /* calculate {xmt,rcv}_{lower,upper}_limit */ + eepro_recalc(dev); + + if (GetBit(read_eeprom(ioaddr, 5, dev), ee_BNC_TPE)) + dev->if_port = BNC; + else + dev->if_port = TPE; - return 0; + if ((dev->irq < 2) && (lp->eepro != 0)) { + i = read_eeprom(ioaddr, 1, dev); + irqMask = read_eeprom(ioaddr, 7, dev); + i &= 0x07; /* Mask off INT number */ + + for (j=0; ((j<16) && (i>=0)); j++) { + if ((irqMask & (1<irq = j; + /* found bit corresponding to irq */ + break; + } + i--; /* count bits set in irqMask */ } - else return ENODEV; } - else if (net_debug > 3) - printk ("EtherExpress Pro probed failed!\n"); - return ENODEV; + if (dev->irq < 2) { + printk(KERN_ERR " Duh! illegal interrupt vector stored in " + "EEPROM.\n"); + retval = -ENODEV; + goto freeall; + } else + if (dev->irq == 2) dev->irq = 9; + } + /* Grab the region so we can find another board if autoIRQ fails. */ + request_region(ioaddr, EEPRO_IO_EXTENT, dev->name); + spin_lock_init(&(((struct eepro_local *)dev->priv)->lock)); + dev->open = eepro_open; + dev->stop = eepro_close; + dev->hard_start_xmit = eepro_send_packet; + dev->get_stats = eepro_get_stats; + dev->set_multicast_list = &set_multicast_list; + + /* Fill in the fields of the device structure with ethernet generic + * values */ + ether_setup(dev); + + /* print boot time info */ + eepro_print_info(dev); + + /* reset 82595 */ + eepro_reset(ioaddr); + +exit: + return retval; +freeall: + kfree(dev->priv); + goto exit; } /* Open/initialize the board. This is called (in the current kernel) @@ -842,7 +853,7 @@ eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */ - if (request_irq (*irqp, NULL, 0, "bogus", dev) != EBUSY) { + if (request_irq (*irqp, NULL, SA_SHIRQ, "bogus", dev) != -EBUSY) { /* Twinkle the interrupt, and check if it's seen */ autoirq_setup(0); @@ -877,7 +888,6 @@ unsigned short temp_reg, old8, old9; int irqMask; int i, ioaddr = dev->base_addr; - struct eepro_local *lp = (struct eepro_local *)dev->priv; if (net_debug > 3) @@ -906,12 +916,12 @@ /* Get the interrupt vector for the 82595 */ if (dev->irq < 2 && eepro_grab_irq(dev) == 0) { - printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq); + printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); return -EAGAIN; } if (request_irq(dev->irq , &eepro_interrupt, 0, dev->name, dev)) { - printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq); + printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); return -EAGAIN; } @@ -920,6 +930,7 @@ || (irq2dev_map[dev->irq] = dev) == 0) && (irq2dev_map[dev->irq]!=dev)) { /* printk("%s: IRQ map wrong\n", dev->name); */ + free_irq(dev->irq, dev); return -EAGAIN; } #endif @@ -930,7 +941,6 @@ temp_reg = inb(ioaddr + lp->eeprom_reg); lp->stepping = temp_reg >> 5; /* Get the stepping number of the 595 */ - /* Get the stepping number of the 595 */ if (net_debug > 3) printk(KERN_DEBUG "The stepping of the 82595 is %d\n", lp->stepping); @@ -955,12 +965,12 @@ /* Set the interrupt vector */ temp_reg = inb(ioaddr + INT_NO_REG); - if (lp->eepro == 2 || lp->eepro == LAN595FX_10ISA) + if (lp->eepro == LAN595FX || lp->eepro == LAN595FX_10ISA) outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG); else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); temp_reg = inb(ioaddr + INT_NO_REG); - if (lp->eepro == 2 || lp->eepro == LAN595FX_10ISA) + if (lp->eepro == LAN595FX || lp->eepro == LAN595FX_10ISA) outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG); else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); @@ -969,10 +979,10 @@ /* Initialize the RCV and XMT upper and lower limits */ - outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG); - outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG); - outb(XMT_LOWER_LIMIT, ioaddr + lp->xmt_lower_limit_reg); - outb(XMT_UPPER_LIMIT, ioaddr + lp->xmt_upper_limit_reg); + outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG); + outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG); + outb(lp->xmt_lower_limit >> 8, ioaddr + lp->xmt_lower_limit_reg); + outb(lp->xmt_upper_limit >> 8, ioaddr + lp->xmt_upper_limit_reg); /* Enable the interrupt line. */ eepro_en_intline(ioaddr); @@ -986,12 +996,14 @@ eepro_clear_int(ioaddr); /* Initialize RCV */ - outw((RCV_LOWER_LIMIT << 8), ioaddr + RCV_BAR); - lp->rx_start = (RCV_LOWER_LIMIT << 8); - outw(((RCV_UPPER_LIMIT << 8) | 0xfe), ioaddr + RCV_STOP); + outw(lp->rcv_lower_limit, ioaddr + RCV_BAR); + outw((lp->rcv_upper_limit | 0xfe), ioaddr + RCV_STOP); + lp->rx_start = lp->rcv_lower_limit; /* Initialize XMT */ - outw((XMT_LOWER_LIMIT << 8), ioaddr + lp->xmt_bar); + outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar); + lp->tx_start = lp->tx_end = lp->xmt_lower_limit; + lp->tx_last = 0; /* Check for the i82595TX and i82595FX */ old8 = inb(ioaddr + 8); @@ -1034,11 +1046,6 @@ } eepro_sel_reset(ioaddr); - SLOW_DOWN; - SLOW_DOWN; - - lp->tx_start = lp->tx_end = (XMT_LOWER_LIMIT << 8); - lp->tx_last = 0; dev->tbusy = 0; dev->interrupt = 0; @@ -1064,14 +1071,10 @@ if (net_debug > 5) printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name); - if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; + eepro_dis_int(ioaddr); + spin_lock_irqsave(&lp->lock, flags); - if (tickssofar < 40) - return 1; - + if (dev->tbusy) { /* if (net_debug > 1) */ printk(KERN_ERR "%s: transmit timed out, %s?\n", dev->name, "network cable problem"); @@ -1083,33 +1086,29 @@ /* let's do a complete sel reset */ eepro_complete_selreset(ioaddr); } - spin_lock_irqsave(&lp->lock, flags); /* Block a timer-based transmit from overlapping. */ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); - - spin_unlock_irqrestore(&lp->lock, flags); + lp->stats.tx_aborted_errors++; } else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; - - lp->stats.tx_bytes+=skb->len; - if (hardware_send_packet(dev, buf, length)) - return 1; - - dev->trans_start = jiffies; + if (hardware_send_packet(dev, skb->data, length)) + /* we won't unset tbusy because we're out of space. */ + lp->stats.tx_dropped++; + else { + lp->stats.tx_bytes += skb->len; + dev->trans_start = jiffies; + dev->tbusy = 0; + } } - dev_kfree_skb(skb); - /* You might need to clean up and record Tx statistics here. */ - /* lp->stats.tx_aborted_errors++; */ - if (net_debug > 5) printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name); + eepro_en_int(ioaddr); spin_unlock_irqrestore(&lp->lock, flags); return 0; @@ -1122,17 +1121,20 @@ static void eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs) { - struct device *dev = (struct device *)dev_id; - /* (struct device *)(irq2dev_map[irq]);*/ - struct eepro_local *lp = (struct eepro_local *)dev->priv; + struct device *dev; + struct eepro_local *lp; int ioaddr, status, boguscount = 20; - if (dev == NULL) { + if (dev_id == NULL) { printk (KERN_ERR "eepro_interrupt(): irq %d for unknown device.\\n", irq); return; } - spin_lock(&lp->lock); + dev = (struct device *)dev_id; + + lp = (struct eepro_local *)dev->priv; + + spin_lock(&lp->lock); if (dev->interrupt) { printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); @@ -1150,39 +1152,37 @@ ioaddr = dev->base_addr; - while (((status = inb(ioaddr + STATUS_REG)) & 0x06) && (boguscount--)) + eepro_sw2bank0(ioaddr); + + while (((status = inb(ioaddr + STATUS_REG)) & (RX_INT|TX_INT)) && boguscount--) { - switch (status & (RX_INT | TX_INT)) { -#ifdef ANSWER_TX_AND_RX - case (RX_INT | TX_INT): - eepro_ack_rxtx(ioaddr); - break; -#endif - case RX_INT: - eepro_ack_rx(ioaddr); - break; - case TX_INT: - eepro_ack_tx(ioaddr); - } + if (status & RX_INT) { if (net_debug > 4) printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name); + eepro_dis_int(ioaddr); + /* Get the received packets */ + eepro_ack_rx(ioaddr); eepro_rx(dev); -#ifndef ANSWER_TX_AND_RX - continue; -#endif + + eepro_en_int(ioaddr); } if (status & TX_INT) { if (net_debug > 4) printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name); + eepro_dis_int(ioaddr); + /* Process the status of transmitted packets */ + eepro_ack_tx(ioaddr); eepro_transmit_interrupt(dev); + + eepro_en_int(ioaddr); } } - + dev->interrupt = 0; if (net_debug > 5) @@ -1212,7 +1212,7 @@ /* Flush the Tx and disable Rx. */ outb(STOP_RCV_CMD, ioaddr); - lp->tx_start = lp->tx_end = (XMT_LOWER_LIMIT << 8); + lp->tx_start = lp->tx_end = lp->xmt_lower_limit; lp->tx_last = 0; /* Mask all the interrupts. */ @@ -1273,7 +1273,7 @@ mode = inb(ioaddr + REG3); outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */ - printk("%s: promiscuous mode enabled.\n", dev->name); + printk(KERN_INFO "%s: promiscuous mode enabled.\n", dev->name); } else if (dev->mc_count==0 ) @@ -1352,11 +1352,11 @@ outb(0x08, ioaddr + STATUS_REG); if (i & 0x20) { /* command ABORTed */ - printk("%s: multicast setup failed.\n", + printk(KERN_NOTICE "%s: multicast setup failed.\n", dev->name); break; } else if ((i & 0x0f) == 0x03) { /* MC-Done */ - printk("%s: set Rx mode to %d address%s.\n", + printk(KERN_DEBUG "%s: set Rx mode to %d address%s.\n", dev->name, dev->mc_count, dev->mc_count > 1 ? "es":""); break; @@ -1392,14 +1392,10 @@ int read_cmd = location | EE_READ_CMD; short ctrl_val = EECS ; - /* XXXX - this is not the final version. We must test this on other - * boards other than eepro10. I think that it won't let other - * boards to fail. (aris) - */ - if (lp->eepro == LAN595FX_10ISA) { - eepro_sw2bank1(ioaddr); - outb(0x00, ioaddr + STATUS_REG); - } + /* XXXX - black magic */ + eepro_sw2bank1(ioaddr); + outb(0x00, ioaddr + STATUS_REG); + /* XXXX - black magic */ eepro_sw2bank2(ioaddr); outb(ctrl_val, ee_addr); @@ -1437,133 +1433,95 @@ { struct eepro_local *lp = (struct eepro_local *)dev->priv; short ioaddr = dev->base_addr; - - unsigned status, tx_available, last, end, boguscount = 100; + unsigned status, tx_available, last, end; if (net_debug > 5) printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name); + /* determine how much of the transmit buffer space is + * available */ + if (lp->tx_end > lp->tx_start) + tx_available = lp->xmt_ram - (lp->tx_end - + lp->tx_start); + else if (lp->tx_end < lp->tx_start) + tx_available = lp->tx_start - lp->tx_end; + else tx_available = lp->xmt_ram; - while (boguscount-- > 0) { - /* Disable RX and TX interrupts. Necessary to avoid - corruption of the HOST_ADDRESS_REG by interrupt - service routines. */ - eepro_dis_int(ioaddr); - - if (dev->interrupt == 1) { - /* Enable RX and TX interrupts */ - eepro_en_int(ioaddr); - continue; - } - - /* determine how much of the transmit buffer space is available */ - if (lp->tx_end > lp->tx_start) - tx_available = XMT_RAM - (lp->tx_end - lp->tx_start); - else if (lp->tx_end < lp->tx_start) - tx_available = lp->tx_start - lp->tx_end; - else tx_available = XMT_RAM; - - if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) - >= tx_available) /* No space available ??? */ - { - eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */ - - /* Enable RX and TX interrupts */ - eepro_en_int(ioaddr); - continue; - } - - last = lp->tx_end; - end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; - - if (end >= (XMT_UPPER_LIMIT << 8)) { /* the transmit buffer is wrapped around */ - if (((XMT_UPPER_LIMIT << 8) - last) <= XMT_HEADER) { - /* Arrrr!!!, must keep the xmt header together, - several days were lost to chase this one down. */ - - last = (XMT_LOWER_LIMIT << 8); - end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; - } - else end = (XMT_LOWER_LIMIT << 8) + (end - - (XMT_UPPER_LIMIT << 8)); - } - - outw(last, ioaddr + HOST_ADDRESS_REG); - outw(XMT_CMD, ioaddr + IO_PORT); - outw(0, ioaddr + IO_PORT); - outw(end, ioaddr + IO_PORT); - outw(length, ioaddr + IO_PORT); - - if (lp->version == LAN595) - outsw(ioaddr + IO_PORT, buf, (length + 3) >> 1); - else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */ - unsigned short temp = inb(ioaddr + INT_MASK_REG); - outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG); - outsl(ioaddr + IO_PORT_32_BIT, buf, (length + 3) >> 2); - outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG); - } + if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) >= tx_available) { + /* No space available ??? */ + return 1; + } - /* A dummy read to flush the DRAM write pipeline */ - status = inw(ioaddr + IO_PORT); + last = lp->tx_end; + end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; - if (lp->tx_start == lp->tx_end) { - outw(last, ioaddr + lp->xmt_bar); - outb(XMT_CMD, ioaddr); - lp->tx_start = last; /* I don't like to change tx_start here */ - } - else { - /* update the next address and the chain bit in the - last packet */ - if (lp->tx_end != last) { - outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG); - outw(last, ioaddr + IO_PORT); - } + if (end >= lp->xmt_upper_limit + 2) { + /* the transmit buffer is wrapped around */ + if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) { + /* Arrrr!!!, must keep the xmt header together, + several days were lost to chase this one down. */ - outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG); - status = inw(ioaddr + IO_PORT); - outw(status | CHAIN_BIT, ioaddr + IO_PORT); - /* Continue the transmit command */ - outb(RESUME_XMT_CMD, ioaddr); - } - - lp->tx_last = last; - lp->tx_end = end; - - if (dev->tbusy) { - dev->tbusy = 0; + last = lp->xmt_lower_limit; + end = last + (((length + 3) >> 1) << 1) + + XMT_HEADER; + } + else end = lp->xmt_lower_limit + (end - + lp->xmt_upper_limit + 2); + } + + outw(last, ioaddr + HOST_ADDRESS_REG); + outw(XMT_CMD, ioaddr + IO_PORT); + outw(0, ioaddr + IO_PORT); + outw(end, ioaddr + IO_PORT); + outw(length, ioaddr + IO_PORT); + + if (lp->version == LAN595) + outsw(ioaddr + IO_PORT, buf, (length + 3) >> 1); + else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */ + unsigned short temp = inb(ioaddr + INT_MASK_REG); + outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG); + outsl(ioaddr + IO_PORT_32_BIT, buf, (length + 3) >> 2); + outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG); + } + + /* A dummy read to flush the DRAM write pipeline */ + status = inw(ioaddr + IO_PORT); + if (lp->tx_start == lp->tx_end) { + outw(last, ioaddr + lp->xmt_bar); + outb(XMT_CMD, ioaddr); + lp->tx_start = last; /* I don't like to change tx_start here */ + } + else { + /* update the next address and the chain bit in the + last packet */ + if (lp->tx_end != last) { + outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG); + outw(last, ioaddr + IO_PORT); } - - /* now we are serializing tx. tbusy won't come back until - * the tx interrupt - */ - if (lp->eepro == LAN595FX_10ISA) - dev->tbusy = 1; - - /* Enable RX and TX interrupts */ - eepro_en_int(ioaddr); - - if (net_debug > 5) - printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name); - return 0; + outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG); + status = inw(ioaddr + IO_PORT); + outw(status | CHAIN_BIT, ioaddr + IO_PORT); + /* Continue the transmit command */ + outb(RESUME_XMT_CMD, ioaddr); } - if (lp->eepro == LAN595FX_10ISA) - dev->tbusy = 1; + + lp->tx_last = last; + lp->tx_end = end; if (net_debug > 5) printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name); - return 1; + return 0; } static void eepro_rx(struct device *dev) { struct eepro_local *lp = (struct eepro_local *)dev->priv; - short ioaddr = dev->base_addr; - - short boguscount = 20; - unsigned rcv_car = lp->rx_start; + short ioaddr = dev->base_addr, + boguscount = 25, + rcv_car = lp->rx_start; unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size; if (net_debug > 5) @@ -1575,7 +1533,6 @@ rcv_event = inw(ioaddr + IO_PORT); while (rcv_event == RCV_DONE) { - rcv_status = inw(ioaddr + IO_PORT); rcv_next_frame = inw(ioaddr + IO_PORT); rcv_size = inw(ioaddr + IO_PORT); @@ -1624,24 +1581,26 @@ else if (rcv_status & 0x0800) lp->stats.rx_crc_errors++; - printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n", + printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n", dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size); } if (rcv_status & 0x1000) lp->stats.rx_length_errors++; - if (--boguscount == 0) - break; rcv_car = lp->rx_start + RCV_HEADER + rcv_size; lp->rx_start = rcv_next_frame; + + if (--boguscount == 0) + break; + outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG); rcv_event = inw(ioaddr + IO_PORT); } if (rcv_car == 0) - rcv_car = ((RCV_UPPER_LIMIT << 8) | 0xff); + rcv_car = lp->rcv_upper_limit | 0xff; outw(rcv_car - 1, ioaddr + RCV_STOP); @@ -1653,59 +1612,25 @@ eepro_transmit_interrupt(struct device *dev) { struct eepro_local *lp = (struct eepro_local *)dev->priv; - short ioaddr = dev->base_addr; - short boguscount = 20; - unsigned xmt_status; - - /* - if (dev->tbusy == 0) { - printk("%s: transmit_interrupt called with tbusy = 0 ??\n", - dev->name); - printk(KERN_DEBUG "%s: transmit_interrupt called with tbusy = 0 ??\n", - dev->name); - } - */ - while (lp->tx_start != lp->tx_end && boguscount) { + short ioaddr = dev->base_addr, + boguscount = 25, + xmt_status; + while ((lp->tx_start != lp->tx_end) && boguscount--) { outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); xmt_status = inw(ioaddr+IO_PORT); - if ((xmt_status & TX_DONE_BIT) == 0) { - if (lp->eepro == LAN595FX_10ISA) { - udelay(40); - boguscount--; - continue; - } - else - break; - } - - - xmt_status = inw(ioaddr+IO_PORT); - lp->tx_start = inw(ioaddr+IO_PORT); - - if (lp->eepro == LAN595FX_10ISA) { - lp->tx_start = (XMT_LOWER_LIMIT << 8); - lp->tx_end = lp->tx_start; - - /* yeah, black magic :( */ - eepro_sw2bank0(ioaddr); - eepro_en_int(ioaddr); + /* are we trying to get a packet not ready? */ + if ((xmt_status & TX_DONE_BIT) == 0) + break; - /* disabling rx */ - eepro_dis_rx(ioaddr); - - /* enabling rx */ - eepro_en_rx(ioaddr); - } + xmt_status = inw(ioaddr+IO_PORT); + lp->tx_start = inw(ioaddr + IO_PORT); - /* here the tbusy comes to 0 for normal and ee10 cards - */ dev->tbusy = 0; - mark_bh(NET_BH); - - if (xmt_status & 0x2000) { + + if (xmt_status & TX_OK) { lp->stats.tx_packets++; } else { @@ -1714,45 +1639,17 @@ lp->stats.tx_carrier_errors++; printk(KERN_DEBUG "%s: carrier error\n", dev->name); - printk(KERN_DEBUG "%s: XMT status = %#x\n", - dev->name, xmt_status); } - else { - printk(KERN_DEBUG "%s: XMT status = %#x\n", - dev->name, xmt_status); - printk(KERN_DEBUG "%s: XMT status = %#x\n", + printk(KERN_DEBUG "%s: XMT status = %#x\n", dev->name, xmt_status); - } - - if (lp->eepro == LAN595FX_10ISA) { - /* Try to restart the adaptor. */ - /* We are supposed to wait for 2 us after a SEL_RESET */ - eepro_sel_reset(ioaddr); - - /* first enable interrupts */ - eepro_sw2bank0(ioaddr); - outb(ALL_MASK & ~(RX_INT | TX_INT), ioaddr + STATUS_REG); - - /* enabling rx */ - eepro_en_rx(ioaddr); - } } - if (xmt_status & 0x000f) { + if (xmt_status & 0x000f) lp->stats.collisions += (xmt_status & 0x000f); - } - if ((xmt_status & 0x0040) == 0x0) { + if (!(xmt_status & 0x0040)) lp->stats.tx_heartbeat_errors++; - } - boguscount--; } - /* if it reached here then it's probable that the adapter won't - * interrupt again for tx. in other words: tx timeout what will take - * a lot of time to happen, so we'll do a complete selreset. - */ - if (!boguscount && lp->eepro == LAN595FX_10ISA) - eepro_complete_selreset(ioaddr); } #ifdef MODULE @@ -1781,23 +1678,23 @@ { int i; if (io[0] == 0 && autodetect == 0) { - printk("eepro_init_module: Probe is very dangerous in ISA boards!\n"); - printk("eepro_init_module: Please add \"autodetect=1\" to force probe\n"); + printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n"); + printk(KERN_WARNING "eepro_init_module: Please add \"autodetect=1\" to force probe\n"); return 1; } else if (autodetect) { /* if autodetect is set then we must force detection */ io[0] = 0; - printk("eepro_init_module: Auto-detecting boards (May God protect us...)\n"); + printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n"); } for (i = 0; i < MAX_EEPRO; i++) { struct device *d = &dev_eepro[n_eepro]; d->name = devicename[n_eepro]; /* inserted by drivers/net/net_init.c */ - d->mem_end = mem[n_eepro]; - d->base_addr = io[0]; - d->irq = irq[n_eepro]; + d->mem_end = mem[i]; + d->base_addr = io[i]; + d->irq = irq[i]; d->init = eepro_probe; if (register_netdev(d) == 0) @@ -1805,7 +1702,10 @@ else break; } - + + if (n_eepro) + printk(KERN_INFO "%s", version); + return n_eepro ? 0 : -ENODEV; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/3w-xxxx.c linux.21p1/drivers/scsi/3w-xxxx.c --- linux.vanilla/drivers/scsi/3w-xxxx.c Sat Dec 29 16:57:22 2001 +++ linux.21p1/drivers/scsi/3w-xxxx.c Sat Dec 29 03:11:00 2001 @@ -4,6 +4,7 @@ Written By: Adam Radford Modifications By: Joel Jacobson Arnaldo Carvalho de Melo + Brad Strand Copyright (C) 1999-2001 3ware Inc. @@ -98,6 +99,11 @@ Fix possible null pointer dereference in tw_aen_drain_queue() during initialization. Clear pci parity errors during initialization and during io. + 1.02.00.009 - Remove redundant increment in tw_state_request_start(). + Add ioctl support for direct ATA command passthru. + Add entire aen code string list. + 1.02.00.010 - Cleanup queueing code, fix jbod throughput. + Fix get_param for specific units. */ #include @@ -149,7 +155,7 @@ }; /* Globals */ -char *tw_driver_version="1.02.00.008"; +char *tw_driver_version="1.02.00.010"; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; int tw_device_extension_count = 0; @@ -170,21 +176,17 @@ dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen); /* Print some useful info when certain aen codes come out */ - switch (aen & 0x0ff) { - case TW_AEN_APORT_TIMEOUT: - printk(KERN_WARNING "3w-xxxx: scsi%d: Received drive timeout AEN on port %d, check drive and drive cables.\n", tw_dev->host->host_no, aen >> 8); - break; - case TW_AEN_DRIVE_ERROR: - printk(KERN_WARNING "3w-xxxx: scsi%d: Received drive error AEN on port %d, check/replace cabling, or possible bad drive.\n", tw_dev->host->host_no, aen >> 8); - break; - case TW_AEN_SMART_FAIL: - printk(KERN_WARNING "3w-xxxx: scsi%d: Received S.M.A.R.T. threshold AEN on port %d, check drive/cooling, or possible bad drive.\n", tw_dev->host->host_no, aen >> 8); - break; - case TW_AEN_SBUF_FAIL: - printk(KERN_WARNING "3w-xxxx: scsi%d: Received SBUF integrity check failure AEN, reseat card or bad card.\n", tw_dev->host->host_no); - break; - default: - printk(KERN_WARNING "3w-xxxx: Received AEN 0x%x\n", aen); + if (aen == 0x0ff) { + printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: AEN queue overflow.\n", tw_dev->host->host_no); + } else { + if ((aen & 0x0ff) < TW_AEN_STRING_MAX) { + if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') { + printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8); + } else { + printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff]); + } + } else + printk(KERN_WARNING "3w-xxxx: scsi%d: Received AEN %d.\n", tw_dev->host->host_no, aen); } tw_dev->aen_count++; @@ -236,7 +238,7 @@ response_que_addr = tw_dev->registers.response_que_addr; if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT, 15)) { - printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d\n", tw_device_extension_count); + dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d\n", tw_device_extension_count); return 1; } @@ -292,7 +294,7 @@ mdelay(5); status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { - printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n"); + dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n"); tw_decode_bits(tw_dev, status_reg_value); return 1; } @@ -309,7 +311,8 @@ if (command_packet->status != 0) { if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) { /* Bad response */ - printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); + dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); + tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit); return 1; } else { /* We know this is a 3w-1x00, and doesn't support aen's */ @@ -429,7 +432,7 @@ status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { - printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n"); + dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n"); tw_decode_bits(tw_dev, status_reg_value); return 1; } @@ -527,11 +530,11 @@ int tw_check_bits(u32 status_reg_value) { if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) { - printk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value); + dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value); return 1; } if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) { - printk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value); + dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value); return 1; } @@ -635,9 +638,13 @@ case 0x51: printk(KERN_WARNING "3w-xxxx: scsi%d: Unrecoverable drive error on unit %d, check/replace cabling, or possible bad drive.\n", tw_dev->host->host_no, unit); break; - } + default: + printk(KERN_WARNING "3w-xxxx: scsi%d: Controller error: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, status, flags, unit); + } break; - } + default: + printk(KERN_WARNING "3w-xxxx: scsi%d: Controller error: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, status, flags, unit); + } } /* End tw_decode_error() */ /* This function will disable interrupts on the controller */ @@ -662,7 +669,7 @@ status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { - printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n"); + dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n"); tw_decode_bits(tw_dev, status_reg_value); return 1; } @@ -671,7 +678,7 @@ response_que_value = inl(response_que_addr); status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { - printk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n"); + dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n"); tw_decode_bits(tw_dev, status_reg_value); return 1; } @@ -817,9 +824,20 @@ continue; } - /* Calculate max cmds per lun */ - if (tw_dev->num_units > 0) - tw_host->cmd_per_lun = (TW_Q_LENGTH-2)/tw_dev->num_units; + /* Calculate max cmds per lun, and setup queues */ + if (tw_dev->num_units > 0) { + if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) { + tw_host->cmd_per_lun = (TW_MAX_BOUNCEBUF-1)/tw_dev->num_units; + tw_dev->free_head = TW_Q_START; + tw_dev->free_tail = TW_MAX_BOUNCEBUF - 1; + tw_dev->free_wrap = TW_MAX_BOUNCEBUF - 1; + } else { + tw_host->cmd_per_lun = (TW_Q_LENGTH-1)/tw_dev->num_units; + tw_dev->free_head = TW_Q_START; + tw_dev->free_tail = TW_Q_LENGTH - 1; + tw_dev->free_wrap = TW_Q_LENGTH - 1; + } + } /* Register the card with the kernel SCSI layer */ host = scsi_register(tw_host, sizeof(TW_Device_Extension)); @@ -890,18 +908,19 @@ /* This function will free up device extension resources */ void tw_free_device_extension(TW_Device_Extension *tw_dev) { - int i, imax; - imax = TW_Q_LENGTH; + int i; dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n"); /* Free command packet and generic buffer memory */ - for (i=0;icommand_packet_virtual_address[i]) kfree(tw_dev->command_packet_virtual_address[i]); if (tw_dev->alignment_virtual_address[i]) kfree(tw_dev->alignment_virtual_address[i]); + } + for (i=0;ibounce_buffer[i]) kfree(tw_dev->bounce_buffer[i]); } @@ -913,7 +932,7 @@ int i; for (i=0;istatus != 0) { /* bad response */ - printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); + dprintk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); + tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit); return 1; } break; /* Response was okay, so we exit */ @@ -1034,8 +1054,6 @@ tw_dev->num_units = 0; tw_dev->num_aborts = 0; tw_dev->num_resets = 0; - tw_dev->free_head = TW_Q_START; - tw_dev->free_tail = TW_Q_LENGTH - 1; tw_dev->posted_request_count = 0; tw_dev->max_posted_request_count = 0; tw_dev->max_sgl_entries = 0; @@ -1125,7 +1143,7 @@ mdelay(5); status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { - printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n"); + dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n"); tw_decode_bits(tw_dev, status_reg_value); return 1; } @@ -1139,7 +1157,8 @@ } if (command_packet->status != 0) { /* bad response */ - printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); + dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); + tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit); return 1; } found = 1; @@ -1228,7 +1247,7 @@ mdelay(5); status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { - printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n"); + dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n"); tw_decode_bits(tw_dev, status_reg_value); return 1; } @@ -1242,7 +1261,8 @@ } if (command_packet->status != 0) { /* bad response */ - printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); + dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); + tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit); return 1; } found = 1; @@ -1267,13 +1287,13 @@ /* Now allocate raid5 bounce buffers */ if ((num_raid_five != 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) { - for (i=0;ibounce_buffer[i] == NULL) { printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bounce buffer allocation failed.\n"); return 1; } - memset(tw_dev->bounce_buffer[i], 0, sizeof(TW_Sector)*128); + memset(tw_dev->bounce_buffer[i], 0, sizeof(TW_Sector)*TW_MAX_SECTORS); } } @@ -1330,7 +1350,7 @@ tw_state_request_start(tw_dev, &request_id); error = tw_aen_read_queue(tw_dev, request_id); if (error) { - printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Error reading aen queue.\n"); + printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no); tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); } @@ -1342,7 +1362,7 @@ while (tw_dev->pending_request_count > 0) { request_id = tw_dev->pending_queue[tw_dev->pending_head]; if (tw_dev->state[request_id] != TW_S_PENDING) { - printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found request id that wasn't pending.\n"); + printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no); break; } if (tw_post_command_packet(tw_dev, request_id)==0) { @@ -1370,12 +1390,12 @@ command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; error = 0; if (command_packet->status != 0) { - printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, status = 0x%x, flags = 0x%x, unit = 0x%x.\n", command_packet->status, command_packet->flags, command_packet->byte3.unit); + dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Bad response, status = 0x%x, flags = 0x%x, unit = 0x%x.\n", command_packet->status, command_packet->flags, command_packet->byte3.unit); tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit); error = 1; } if (tw_dev->state[request_id] != TW_S_POSTED) { - printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", request_id, command_packet->byte0.opcode); + printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode); error = 1; } if (TW_STATUS_ERRORS(status_reg_value)) { @@ -1388,24 +1408,22 @@ dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n"); error = tw_aen_complete(tw_dev, request_id); if (error) { - printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Error completing aen.\n"); + printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no); } status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { - printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); + dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); tw_decode_bits(tw_dev, status_reg_value); } } else { switch (tw_dev->srb[request_id]->cmnd[0]) { case READ_10: - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10\n"); case READ_6: - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_6\n"); + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n"); break; case WRITE_10: - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10\n"); case WRITE_6: - dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_6\n"); + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n"); break; case INQUIRY: dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n"); @@ -1420,7 +1438,7 @@ error = tw_ioctl_complete(tw_dev, request_id); break; default: - printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unknown scsi opcode: 0x%x.\n", tw_dev->srb[request_id]->cmnd[0]); + printk(KERN_WARNING "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x.\n", tw_dev->host->host_no, tw_dev->srb[request_id]->cmnd[0]); tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16); tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); } @@ -1438,7 +1456,7 @@ tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { - printk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); + dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); tw_decode_bits(tw_dev, status_reg_value); } } @@ -1458,6 +1476,7 @@ TW_Command *command_packet; u32 param_value; TW_Ioctl *ioctl = NULL; + TW_Passthru *passthru = NULL; int tw_aen_code; ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer; @@ -1506,6 +1525,7 @@ case TW_OP_GET_PARAM: dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_GET_PARAM.\n"); command_packet->byte0.opcode = TW_OP_GET_PARAM; + command_packet->byte3.unit = ioctl->unit_index; param->table_id = ioctl->table_id; param->parameter_id = ioctl->parameter_id; param->parameter_size_bytes = ioctl->parameter_size_bytes; @@ -1549,6 +1569,25 @@ tw_dev->srb[request_id]->result = (DID_OK << 16); tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); return 0; + case TW_ATA_PASSTHRU: + if (ioctl->data != NULL) { + memcpy(command_packet, ioctl->data, sizeof(TW_Command)); + command_packet->request_id = request_id; + } else { + printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n"); + return 1; + } + + passthru = (TW_Passthru *)tw_dev->command_packet_virtual_address[request_id]; + passthru->sg_list[0].length = passthru->sector_count*512; + if (passthru->sg_list[0].length > TW_MAX_PASSTHRU_BYTES) { + printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Passthru size (%ld) too big.\n", passthru->sg_list[0].length); + return 1; + } + passthru->sg_list[0].address = virt_to_bus(tw_dev->alignment_virtual_address[request_id]); + tw_post_command_packet(tw_dev, request_id); + return 0; + case TW_CMD_PACKET: if (ioctl->data != NULL) { memcpy(command_packet, ioctl->data, sizeof(TW_Command)); @@ -1583,7 +1622,6 @@ command_packet->byte0.sgl_offset = 2; command_packet->size = 4; command_packet->request_id = request_id; - command_packet->byte3.unit = 0; command_packet->byte3.host_id = 0; command_packet->status = 0; command_packet->flags = 0; @@ -1601,7 +1639,10 @@ unsigned char *param_data; unsigned char *buff; TW_Param *param; + TW_Ioctl *ioctl = NULL; + TW_Passthru *passthru = NULL; + ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer; dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete()\n"); buff = tw_dev->srb[request_id]->request_buffer; if (buff == NULL) { @@ -1609,16 +1650,23 @@ return 1; } dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete(): Request_bufflen = %d\n", tw_dev->srb[request_id]->request_bufflen); - memset(buff, 0, tw_dev->srb[request_id]->request_bufflen); - param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; - if (param == NULL) { - printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n"); - return 1; - } - param_data = &(param->data[0]); - - memcpy(buff, param_data, tw_dev->ioctl_size[request_id]); + ioctl = (TW_Ioctl *)buff; + switch (ioctl->opcode) { + case TW_ATA_PASSTHRU: + passthru = (TW_Passthru *)ioctl->data; + memcpy(buff, tw_dev->alignment_virtual_address[request_id], passthru->sector_count * 512); + break; + default: + memset(buff, 0, tw_dev->srb[request_id]->request_bufflen); + param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; + if (param == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Bad alignment virtual address.\n"); + return 1; + } + param_data = &(param->data[0]); + memcpy(buff, param_data, tw_dev->ioctl_size[request_id]); + } return 0; } /* End tw_ioctl_complete() */ @@ -1646,7 +1694,7 @@ status_reg_value = inl(status_reg_addr); do_gettimeofday(&timeout); if (before.tv_sec + seconds < timeout.tv_sec) { - printk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag); + dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag); return 1; } mdelay(1); @@ -1667,7 +1715,7 @@ status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { - printk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n"); + dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n"); tw_decode_bits(tw_dev, status_reg_value); } @@ -1711,7 +1759,7 @@ imax = TW_Q_LENGTH; if (tw_reset_sequence(tw_dev)) { - printk(KERN_WARNING "3w-xxxx: tw_reset_device_extension(): Reset sequence failed for card %d.\n", tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no); return 1; } @@ -1758,14 +1806,14 @@ error = tw_aen_drain_queue(tw_dev); if (error) { - printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): No attention interrupt for card %d.\n", tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: scsi%d: Card not responding, retrying.\n", tw_dev->host->host_no); tries++; continue; } /* Check for controller errors */ if (tw_check_errors(tw_dev)) { - printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Controller errors found, soft resetting card %d.\n", tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors found, retrying.\n", tw_dev->host->host_no); tries++; continue; } @@ -1773,7 +1821,7 @@ /* Empty the response queue again */ error = tw_empty_response_que(tw_dev); if (error) { - printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't empty response queue for card %d.\n", tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: scsi%d: Couldn't empty response queue, retrying.\n", tw_dev->host->host_no); tries++; continue; } @@ -1783,13 +1831,13 @@ } if (tries >= TW_MAX_RESET_TRIES) { - printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Controller error or no attention interrupt: giving up for card %d.\n", tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors, card not responding, check all cabling.\n", tw_dev->host->host_no); return 1; } error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS); if (error) { - printk(KERN_WARNING "3w-xxxx: tw_reset_sequence(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: scsi%d: Connection initialization failed.\n", tw_dev->host->host_no); return 1; } @@ -1879,14 +1927,14 @@ for (i=0;isrb[i] == SCpnt) { if (tw_dev->state[i] == TW_S_STARTED) { - printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for started Scsi_Cmnd 0x%x\n", (u32)tw_dev->srb[i]); + printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, (u32)SCpnt); tw_dev->state[i] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, i); spin_unlock(&tw_dev->tw_lock); return (SUCCESS); } if (tw_dev->state[i] == TW_S_PENDING) { - printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort succeeded for pending Scsi_Cmnd 0x%x\n", (u32)tw_dev->srb[i]); + printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out.\n", tw_dev->host->host_no, (u32)SCpnt); if (tw_dev->pending_head == TW_Q_LENGTH-1) { tw_dev->pending_head = TW_Q_START; } else { @@ -1902,10 +1950,9 @@ } /* If the command has already been posted, we have to reset the card */ - printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Abort failed for unknown Scsi_Cmnd 0x%x, resetting card %d.\n", (u32)SCpnt, tw_dev->host->host_no); - + printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, (u32)SCpnt); if (tw_reset_device_extension(tw_dev)) { - printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no); + dprintk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no); spin_unlock(&tw_dev->tw_lock); return (FAILED); } @@ -1943,11 +1990,11 @@ /* Now reset the card and some of the device extension data */ if (tw_reset_device_extension(tw_dev)) { - printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Reset failed for card %d.\n", tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no); spin_unlock_irqrestore(&tw_dev->tw_lock, flags); return (FAILED); } - printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Reset succeeded for card %d.\n", tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: scsi%d: Reset succeeded.\n", tw_dev->host->host_no); spin_unlock_irqrestore(&tw_dev->tw_lock, flags); return (SUCCESS); @@ -2060,13 +2107,10 @@ switch (*command) { case READ_10: - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_10.\n"); case READ_6: - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_6.\n"); case WRITE_10: - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_10.\n"); case WRITE_6: - dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught WRITE_6.\n"); + dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ/WRITE.\n"); error = tw_scsiop_read_write(tw_dev, request_id); break; case TEST_UNIT_READY: @@ -2090,7 +2134,7 @@ error = tw_ioctl(tw_dev, request_id); break; default: - printk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): Unknown scsi opcode: 0x%x\n", *command); + printk(KERN_NOTICE "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x\n", tw_dev->host->host_no, *command); tw_dev->state[request_id] = TW_S_COMPLETED; tw_state_request_finish(tw_dev, request_id); SCpnt->result = (DID_BAD_TARGET << 16); @@ -2558,7 +2602,7 @@ mdelay(5); status_reg_value = inl(status_reg_addr); if (tw_check_bits(status_reg_value)) { - printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n"); + dprintk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n"); tw_decode_bits(tw_dev, status_reg_value); return 1; } @@ -2572,7 +2616,8 @@ } if (command_packet->status != 0) { /* bad response */ - printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); + dprintk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad response, status = 0x%x, flags = 0x%x.\n", command_packet->status, command_packet->flags); + tw_decode_error(tw_dev, command_packet->status, command_packet->flags, command_packet->byte3.unit); return 1; } break; /* Response was okay, so we exit */ @@ -2592,7 +2637,7 @@ error = request_irq(tw_dev->tw_pci_dev->irq, tw_interrupt, SA_SHIRQ, device, tw_dev); if (error < 0) { - printk(KERN_WARNING "3w-xxxx: tw_setup_irq(): Error requesting IRQ: %d for card %d.\n", tw_dev->tw_pci_dev->irq, tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: scsi%d: Error requesting IRQ: %d.\n", tw_dev->host->host_no, tw_dev->tw_pci_dev->irq); return 1; } return 0; @@ -2610,9 +2655,9 @@ /* poke the board */ error = tw_initconnection(tw_dev, 1); if (error) { - printk(KERN_WARNING "3w-xxxx: tw_shutdown_device(): Couldn't initconnection for card %d.\n", tw_dev->host->host_no); + printk(KERN_WARNING "3w-xxxx: scsi%d: Connection shutdown failed.\n", tw_dev->host->host_no); } else { - printk(KERN_NOTICE "3w-xxxx shutdown succeeded\n"); + printk(KERN_NOTICE "3w-xxxx: Shutdown complete.\n"); } /* Re-enable interrupts */ @@ -2643,7 +2688,7 @@ dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish()\n"); do { - if (tw_dev->free_tail == TW_Q_LENGTH-1) { + if (tw_dev->free_tail == tw_dev->free_wrap) { tw_dev->free_tail = TW_Q_START; } else { tw_dev->free_tail = tw_dev->free_tail + 1; @@ -2667,23 +2712,14 @@ /* Obtain next free request_id */ do { - if (tw_dev->free_head == TW_Q_LENGTH - 1) { + if (tw_dev->free_head == tw_dev->free_wrap) { tw_dev->free_head = TW_Q_START; } else { tw_dev->free_head = tw_dev->free_head + 1; } - } while ((tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_STARTED) || - (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_POSTED) || - (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_PENDING) || - (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] == TW_S_COMPLETED)); + } while (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] & TW_START_MASK); id = tw_dev->free_queue[tw_dev->free_head]; - - if (tw_dev->free_head == TW_Q_LENGTH - 1) { - tw_dev->free_head = TW_Q_START; - } else { - tw_dev->free_head = tw_dev->free_head + 1; - } dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start(): id = %d.\n", id); *request_id = id; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/3w-xxxx.h linux.21p1/drivers/scsi/3w-xxxx.h --- linux.vanilla/drivers/scsi/3w-xxxx.h Sat Dec 29 16:57:22 2001 +++ linux.21p1/drivers/scsi/3w-xxxx.h Sat Dec 29 03:50:08 2001 @@ -4,6 +4,7 @@ Written By: Adam Radford Modifications By: Joel Jacobson Arnaldo Carvalho de Melo + Brad Strand Copyright (C) 1999-2001 3ware Inc. @@ -57,6 +58,43 @@ #include #include +/* AEN strings */ +static char *tw_aen_string[] = { + "AEN queue empty", // 0x000 + "Soft reset occurred", // 0x001 + "Mirorr degraded: Unit #", // 0x002 + "Controller error", // 0x003 + "Rebuild failed: Unit #", // 0x004 + "Rebuild complete: Unit #", // 0x005 + "Incomplete unit detected: Unit #", // 0x006 + "Initialization complete: Unit #", // 0x007 + "Unclean shutdown detected: Unit #", // 0x008 + "ATA port timeout: Port #", // 0x009 + "Drive error: Port #", // 0x00A + "Rebuild started: Unit #", // 0x00B + "Initialization started: Unit #", // 0x00C + "Logical unit deleted: Unit #", // 0x00D + NULL, // 0x00E unused + "SMART threshold exceeded: Port #", // 0x00F + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, // 0x010-0x020 unused + "ATA UDMA downgrade: Port #", // 0x021 + "ATA UDMA upgrade: Port #", // 0x022 + "Sector repair occurred: Port #", // 0x023 + "SBUF integrity check failure", // 0x024 + "Lost cached write: Port #", // 0x025 + "Drive ECC error detected: Port #", // 0x026 + "DCB checksum error: Port #", // 0x027 + "DCB unsupported version: Port #", // 0x028 + "Verify started: Unit #", // 0x029 + "Verify failed: Port #", // 0x02A + "Verify complete: Unit #" // 0x02B +}; + +#define TW_AEN_STRING_MAX 0x02C + /* Control register bit definitions */ #define TW_CONTROL_CLEAR_HOST_INTERRUPT 0x00080000 #define TW_CONTROL_CLEAR_ATTENTION_INTERRUPT 0x00040000 @@ -114,6 +152,7 @@ #define TW_OP_SECTOR_INFO 0x1a #define TW_OP_AEN_LISTEN 0x1c #define TW_CMD_PACKET 0x1d +#define TW_ATA_PASSTHRU 0x1e /* Asynchronous Event Notification (AEN) Codes */ #define TW_AEN_QUEUE_EMPTY 0x0000 @@ -137,7 +176,10 @@ #define TW_INIT_COMMAND_PACKET_SIZE 0x3 #define TW_POLL_MAX_RETRIES 20000 #define TW_MAX_SGL_LENGTH 62 -#define TW_Q_LENGTH 16 +#define TW_ATA_PASS_SGL_MAX 60 +#define TW_MAX_PASSTHRU_BYTES 4096 +#define TW_Q_LENGTH 256 +#define TW_MAX_BOUNCEBUF 16 #define TW_Q_START 0 #define TW_MAX_SLOT 32 #define TW_MAX_PCI_BUSES 255 @@ -149,6 +191,7 @@ #define TW_MAX_AEN_TRIES 100 #define TW_UNIT_ONLINE 1 #define TW_IN_INTR 1 +#define TW_MAX_SECTORS 128 #define TW_AEN_WAIT_TIME 1000 /* Macros */ @@ -222,6 +265,7 @@ unsigned short table_id; unsigned char parameter_id; unsigned char parameter_size_bytes; + unsigned char unit_index; unsigned char data[1]; } TW_Ioctl; @@ -258,14 +302,42 @@ int position; } TW_Info; -typedef enum TAG_TW_Cmd_State { - TW_S_INITIAL, /* Initial state */ - TW_S_STARTED, /* Id in use */ - TW_S_POSTED, /* Posted to the controller */ - TW_S_PENDING, /* Waiting to be posted in isr */ - TW_S_COMPLETED, /* Completed by isr */ - TW_S_FINISHED, /* I/O completely done */ -} TW_Cmd_State; +typedef int TW_Cmd_State; + +#define TW_S_INITIAL 0x1 /* Initial state */ +#define TW_S_STARTED 0x2 /* Id in use */ +#define TW_S_POSTED 0x4 /* Posted to the controller */ +#define TW_S_PENDING 0x8 /* Waiting to be posted in isr */ +#define TW_S_COMPLETED 0x10 /* Completed by isr */ +#define TW_S_FINISHED 0x20 /* I/O completely done */ +#define TW_START_MASK (TW_S_STARTED | TW_S_POSTED | TW_S_PENDING | TW_S_COMPLETED) + +/* Command header for ATA pass-thru */ +typedef struct TAG_TW_Passthru +{ + struct { + unsigned char opcode:5; + unsigned char sgloff:3; + } byte0; + unsigned char size; + unsigned char request_id; + struct { + unsigned char aport:4; + unsigned char host_id:4; + } byte3; + unsigned char status; + unsigned char flags; + unsigned short param; + unsigned short features; + unsigned short sector_count; + unsigned short sector_num; + unsigned short cylinder_lo; + unsigned short cylinder_hi; + unsigned char drive_head; + unsigned char command; + TW_SG_Entry sg_list[TW_ATA_PASS_SGL_MAX]; + unsigned char padding[12]; +} TW_Passthru; typedef struct TAG_TW_Device_Extension { TW_Registers registers; @@ -283,6 +355,7 @@ unsigned char free_queue[TW_Q_LENGTH]; unsigned char free_head; unsigned char free_tail; + unsigned char free_wrap; unsigned char pending_queue[TW_Q_LENGTH]; unsigned char pending_head; unsigned char pending_tail; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/53c7,8xx.c linux.21p1/drivers/scsi/53c7,8xx.c --- linux.vanilla/drivers/scsi/53c7,8xx.c Sun Mar 25 17:31:30 2001 +++ linux.21p1/drivers/scsi/53c7,8xx.c Sat Dec 29 03:07:50 2001 @@ -239,6 +239,7 @@ #include #include #include +#include #include #include #include @@ -1463,7 +1464,7 @@ command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO; pci_write_config_word(pdev, PCI_COMMAND, command); - if (io_port >= 0x10000000 && is_prep ) { + if (io_port >= 0x10000000 && (_machine == _MACH_prep)) { /* Mapping on PowerPC can't handle this! */ unsigned long new_io_port; new_io_port = (io_port & 0x00FFFFFF) | 0x01000000; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/drivers/scsi/sym53c8xx.c linux.21p1/drivers/scsi/sym53c8xx.c --- linux.vanilla/drivers/scsi/sym53c8xx.c Sat Dec 29 16:57:23 2001 +++ linux.21p1/drivers/scsi/sym53c8xx.c Sat Dec 29 03:17:07 2001 @@ -10125,14 +10125,13 @@ if (i >= MAX_START*2) i = 0; } - assert(k != -1); - if (k != 1) { + if (k != -1) { np->squeue[k] = np->squeue[i]; /* Idle task */ np->squeueput = k; /* Start queue pointer */ - cp->host_status = HS_ABORTED; - cp->scsi_status = S_ILLEGAL; - ncr_complete(np, cp); } + cp->host_status = HS_ABORTED; + cp->scsi_status = S_ILLEGAL; + ncr_complete(np, cp); } break; /* diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/nfs/read.c linux.21p1/fs/nfs/read.c --- linux.vanilla/fs/nfs/read.c Sun Mar 25 17:37:38 2001 +++ linux.21p1/fs/nfs/read.c Sat Dec 29 03:10:22 2001 @@ -420,7 +420,7 @@ { struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; struct inode *inode = data->inode; - int count = data->res.count; + unsigned int count = data->res.count; dprintk("NFS: %4d nfs_readpage_result, (status %d)\n", task->tk_pid, task->tk_status); @@ -431,10 +431,15 @@ struct page *page = req->wb_page; nfs_list_remove_request(req); - if (task->tk_status >= 0 && count >= 0) { + if (task->tk_status >= 0) { + char *p = page_address(page); + if (count < PAGE_CACHE_SIZE) { + memset(p + count, 0, PAGE_CACHE_SIZE - count); + count = 0; + } else + count -= PAGE_CACHE_SIZE; flush_dcache_page(page_address(page)); /* Is this correct? */ set_bit(PG_uptodate, &page->flags); - count -= PAGE_CACHE_SIZE; } else set_bit(PG_error, &page->flags); nfs_unlock_page(page); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/fs/proc/root.c linux.21p1/fs/proc/root.c --- linux.vanilla/fs/proc/root.c Sun Mar 25 17:30:58 2001 +++ linux.21p1/fs/proc/root.c Sat Dec 29 03:21:08 2001 @@ -454,7 +454,7 @@ de = (struct proc_dir_entry *) inode->u.generic_ip; if (!(page = (char*) __get_free_page(GFP_KERNEL))) - return NULL; + return ERR_PTR(-ENOMEM); if (de->readlink_proc) len = de->readlink_proc(de, page); diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/asm-alpha/pci.h linux.21p1/include/asm-alpha/pci.h --- linux.vanilla/include/asm-alpha/pci.h Sat Dec 29 16:57:24 2001 +++ linux.21p1/include/asm-alpha/pci.h Sat Dec 29 03:28:12 2001 @@ -3,7 +3,7 @@ #include #include - +#include /* * The following structure is used to manage multiple PCI busses. @@ -59,7 +59,7 @@ if (bus2hose[pdev->bus->number] == NULL) return -ENXIO; - return bus2hose[pdev->bus->number]->pci_host_index; + return bus2hose[pdev->bus->number]->pci_hose_index; } #endif /* __ALPHA_PCI_H */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/include/linux/sem.h linux.21p1/include/linux/sem.h --- linux.vanilla/include/linux/sem.h Sun Mar 25 17:31:03 2001 +++ linux.21p1/include/linux/sem.h Sat Dec 29 03:49:30 2001 @@ -65,11 +65,11 @@ #define SEMMNS (SEMMNI*SEMMSL) /* ? max # of semaphores in system */ #define SEMOPM 32 /* ~ 100 max num of ops per semop call */ #define SEMVMX 32767 /* semaphore maximum value */ +#define SEMAEM SEMVMX /* adjust on exit max value */ /* unused */ #define SEMUME SEMOPM /* max num of undo entries per process */ #define SEMMNU SEMMNS /* num of undo structures system wide */ -#define SEMAEM (SEMVMX >> 1) /* adjust on exit max value */ #define SEMMAP SEMMNS /* # of entries in semaphore map */ #define SEMUSZ 20 /* sizeof struct sem_undo */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/ipc/sem.c linux.21p1/ipc/sem.c --- linux.vanilla/ipc/sem.c Sun Mar 25 17:31:15 2001 +++ linux.21p1/ipc/sem.c Sat Dec 29 03:21:48 2001 @@ -229,7 +229,19 @@ curr->sempid = (curr->sempid << 16) | pid; curr->semval += sem_op; if (sop->sem_flg & SEM_UNDO) - un->semadj[sop->sem_num] -= sem_op; + { + int undo = un->semadj[sop->sem_num] - sem_op; + /* + * Exceeding the undo range is an error. + */ + if(undo < (-SEMAEM - 1) || undo > SEMAEM) + { + /* Don't undo the undo */ + sop->sem_flg &= ~SEM_UNDO; + goto out_of_range; + } + un->semadj[sop->sem_num] = undo; + } if (curr->semval < 0) goto would_block; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/mm/page_alloc.c linux.21p1/mm/page_alloc.c --- linux.vanilla/mm/page_alloc.c Sun Mar 25 17:37:41 2001 +++ linux.21p1/mm/page_alloc.c Sat Dec 29 03:11:56 2001 @@ -149,7 +149,8 @@ * local since we must deal with fragmentation too and we * can't rely on the nr_local_pages information. */ - if (current->nr_local_pages && !current->allocation_order) + if ((current->nr_local_pages && !current->allocation_order) || + in_interrupt()) goto back_local_freelist; page = mem_map + map_nr; diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla/mm/vmalloc.c linux.21p1/mm/vmalloc.c --- linux.vanilla/mm/vmalloc.c Sun Mar 25 17:31:02 2001 +++ linux.21p1/mm/vmalloc.c Sat Dec 29 03:06:17 2001 @@ -132,7 +132,6 @@ unsigned long end = address + size; dir = pgd_offset_k(address); - flush_cache_all(); while (address >= start && address < end) { pmd_t *pmd; pgd_t olddir = *dir; @@ -147,6 +146,7 @@ address = (address + PGDIR_SIZE) & PGDIR_MASK; dir++; } + flush_cache_all(); flush_tlb_all(); return 0; }