From f764aed274e3ac6333e454f3129a050b338a2ba8 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 23 Nov 2007 15:22:41 -0500 Subject: [PATCH] Linux 2.2.18pre18 o Fix off by one in net/ipv4/proc (Dave Miller) o Move the fpu emu patch that got away (Dave Miller) o K6 update for MTRR ability (Dave Jones) o Fix raid1/vm deadlock (Marcelo Tosatti) o Fix usb mouse userspace memory accesses (David Woodhouse) o Fix xpdsl if compiled in (typo) (Arjan van de Ven) o Rio fixes for modem handling. Fix a small (Patrick van de Lageweg) generic serial bug o IBMtr driver fixes for cable pulls, pcmcia (Burt Silverman, behaviour etc Mike Sullivan) o Tidy up /dev/microcode messages (Daniel Roesen) o Add arpfilter (Andi Kleen) o IDE floppy updates for clik support, cleanups (Paul Bristow) o Fix irongate handling on Alpha (Soohoon Lee) o Fix HZ=100 assumption in aha152x.c (Alan Cox) o Fix power management handling in i810 audio (Alan Cox) (From an ALSA fix by Godmar Back) o Put the NFS block default back to 4K (Trond Myklebust) o Fix misleading comment in printk code (Riley Williams) o Fix fbcon scroll back/paste bug (Herbert Xu) o Fix rtc_lock for ide-probe, and hd.c (Richard Johnson) o Backport of 2.4 PR_GET/SET_KEEPCAPS (Brian Brunswick) (from Chris Evans 2.4 code) o LRU list corruption fix (Andrea Arcangeli) o Initial gcc 2.96+ support for kernel building (H J Lu) | Not a recommended compiler for production kernels... o ALI silence clearing fix (Ching-Ling Lee) o Fix remaining old-style use of copy_strings (Solar Designer) o Better pci_resource_start macro for 2.2 (Jeff Garzik) o Fix nbd deadlock (Marcelo Tosatti) --- MAINTAINERS | 8 + Makefile | 2 +- arch/i386/kernel/i386_ksyms.c | 3 +- arch/i386/kernel/microcode.c | 8 +- arch/i386/kernel/setup.c | 3 +- arch/i386/lib/Makefile | 2 +- arch/s390/boot/ipleckd.S | 16 +- drivers/block/hd.c | 8 +- drivers/block/ide-floppy.c | 168 +- drivers/block/ide-probe.c | 5 + drivers/block/nbd.c | 2 + drivers/block/raid1.c | 4 +- drivers/char/generic_serial.c | 7 +- drivers/char/rio/linux_compat.h | 4 +- drivers/char/rio/rio_linux.c | 27 +- drivers/char/rio/rio_linux.h | 6 +- drivers/char/rio/rioboot.c | 2 +- drivers/char/rio/riocmd.c | 7 +- drivers/char/rio/rioinit.c | 2 +- drivers/char/rio/riotable.c | 2 + drivers/char/rio/riotty.c | 33 +- drivers/char/rtc.c | 12 +- drivers/net/ibmtr.c | 2317 ++++++++++----------- drivers/net/ibmtr.h | 25 +- drivers/net/xpds/xpds.c | 6 +- drivers/scsi/aha152x.c | 4 +- drivers/sound/i810_audio.c | 13 +- drivers/sound/trident.c | 48 +- drivers/usb/microtek.c | 2 +- drivers/usb/mousedev.c | 2 +- drivers/video/fbcon.c | 7 +- fs/binfmt_elf.c | 4 +- fs/binfmt_em86.c | 4 +- fs/binfmt_java.c | 8 +- fs/binfmt_misc.c | 4 +- fs/binfmt_script.c | 4 +- fs/buffer.c | 9 +- fs/exec.c | 2 + include/asm-alpha/core_irongate.h | 4 + include/{asm-i386 => asm-m68k}/math-emu.h | 0 include/linux/inetdevice.h | 4 + include/linux/kcomp.h | 5 +- include/linux/mc146818rtc.h | 2 + include/linux/nfs_fs.h | 2 +- include/linux/prctl.h | 3 + include/linux/sched.h | 6 +- include/linux/sysctl.h | 3 +- include/net/snmp.h | 1 + kernel/printk.c | 4 +- kernel/sys.c | 25 +- net/ipv4/arp.c | 27 +- net/ipv4/devinet.c | 5 +- net/ipv4/proc.c | 10 +- 53 files changed, 1464 insertions(+), 1427 deletions(-) rename include/{asm-i386 => asm-m68k}/math-emu.h (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 106bf5f57e6b..3bfccb96a219 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -812,6 +812,14 @@ L: rtl@rtlinux.org W: www.rtlinux.org S: Maintained +S390 +P: Martin Schwidefsky +M: schwidefsky@de.ibm.com +M: linux390@de.ibm.com +L: linux-390@vm.marist.edu +W: http://oss.software.ibm.com/developerworks/opensource/linux390 +S: Supported + SBPCD CDROM DRIVER P: Eberhard Moenkeberg M: emoenke@gwdg.de diff --git a/Makefile b/Makefile index 4a983751226b..b1851f24f449 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 2 SUBLEVEL = 18 -EXTRAVERSION = pre17 +EXTRAVERSION = pre18 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 23fa07d021d1..7c7e113ccc54 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -42,7 +42,7 @@ EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(disable_irq_nosync); EXPORT_SYMBOL(kernel_thread); - +EXPORT_SYMBOL(rtc_lock); EXPORT_SYMBOL(init_mm); EXPORT_SYMBOL_NOVERS(__down_failed); @@ -121,4 +121,3 @@ EXPORT_SYMBOL(mca_is_adapter_used); EXPORT_SYMBOL(screen_info); #endif -EXPORT_SYMBOL(rtc_lock); diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index 62dd129406b1..f97a15d68adc 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -220,11 +220,15 @@ static void do_update_one(void *arg) found=1; rdmsr(0x8B, val[0], rev); - if (microcode[i].rev <= rev) { + if (microcode[i].rev < rev) { printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision" " %d (current=%d)\n", cpu_num, microcode[i].rev, rev); - } else { + } else if (microcode[i].rev == rev) { + printk(KERN_ERR + "microcode: CPU%d already up-to-date (revision %d)\n", + cpu_num, rev); + } else { int sum = 0; struct microcode *m = µcode[i]; unsigned int *sump = (unsigned int *)(m+1); diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 87b1117c7052..17fc5a7ec925 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -560,7 +560,8 @@ __initfunc(static int amd_model(struct cpuinfo_x86 *c)) } /* Set MTRR capability flag if appropriate */ - if((boot_cpu_data.x86_model == 9) || + if((boot_cpu_data.x86_model == 13) || + (boot_cpu_data.x86_model == 9) || ((boot_cpu_data.x86_model == 8) && (boot_cpu_data.x86_mask >= 8))) c->x86_capability |= X86_FEATURE_MTRR; diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile index c2cb3e5a6b9d..18abc7db0d9b 100644 --- a/arch/i386/lib/Makefile +++ b/arch/i386/lib/Makefile @@ -3,7 +3,7 @@ # .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o + $(CC) -D__ASSEMBLY__ $(AFLAGS) -c $< -o $*.o L_TARGET = lib.a L_OBJS = checksum.o old-checksum.o semaphore.o delay.o \ diff --git a/arch/s390/boot/ipleckd.S b/arch/s390/boot/ipleckd.S index eac32a73d5b3..c422ebbf7019 100644 --- a/arch/s390/boot/ipleckd.S +++ b/arch/s390/boot/ipleckd.S @@ -44,10 +44,10 @@ _start: .globl _start stsch .Lrdcdata oi .Lrdcdata+5,0x84 # enable ssch and multipath mode .Lecs: xi .Lrdcdata+27,0x01 # enable concurrent sense - msch .Lrdcdata + msch .Lrdcdata xi .Lprgn,6 # restore Wait and d/a bit in PCnew PSW l %r2,.Lparm - mvc 0x0(8,%r2),.Lnull # set parmarea to null + mvc 0x0(8,%r2),.Lnull # set parmarea to null lctl %c6,%c6,.Lc6 # enable all interrupts .Lrdc: # read device characteristics la %r6,.Lrdcccw @@ -94,7 +94,7 @@ _start: .globl _start .Lzeroes: lr %r2,%r3 .L001: slr %r3,%r3 - icm %r3,3,.Lcountarea+6 # get blocksize + icm %r3,3,.Lcountarea+6 # get blocksize slr %r5,%r5 # no bytes to move .L008: mvcle %r2,%r4,0 # fill zeroes to storage jo .L008 # until block is filled @@ -140,10 +140,10 @@ _start: .globl _start lr %r15,%r4 # save number or blocks slr %r7,%r7 icm %r7,3,.Lrdcdata+14 # load heads to r7 - lhi %r6,9 - clc .Lrdcdata+3(2),.L9343 + lhi %r6,9 + clc .Lrdcdata+3(2),.L9345 je .L011 - lhi %r6,10 + lhi %r6,10 clc .Lrdcdata+3(2),.L3380 je .L011 lhi %r6,12 @@ -244,8 +244,8 @@ _start: .globl _start .long 0x00008000 # they are loaded with a LM .L3390: .word 0x3390 -.L9343: - .word 0x934a +.L9345: + .word 0x9345 .L3380: .word 0x3380 .Lnull: diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 203c2d609acb..4daaf76e69ab 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c @@ -21,6 +21,8 @@ * Removed 99% of above. Use Mark's ide driver for those options. * This is now a lightweight ST-506 driver. (Paul Gortmaker) * + * 17-OCT-2000 rjohnson@analogic.com Added spin-lock for reading + * CMOS chip. */ /* Uncomment the following if you want verbose error reports. */ @@ -48,7 +50,7 @@ #define MAJOR_NR HD_MAJOR #include - +extern spinlock_t rtc_lock; static int revalidate_hddisk(kdev_t, int); #define HD_DELAY 0 @@ -701,6 +703,7 @@ static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void hd_geninit(struct gendisk *ignored) { int drive; + unsigned long flags; #ifdef __i386__ if (!NR_HD) { @@ -743,13 +746,14 @@ static void hd_geninit(struct gendisk *ignored) */ - + spin_lock_irqsave(&rtc_lock, flags); if ((cmos_disks = CMOS_READ(0x12)) & 0xf0) { if (cmos_disks & 0x0f) NR_HD = 2; else NR_HD = 1; } + spin_unlock_irqrestore(&rtc_lock, flags); } #endif /* __i386__ */ for (drive=0 ; drive < NR_HD ; drive++) { diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c index 891211d684a1..e64932fe6d6a 100644 --- a/drivers/block/ide-floppy.c +++ b/drivers/block/ide-floppy.c @@ -1,7 +1,8 @@ /* - * linux/drivers/block/ide-floppy.c Version 0.9 Jul 4, 1999 + * linux/drivers/block/ide-floppy.c Version 0.94 Oct 27, 2000 * * Copyright (C) 1996 - 1999 Gadi Oxman + * Copyright (C) 2000 Paul Bristow */ /* @@ -10,6 +11,12 @@ * The driver currently doesn't have any fancy features, just the bare * minimum read/write support. * + * This driver supports the following IDE floppy drives: + * + * LS-120 SuperDisk + * Iomega Zip 100/250 + * Iomega PC Card Clik!/PocketZip + * * Many thanks to Lode Leroy , who tested so many * ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive. * @@ -29,9 +36,17 @@ * Ver 0.9 Jul 4 99 Fix a bug which might have caused the number of * bytes requested on each interrupt to be zero. * Thanks to for pointing this out. + * Ver 0.91 Dec 11 99 Added IOMEGA Clik! drive support by + * + * Ver 0.92 Oct 22 00 Paul Bristow became official maintainer for this + * driver. Included Powerbook internal zip kludge. + * Ver 0.93 Oct 24 00 Fixed bugs for Clik! drive + * no disk on insert and disk change now works + * Ver 0.94 Oct 27 00 Tidied up to remove strstr(Clik) everywhere + * */ -#define IDEFLOPPY_VERSION "0.9" +#define IDEFLOPPY_VERSION "0.94" #include #include @@ -60,12 +75,14 @@ */ #include "ide.h" + /* * The following are used to debug the driver. */ -#define IDEFLOPPY_DEBUG_LOG 0 #define IDEFLOPPY_DEBUG_INFO 0 #define IDEFLOPPY_DEBUG_BUGS 1 +/* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */ +#define IDEFLOPPY_DEBUG( fmt, args... ) /* * Some drives require a longer irq timeout. @@ -185,6 +202,7 @@ typedef struct { u8 reserved30[2]; } idefloppy_flexible_disk_page_t; + /* * Format capacity */ @@ -250,6 +268,8 @@ typedef struct { #define IDEFLOPPY_DRQ_INTERRUPT 0 /* DRQ interrupt device */ #define IDEFLOPPY_MEDIA_CHANGED 1 /* Media may have changed */ #define IDEFLOPPY_USE_READ12 2 /* Use READ12/WRITE12 or READ10/WRITE10 */ +#define IDEFLOPPY_CLIK_DRIVE 3 /* Avoid commands not supported in Clik drive */ +#define IDEFLOPPY_POWERBOOK_ZIP 4 /* Kludge for Apple Powerbook Zip drive */ /* * ATAPI floppy drive packet commands @@ -625,9 +645,7 @@ static void idefloppy_end_request (byte uptodate, ide_hwgroup_t *hwgroup) struct request *rq = hwgroup->rq; int error; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_end_request\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "Reached idefloppy_end_request\n"); switch (uptodate) { case 0: error = IDEFLOPPY_ERROR_GENERAL; break; @@ -750,21 +768,19 @@ static void idefloppy_analyze_error (ide_drive_t *drive,idefloppy_request_sense_ idefloppy_floppy_t *floppy = drive->driver_data; floppy->sense_key = result->sense_key; floppy->asc = result->asc; floppy->ascq = result->ascq; -#if IDEFLOPPY_DEBUG_LOG - if (floppy->failed_pc) - printk (KERN_INFO "ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq); - else - printk (KERN_INFO "ide-floppy: sense key = %x, asc = %x, ascq = %x\n",result->sense_key,result->asc,result->ascq); -#endif /* IDEFLOPPY_DEBUG_LOG */ + if (floppy->failed_pc) { + IDEFLOPPY_DEBUG("ide-floppy: pc = %x, sense key = %x, asc = %x, ascq = %x\n",floppy->failed_pc->c[0],result->sense_key,result->asc,result->ascq); + } + else { + IDEFLOPPY_DEBUG("ide-floppy: sense key = %x, asc = %x, ascq = %x\n",result->sense_key,result->asc,result->ascq); + } } static void idefloppy_request_sense_callback (ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_request_sense_callback\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_request_sense_callback\n"); if (!floppy->pc->error) { idefloppy_analyze_error (drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer); idefloppy_end_request (1,HWGROUP (drive)); @@ -781,9 +797,7 @@ static void idefloppy_pc_callback (ide_drive_t *drive) { idefloppy_floppy_t *floppy = drive->driver_data; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_callback\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_pc_callback\n"); idefloppy_end_request (floppy->pc->error ? 0:1, HWGROUP(drive)); } @@ -844,9 +858,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) struct request *rq = pc->rq; unsigned int temp; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_pc_intr interrupt handler\n"); #ifdef CONFIG_BLK_DEV_IDEDMA if (test_bit (PC_DMA_IN_PROGRESS, &pc->flags)) { @@ -856,26 +868,20 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) pc->actually_transferred=pc->request_transfer; idefloppy_update_buffers (drive, pc); } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: DMA finished\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: DMA finished\n"); } #endif /* CONFIG_BLK_DEV_IDEDMA */ status.all = GET_STAT(); /* Clear the interrupt */ if (!status.b.drq) { /* No more interrupts */ -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "Packet command completed, %d bytes transferred\n", pc->actually_transferred); clear_bit (PC_DMA_IN_PROGRESS, &pc->flags); ide__sti(); /* local CPU only */ if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */ -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: %s: I/O error\n",drive->name); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: %s: I/O error\n",drive->name); rq->errors++; if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) { printk (KERN_ERR "ide-floppy: I/O error in request sense command\n"); @@ -919,9 +925,7 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive) ide_set_handler (drive,&idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD,NULL); return ide_started; } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_NOTICE "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: The floppy wants to send us more data than expected - allowing transfer\n"); } } if (test_bit (PC_WRITING, &pc->flags)) { @@ -987,7 +991,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p * a legitimate error code was received. */ if (!test_bit (PC_ABORT, &pc->flags)) { - printk (KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", + IDEFLOPPY_DEBUG( "ide-floppy: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n", drive->name, pc->c[0], floppy->sense_key, floppy->asc, floppy->ascq); pc->error = IDEFLOPPY_ERROR_GENERAL; /* Giving up */ } @@ -995,9 +999,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p pc->callback(drive); return ide_stopped; } -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Retry number - %d\n",pc->retries); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "Retry number - %d\n",pc->retries); pc->retries++; pc->actually_transferred=0; /* We haven't transferred any data yet */ @@ -1037,9 +1039,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p static void idefloppy_rw_callback (ide_drive_t *drive) { -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: Reached idefloppy_rw_callback\n"); idefloppy_end_request(1, HWGROUP(drive)); return; @@ -1047,9 +1047,7 @@ static void idefloppy_rw_callback (ide_drive_t *drive) static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent) { -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "ide-floppy: creating prevent removal command, prevent = %d\n", prevent); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "ide-floppy: creating prevent removal command, prevent = %d\n", prevent); idefloppy_init_pc (pc); pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD; @@ -1109,10 +1107,8 @@ static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t int block = sector / floppy->bs_factor; int blocks = rq->nr_sectors / floppy->bs_factor; -#if IDEFLOPPY_DEBUG_LOG - printk ("create_rw1%d_cmd: block == %d, blocks == %d\n", + IDEFLOPPY_DEBUG( "create_rw1%d_cmd: block == %d, blocks == %d\n", 2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags), block, blocks); -#endif /* IDEFLOPPY_DEBUG_LOG */ idefloppy_init_pc (pc); if (test_bit (IDEFLOPPY_USE_READ12, &floppy->flags)) { @@ -1142,10 +1138,8 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t *pc; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); - printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors); + IDEFLOPPY_DEBUG( "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors); if (rq->errors >= ERROR_MAX) { if (floppy->failed_pc != NULL) @@ -1238,6 +1232,7 @@ static int idefloppy_get_flexible_disk_page (ide_drive_t *drive) return 0; } + /* * Determine if a media is present in the floppy drive, and if so, * its LBA capacity. @@ -1266,7 +1261,12 @@ static int idefloppy_get_capacity (ide_drive_t *drive) for (i = 0; i < descriptors; i++, descriptor++) { blocks = descriptor->blocks = ntohl (descriptor->blocks); length = descriptor->length = ntohs (descriptor->length); - if (!i && descriptor->dc == CAPACITY_CURRENT) { + if (!i) { + switch (descriptor->dc) { + case CAPACITY_UNFORMATTED: /* Clik! drive returns this instead of CAPACITY_CURRENT */ + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) + break; /* If it is not a clik drive, break out (maintains previous driver behaviour) */ + case CAPACITY_CURRENT: /* Normal Zip/LS-120 disks */ if (memcmp (descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t))) printk (KERN_INFO "%s: %dkB, %d blocks, %d sector size\n", drive->name, blocks * length / 1024, blocks, length); floppy->capacity = *descriptor; @@ -1279,32 +1279,50 @@ static int idefloppy_get_capacity (ide_drive_t *drive) printk (KERN_NOTICE "%s: warning: non 512 bytes block size not fully supported\n", drive->name); rc = 0; } + break; + case CAPACITY_NO_CARTRIDGE: + /* This is a KERN_ERR so it appears on screen for the user to see */ + printk (KERN_ERR "%s: No disk in drive\n", drive->name); + break; + case CAPACITY_INVALID: + printk (KERN_ERR "%s: Invalid capacity for disk in drive\n", drive->name); + break; } -#if IDEFLOPPY_DEBUG_INFO - if (!i) printk (KERN_INFO "Descriptor 0 Code: %d\n", descriptor->dc); - printk (KERN_INFO "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length); -#endif /* IDEFLOPPY_DEBUG_INFO */ } + if (!i) { + IDEFLOPPY_DEBUG( "Descriptor 0 Code: %d\n", descriptor->dc); + } + IDEFLOPPY_DEBUG( "Descriptor %d: %dkB, %d blocks, %d sector size\n", i, blocks * length / 1024, blocks, length); + } + + /* Clik! disk does not support get_flexible_disk_page */ + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) (void) idefloppy_get_flexible_disk_page (drive); + drive->part[0].nr_sects = floppy->blocks * floppy->bs_factor; return rc; } + /* * Our special ide-floppy ioctl's. * - * Currently there aren't any ioctl's. + * Supports eject command */ static int idefloppy_ioctl (ide_drive_t *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { idefloppy_pc_t pc; + idefloppy_floppy_t *floppy = drive->driver_data; if (cmd == CDROMEJECT) { if (drive->usage > 1) return -EBUSY; + /* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */ + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd (&pc, 0); (void) idefloppy_queue_pc_tail (drive, &pc); + } idefloppy_create_start_stop_cmd (&pc, 2); (void) idefloppy_queue_pc_tail (drive, &pc); return 0; @@ -1320,20 +1338,24 @@ static int idefloppy_open (struct inode *inode, struct file *filp, ide_drive_t * idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_pc_t pc; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_open\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "Reached idefloppy_open\n"); MOD_INC_USE_COUNT; if (drive->usage == 1) { + IDEFLOPPY_DEBUG( "Testing if unit is ready...\n"); idefloppy_create_test_unit_ready_cmd(&pc); if (idefloppy_queue_pc_tail(drive, &pc)) { + IDEFLOPPY_DEBUG( "Not ready, issuing start command\n"); idefloppy_create_start_stop_cmd (&pc, 1); (void) idefloppy_queue_pc_tail (drive, &pc); + } else + { + IDEFLOPPY_DEBUG( "Yes unit is ready\n"); } if (idefloppy_get_capacity (drive)) { drive->usage--; MOD_DEC_USE_COUNT; + IDEFLOPPY_DEBUG( "I/O Error Getting Capacity\n"); return -EIO; } if (floppy->wp && (filp->f_mode & 2)) { @@ -1342,8 +1364,11 @@ static int idefloppy_open (struct inode *inode, struct file *filp, ide_drive_t * return -EROFS; } set_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags); + /* IOMEGA Clik! drives do not support lock/unlock commands - no room for mechanism */ + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd (&pc, 1); (void) idefloppy_queue_pc_tail (drive, &pc); + } check_disk_change(inode->i_rdev); } return 0; @@ -1352,16 +1377,18 @@ static int idefloppy_open (struct inode *inode, struct file *filp, ide_drive_t * static void idefloppy_release (struct inode *inode, struct file *filp, ide_drive_t *drive) { idefloppy_pc_t pc; + idefloppy_floppy_t *floppy = drive->driver_data; -#if IDEFLOPPY_DEBUG_LOG - printk (KERN_INFO "Reached idefloppy_release\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ + IDEFLOPPY_DEBUG( "Reached idefloppy_release\n"); if (!drive->usage) { invalidate_buffers (inode->i_rdev); + /* IOMEGA Clik! drives do not support lock/unlock commands */ + if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) { idefloppy_create_prevent_cmd (&pc, 0); (void) idefloppy_queue_pc_tail (drive, &pc); } + } MOD_DEC_USE_COUNT; } @@ -1549,6 +1576,17 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) for (i = 0; i < 1 << PARTN_BITS; i++) max_sectors[major][minor + i] = 64; } + /* + * Guess what? The IOMEGA Clik! drive also needs the + * above fix. It makes nasty clicking noises without + * it, so please don't remove this. + */ + if (strcmp(drive->id->model, "IOMEGA Clik! 40 CZ ATAPI") == 0) + { + for (i = 0; i < 1 << PARTN_BITS; i++) + max_sectors[major][minor + i] = 64; + set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags); + } (void) idefloppy_get_capacity (drive); idefloppy_add_settings(drive); @@ -1578,6 +1616,7 @@ static ide_proc_entry_t idefloppy_proc[] = { #endif /* CONFIG_PROC_FS */ + /* * IDE subdriver functions, registered with ide.c */ @@ -1609,6 +1648,7 @@ static ide_module_t idefloppy_module = { NULL }; + /* * idefloppy_init will register the driver for each floppy. */ @@ -1641,12 +1681,16 @@ int idefloppy_init (void) return 0; } + #ifdef MODULE +/* Initialisation code for loading the driver as a modules */ int init_module (void) { return idefloppy_init (); } + +/* Cleanup code for removing the driver module */ void cleanup_module (void) { ide_drive_t *drive; diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c index b1dee93e935c..2f3876b30c95 100644 --- a/drivers/block/ide-probe.c +++ b/drivers/block/ide-probe.c @@ -18,6 +18,8 @@ * by Andrea Arcangeli * Version 1.03 fix for (hwif->chipset == ide_4drives) * Version 1.04 fixed buggy treatments of known flash memory cards + * 17-OCT-2000 rjohnson@analogic.com Added spin-locks for reading CMOS + * chip. */ #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -386,6 +388,7 @@ static inline byte probe_for_drive (ide_drive_t *drive) static void probe_cmos_for_drives (ide_hwif_t *hwif) { #ifdef __i386__ + unsigned long flags; extern struct drive_info_struct drive_info; byte cmos_disks, *BIOS = (byte *) &drive_info; int unit; @@ -394,8 +397,10 @@ static void probe_cmos_for_drives (ide_hwif_t *hwif) if (hwif->chipset == ide_pdc4030 && hwif->channel != 0) return; #endif /* CONFIG_BLK_DEV_PDC4030 */ + spin_lock_irqsave(&rtc_lock, flags); outb_p(0x12,0x70); /* specify CMOS address 0x12 */ cmos_disks = inb_p(0x71); /* read the data from 0x12 */ + spin_unlock_irqrestore(&rtc_lock, flags); /* Extract drive geometry from CMOS+BIOS if not already setup */ for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 77f33458c217..f07aa8251226 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -105,6 +106,7 @@ static int nbd_xmit(int send, struct socket *sock, char *buf, int size) do { + sock->sk->allocation = GFP_BUFFER; iov.iov_base = buf; iov.iov_len = size; msg.msg_name = NULL; diff --git a/drivers/block/raid1.c b/drivers/block/raid1.c index 28e7b953a87e..330289dcb0ac 100644 --- a/drivers/block/raid1.c +++ b/drivers/block/raid1.c @@ -209,7 +209,7 @@ raid1_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh) PRINTK(("raid1_make_request().\n")); while (!( /* FIXME: now we are rather fault tolerant than nice */ - r1_bh = kmalloc (sizeof (struct raid1_bh), GFP_KERNEL) + r1_bh = kmalloc (sizeof (struct raid1_bh), GFP_BUFFER) ) ) { printk ("raid1_make_request(#1): out of memory\n"); @@ -301,7 +301,7 @@ raid1_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh) * of this function to grok the difference ;) */ while (!( /* FIXME: now we are rather fault tolerant than nice */ - mirror_bh[i] = kmalloc (sizeof (struct buffer_head), GFP_KERNEL) + mirror_bh[i] = kmalloc (sizeof (struct buffer_head), GFP_BUFFER) ) ) { printk ("raid1_make_request(#2): out of memory\n"); diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 6c19753714ba..3df261a6a028 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c @@ -367,7 +367,7 @@ static int gs_wait_tx_flushed (void * ptr, int timeout) struct gs_port *port = ptr; long end_jiffies; int jiffies_to_transmit, charsleft = 0, rv = 0; - int to, rcib; + int rcib; func_enter(); @@ -391,6 +391,7 @@ static int gs_wait_tx_flushed (void * ptr, int timeout) return rv; } /* stop trying: now + twice the time it would normally take + seconds */ + if (timeout == 0) timeout = MAX_SCHEDULE_TIMEOUT; end_jiffies = jiffies; if (timeout != MAX_SCHEDULE_TIMEOUT) end_jiffies += port->baud?(2 * rcib * 10 * HZ / port->baud):0; @@ -399,11 +400,9 @@ static int gs_wait_tx_flushed (void * ptr, int timeout) gs_dprintk (GS_DEBUG_FLUSH, "now=%lx, end=%lx (%ld).\n", jiffies, end_jiffies, end_jiffies-jiffies); - to = 100; /* the expression is actually jiffies < end_jiffies, but that won't work around the wraparound. Tricky eh? */ - while (to-- && - (charsleft = gs_real_chars_in_buffer (port->tty)) && + while ((charsleft = gs_real_chars_in_buffer (port->tty)) && time_after (end_jiffies, jiffies)) { /* Units check: chars * (bits/char) * (jiffies /sec) / (bits/sec) = jiffies! diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h index ca1649f1efb3..beb075780fa5 100644 --- a/drivers/char/rio/linux_compat.h +++ b/drivers/char/rio/linux_compat.h @@ -16,11 +16,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + #define disable(oldspl) save_flags (oldspl) #define restore(oldspl) restore_flags (oldspl) -#define sysbrk(x) kmalloc ((x), GFP_KERNEL) +#define sysbrk(x) kmalloc ((x),in_interrupt()? GFP_ATOMIC : GFP_KERNEL) #define sysfree(p,size) kfree ((p)) #define WBYTE(p,v) writeb(v, &p) diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 5c48e6d1aee7..9ebb920da21f 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -386,8 +386,8 @@ int rio_minor (kdev_t device) int rio_ismodem (kdev_t device) { - return (MAJOR (device) != RIO_NORMAL_MAJOR0) && - (MAJOR (device) != RIO_NORMAL_MAJOR1); + return (MAJOR (device) == RIO_NORMAL_MAJOR0) || + (MAJOR (device) == RIO_NORMAL_MAJOR1); } @@ -731,20 +731,22 @@ static int rio_fw_ioctl (struct inode *inode, struct file *filp, static int rio_ioctl (struct tty_struct * tty, struct file * filp, unsigned int cmd, unsigned long arg) { -#if 0 int rc; - struct rio_port *port = tty->driver_data; + struct Port *PortP; int ival; - /* func_enter2(); */ + func_enter(); + PortP = (struct Port *)tty->driver_data; rc = 0; switch (cmd) { +#if 0 case TIOCGSOFTCAR: rc = Put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), (unsigned int *) arg); break; +#endif case TIOCSSOFTCAR: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(int))) == 0) { @@ -757,13 +759,14 @@ static int rio_ioctl (struct tty_struct * tty, struct file * filp, case TIOCGSERIAL: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct))) == 0) - gs_getserial(&port->gs, (struct serial_struct *) arg); + gs_getserial(&PortP->gs, (struct serial_struct *) arg); break; case TIOCSSERIAL: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(struct serial_struct))) == 0) - rc = gs_setserial(&port->gs, (struct serial_struct *) arg); + rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg); break; +#if 0 case TIOCMGET: if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int))) == 0) { @@ -795,17 +798,13 @@ static int rio_ioctl (struct tty_struct * tty, struct file * filp, ((ival & TIOCM_RTS) ? 1 : 0)); } break; - +#endif default: rc = -ENOIOCTLCMD; break; } - /* func_exit(); */ + func_exit(); return rc; -#else - return -ENOIOCTLCMD; -#endif - } @@ -1276,6 +1275,7 @@ int rio_init(void) hp->Type = RIO_PCI; hp->Copy = rio_pcicopy; hp->Mode = RIO_PCI_BOOT_FROM_RAM; + hp->HostLock = SPIN_LOCK_UNLOCKED; rio_dprintk (RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec); rio_dprintk (RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode); @@ -1331,6 +1331,7 @@ int rio_init(void) * Moreover, the ISA card will work with the * special PCI copy anyway. -- REW */ hp->Mode = 0; + hp->HostLock = SPIN_LOCK_UNLOCKED; vpdp = get_VPD_PROM (hp); rio_dprintk (RIO_DEBUG_PROBE, "Got VPD ROM\n"); diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h index 4242197e5e22..d0605f913f3c 100644 --- a/drivers/char/rio/rio_linux.h +++ b/drivers/char/rio/rio_linux.h @@ -94,22 +94,22 @@ void rio_inc_mod_count (void); recompile.... */ #if 1 #define rio_spin_lock_irqsave(sem, flags) do { \ + spin_lock_irqsave(sem, flags);\ rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlockirqsave: %p %s:%d\n", \ sem, __FILE__, __LINE__);\ - spin_lock_irqsave(sem, flags);\ } while (0) #define rio_spin_unlock_irqrestore(sem, flags) do { \ rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlockirqrestore: %p %s:%d\n",\ sem, __FILE__, __LINE__);\ - spin_unlock_irqrestore(sem, flags);\ + spin_unlock_irqrestore(sem, flags);\ } while (0) #define rio_spin_lock(sem) do { \ + spin_lock(sem);\ rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlock: %p %s:%d\n",\ sem, __FILE__, __LINE__);\ - spin_lock(sem);\ } while (0) #define rio_spin_unlock(sem) do { \ diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c index d5ab5ba02f6c..760dca26c05f 100644 --- a/drivers/char/rio/rioboot.c +++ b/drivers/char/rio/rioboot.c @@ -38,12 +38,12 @@ static char *_rioboot_c_sccs_ = "@(#)rioboot.c 1.3"; #include #include #include +#include #include #include #include #include - #include #include diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index 3a330a07c51e..b96865694d2a 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c @@ -38,6 +38,9 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2"; #include #include #include +#include +#include +#include #include #include #include @@ -80,7 +83,6 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2"; #include "control.h" #include "cirrus.h" - static struct IdentifyRta IdRta; static struct KillNeighbour KillUnit; @@ -622,7 +624,8 @@ RIOGetCmdBlk() struct CmdBlk *CmdBlkP; CmdBlkP = (struct CmdBlk *)sysbrk(sizeof(struct CmdBlk)); - bzero(CmdBlkP, sizeof(struct CmdBlk)); + if (CmdBlkP) + bzero(CmdBlkP, sizeof(struct CmdBlk)); return CmdBlkP; } diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c index cbefdac2d989..ed0b8040ba17 100644 --- a/drivers/char/rio/rioinit.c +++ b/drivers/char/rio/rioinit.c @@ -1446,7 +1446,7 @@ struct rio_info * p; } RIODefaultName(p, HostP, rup); } - HostP->UnixRups[rup].RupLock = -1; + HostP->UnixRups[rup].RupLock = SPIN_LOCK_UNLOCKED; } } } diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c index 2b82c25ad457..673c62aab782 100644 --- a/drivers/char/rio/riotable.c +++ b/drivers/char/rio/riotable.c @@ -37,6 +37,8 @@ static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2"; #include #include #include +#include + #include #include #include diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c index c9134e3fc84b..087b1b8a91a9 100644 --- a/drivers/char/rio/riotty.c +++ b/drivers/char/rio/riotty.c @@ -451,8 +451,11 @@ bombout: PortP->gs.tty->termios->c_state |= WOPEN; */ PortP->State |= RIO_WOPEN; + rio_spin_unlock_irqrestore(&PortP->portSem, flags); + if (RIODelay (&PortP, HUNDRED_MS) == RIO_FAIL) #if 0 if ( sleep((caddr_t)&tp->tm.c_canqo, TTIPRI|PCATCH)) +#endif { /* ** ACTION: verify that this is a good thing @@ -470,7 +473,6 @@ bombout: func_exit (); return -EINTR; } -#endif } PortP->State &= ~RIO_WOPEN; } @@ -526,8 +528,10 @@ riotclose(void *ptr) #endif struct Port *PortP =ptr; /* pointer to the port structure */ int deleted = 0; - int try = 25; - int repeat_this = 0xff; + int try = -1; /* Disable the timeouts by setting them to -1 */ + int repeat_this = -1; /* Congrats to those having 15 years of + uptime! (You get to break the driver.) */ + long end_time; struct tty_struct * tty; unsigned long flags; int Modem; @@ -540,6 +544,12 @@ riotclose(void *ptr) /* tp = PortP->TtyP;*/ /* Get tty */ tty = PortP->gs.tty; rio_dprintk (RIO_DEBUG_TTY, "TTY is at address 0x%x\n",(int)tty); + + if (PortP->gs.closing_wait) + end_time = jiffies + PortP->gs.closing_wait; + else + end_time = jiffies + MAX_SCHEDULE_TIMEOUT; + Modem = rio_ismodem(tty->device); #if 0 /* What F.CKING cache? Even then, a higly idle multiprocessor, @@ -572,7 +582,8 @@ riotclose(void *ptr) ** clear the open bits for this device */ PortP->State &= (Modem ? ~RIO_MOPEN : ~RIO_LOPEN); - + PortP->State &= ~RIO_CARR_ON; + PortP->ModemState &= ~MSVR1_CD; /* ** If the device was open as both a Modem and a tty line ** then we need to wimp out here, as the port has not really @@ -604,7 +615,7 @@ riotclose(void *ptr) */ rio_dprintk (RIO_DEBUG_TTY, "Timeout 1 starts\n"); -#if 0 + if (!deleted) while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted && (PortP->TxBufferIn != PortP->TxBufferOut) ) { @@ -625,7 +636,7 @@ riotclose(void *ptr) } rio_spin_lock_irqsave(&PortP->portSem, flags); } -#endif + PortP->TxBufferIn = PortP->TxBufferOut = 0; repeat_this = 0xff; @@ -659,9 +670,9 @@ riotclose(void *ptr) } if (!deleted) - while (try && (PortP->PortState & PORT_ISOPEN)) { + while (PortP->PortState & PORT_ISOPEN) { try--; - if (try == 0) { + if (time_after (jiffies, end_time)) { rio_dprintk (RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n" ); RIOPreemptiveCmd(p, PortP,FCLOSE); break; @@ -673,7 +684,11 @@ riotclose(void *ptr) RIOClearUp( PortP ); goto close_end; } - RIODelay_ni(PortP, HUNDRED_MS); + if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { + rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n"); + RIOPreemptiveCmd(p, PortP,FCLOSE); + break; + } } rio_spin_lock_irqsave(&PortP->portSem, flags); rio_dprintk (RIO_DEBUG_TTY, "Close: try was %d on completion\n", try ); diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 9b14e6af65b5..2b38762b090e 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -42,10 +42,9 @@ /* * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with - * interrupts disabled. Due to the index-port/data-port (0x70/0x71) - * design of the RTC, we don't want two different things trying to - * get to it at once. (e.g. the periodic 11 min sync from time.c vs. - * this driver.) + * the rtc_lock held. Due to the index-port/data-port (0x70/0x71) design + * of the RTC, we don't want two different things trying to get to it at + * once. (e.g. the periodic 11 min sync from time.c vs. this driver.) */ #include @@ -110,10 +109,7 @@ unsigned long rtc_irq_data = 0; /* our output to the world */ static unsigned long epoch = 1900; /* year corresponding to 0x00 */ -unsigned char days_in_mo[] = -{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -extern spinlock_t rtc_lock; +unsigned char days_in_mo[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /* * A very tiny interrupt handler. It runs with SA_INTERRUPT set, diff --git a/drivers/net/ibmtr.c b/drivers/net/ibmtr.c index 94a0b191832b..20b32995c412 100644 --- a/drivers/net/ibmtr.c +++ b/drivers/net/ibmtr.c @@ -83,11 +83,18 @@ * Changes by Jochen Friedrich to enable RFC1469 Option 2 multicasting * i.e. using functional address C0 00 00 04 00 00 to transmit and * receive multicast packets. - * + * * Changes by Mike Sullivan (based on original sram patch by Dave Grothe * to support windowing into on adapter shared ram. * i.e. Use LANAID to setup a PnP configuration with 16K RAM. Paging * will shift this 16K window over the entire available shared RAM. + * + * Changes by Burt Silverman to allow the computer to behave nicely when + * a cable is pulled or not in place, or a PCMCIA card is removed hot. It + * is important for the user to understand that unlike some other systems, + * the system doesn't try continuously to establish insertion; however, an + * ifconfig tr0 down,ifconfig tr0 up sequence should restore connectivity, + * when all hardware is good and in place. */ /* change the define of IBMTR_DEBUG_MESSAGES to a nonzero value @@ -107,15 +114,13 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */ #define NO_AUTODETECT 1 #undef NO_AUTODETECT -//#undef ENABLE_PAGING -#define ENABLE_PAGING 1 - +#undef ENABLE_PAGING +#define ENABLE_PAGING 1 #define FALSE 0 #define TRUE (!FALSE) -/* changes the output format of driver initialisation */ -#define TR_NEWFORMAT 1 +/* changes the output format of driver initialization */ #define TR_VERBOSE 0 /* some 95 OS send many non UI frame; this allow removing the warning */ @@ -123,11 +128,12 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */ /* version and credits */ static char *version = -"ibmtr.c: v1.3.57 8/ 7/94 Peter De Schrijver and Mark Swanson\n" -" v2.1.125 10/20/98 Paul Norton \n" -" v2.2.0 12/30/98 Joel Sloan \n" -" v2.2.1 02/08/00 Mike Sullivan \n"; - + "\nibmtr.c: v1.3.57 8/ 7/94 Peter De Schrijver and Mark Swanson\n" + " v2.1.125 10/20/98 Paul Norton \n" + " v2.2.0 12/30/98 Joel Sloan \n" + " v2.2.1 02/08/00 Mike Sullivan \n" + " v2.2.2 07/27/00 Burt Silverman \n"; + static char pcchannelid[] = { 0x05, 0x00, 0x04, 0x09, 0x04, 0x03, 0x04, 0x0f, @@ -171,63 +177,56 @@ static char mcchannelid[] = { #include "ibmtr.h" - #define DPRINTK(format, args...) printk("%s: " format, dev->name , ## args) #define DPRINTD(format, args...) DummyCall("%s: " format, dev->name , ## args) #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) -#if TR_NEWFORMAT /* this allows displaying full adapter information */ -const char *channel_def[] __initdata = { - "ISA", "MCA", "ISA P&P" +const char *channel_def[] __initdata = { + "ISA", "MCA", "ISA P&P" }; __initfunc(char *adapter_def(char type)) { - switch (type) - { - case 0xF : return "PC Adapter | PC Adapter II | Adapter/A"; - case 0xE : return "16/4 Adapter | 16/4 Adapter/A (long)"; - case 0xD : return "16/4 Adapter/A (short) | 16/4 ISA-16 Adapter"; - case 0xC : return "Auto 16/4 Adapter"; - default : return "adapter (unknown type)"; + switch (type) { + case 0xF: + return "PC Adapter | PC Adapter II | Adapter/A"; + case 0xE: + return "16/4 Adapter | 16/4 Adapter/A (long)"; + case 0xD: + return "16/4 Adapter/A (short) | 16/4 ISA-16 Adapter"; + case 0xC: + return "Auto 16/4 Adapter"; + default: + return "adapter (unknown type)"; }; }; -#endif -#if !TR_NEWFORMAT -unsigned char ibmtr_debug_trace=1; /* Patch or otherwise alter to - control tokenring tracing. */ -#else -unsigned char ibmtr_debug_trace=0; -#endif -#define TRC_INIT 0x01 /* Trace initialization & PROBEs */ -#define TRC_INITV 0x02 /* verbose init trace points */ - -int ibmtr_probe(struct device *dev); -static int ibmtr_probe1(struct device *dev, int ioaddr); -static unsigned char get_sram_size(struct tok_info *adapt_info); -#ifdef PCMCIA -extern unsigned char pcmcia_reality_check(unsigned char gss); -#endif -static int tok_init_card(struct device *dev); -void tok_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static int trdev_init(struct device *dev); +#define TRC_INIT 0x01 /* Trace initialization & PROBEs */ +#define TRC_INITV 0x02 /* verbose init trace points */ +unsigned char ibmtr_debug_trace = 0; + +int ibmtr_probe(struct device *dev); +static int ibmtr_probe1(struct device *dev, int ioaddr); +static unsigned char get_sram_size(struct tok_info *adapt_info); +static int trdev_init(struct device *dev); +static int tok_init_card(struct device *dev); +static int tok_open(struct device *dev); +void tok_open_adapter(unsigned long dev_addr); +static void open_sap(unsigned char type, struct device *dev); +static void tok_set_multicast_list(struct device *dev); +static int tok_send_packet(struct sk_buff *skb, struct device *dev); +static int tok_close(struct device *dev); +void tok_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void initial_tok_int(struct device *dev); -static void open_sap(unsigned char type,struct device *dev); -void tok_open_adapter(unsigned long dev_addr); -static void tr_rx(struct device *dev); -static void tr_tx(struct device *dev); -static int tok_open(struct device *dev); -static int tok_close(struct device *dev); -static int tok_send_packet(struct sk_buff *skb, struct device *dev); -static struct net_device_stats * tok_get_stats(struct device *dev); -static void tok_set_multicast_list(struct device *dev); -void ibmtr_readlog(struct device *dev); -void ibmtr_reset_timer(struct timer_list *tmr, struct device *dev); -int ibmtr_change_mtu(struct device *dev, int mtu); +static void tr_tx(struct device *dev); +static void tr_rx(struct device *dev); +void ibmtr_reset_timer(struct timer_list *tmr, struct device *dev); +void ibmtr_readlog(struct device *dev); +static struct net_device_stats *tok_get_stats(struct device *dev); +int ibmtr_change_mtu(struct device *dev, int mtu); static unsigned int ibmtr_portlist[] __initdata = { 0xa20, 0xa24, 0 @@ -235,23 +234,23 @@ static unsigned int ibmtr_portlist[] __initdata = { static __u32 ibmtr_mem_base = 0xd0000; -__initfunc(static void PrtChanID(char *pcid, short stride) ) +__initfunc(static void PrtChanID(char *pcid, short stride)) { short i, j; - for (i=0, j=0; i<24; i++, j+=stride) + for (i = 0, j = 0; i < 24; i++, j += stride) printk("%1x", ((int) pcid[j]) & 0x0f); printk("\n"); } -__initfunc(static void HWPrtChanID (__u32 pcid, short stride)) +__initfunc(static void HWPrtChanID(__u32 pcid, short stride)) { short i, j; - for (i=0, j=0; i<24; i++, j+=stride) - printk("%1x", ((int)readb(pcid + j)) & 0x0f); + for (i = 0, j = 0; i < 24; i++, j += stride) + printk("%1x", ((int) readb(pcid + j)) & 0x0f); printk("\n"); } -/* +/**************************************************************************** * ibmtr_probe(): Routine specified in the network device structure * to probe for an IBM Token Ring Adapter. Routine outline: * I. Interrogate hardware to determine if an adapter exists @@ -262,258 +261,233 @@ __initfunc(static void HWPrtChanID (__u32 pcid, short stride)) * * We expect ibmtr_probe to be called once for each device entry * which references it. - */ - + ****************************************************************************/ + __initfunc(int ibmtr_probe(struct device *dev)) { - int i; - int base_addr = dev ? dev->base_addr : 0; - - if (base_addr > 0x1ff) - { - /* - * Check a single specified location. - */ - - if (ibmtr_probe1(dev, base_addr)) - { + int i; + int base_addr = dev ? dev->base_addr : 0; + + if (base_addr > 0x1ff) { + /* + * Check a single specified location. + */ + + if (ibmtr_probe1(dev, base_addr)) { #ifndef MODULE #ifndef PCMCIA - tr_freedev(dev); + tr_freedev(dev); #endif #endif - return -ENODEV; + return -ENODEV; } else - return 0; - } - else if (base_addr != 0) /* Don't probe at all. */ - return -ENXIO; + return 0; + } else if (base_addr != 0) /* Don't probe at all. */ + return -ENXIO; - for (i = 0; ibmtr_portlist[i]; i++) - { - int ioaddr = ibmtr_portlist[i]; + for (i = 0; ibmtr_portlist[i]; i++) { + int ioaddr = ibmtr_portlist[i]; if (check_region(ioaddr, IBMTR_IO_EXTENT)) - continue; - if (ibmtr_probe1(dev, ioaddr)) { + continue; + if (ibmtr_probe1(dev, ioaddr)) { #ifndef MODULE #ifndef PCMCIA - tr_freedev(dev); + tr_freedev(dev); #endif #endif } else return 0; - } + } - return -ENODEV; + return -ENODEV; } +/*****************************************************************************/ + __initfunc(static int ibmtr_probe1(struct device *dev, int PIOaddr)) { - unsigned char segment=0, intr=0, irq=0, i=0, j=0, cardpresent=NOTOK,temp=0; - __u32 t_mmio=0; - struct tok_info *ti=0; + + unsigned char segment = 0, intr = 0, irq = 0, i = 0, j = 0, cardpresent = NOTOK, temp = 0; + __u32 t_mmio = 0; + struct tok_info *ti = 0; __u32 cd_chanid; unsigned char *tchanid, ctemp; unsigned long timeout; #ifndef MODULE #ifndef PCMCIA - dev = init_trdev(dev,0); + dev = init_trdev(dev, 0); #endif #endif - /* Query the adapter PIO base port which will return - * indication of where MMIO was placed. We also have a - * coded interrupt number. + /* Query the adapter PIO base port which will return + * indication of where MMIO was placed. We also have a + * coded interrupt number. */ - - segment = inb(PIOaddr); - + segment = inb(PIOaddr); /* - * Out of range values so we'll assume non-existent IO device + * Out of range values so we'll assume non-existent IO device */ - if (segment < 0x40 || segment > 0xe0) - return -ENODEV; - + return -ENODEV; /* - * Compute the linear base address of the MMIO area - * as LINUX doesn't care about segments + * Compute the linear base address of the MMIO area + * as LINUX doesn't care about segments */ - - t_mmio=(((__u32)(segment & 0xfc) << 11) + 0x80000); - intr = segment & 0x03; /* low bits is coded interrupt # */ + t_mmio = (((__u32) (segment & 0xfc) << 11) + 0x80000); + intr = segment & 0x03; /* low bits is coded interrupt # */ if (ibmtr_debug_trace & TRC_INIT) - DPRINTK("PIOaddr: %4hx seg/intr: %2x mmio base: %08X intr: %d\n", - PIOaddr, (int)segment, t_mmio, (int)intr); + DPRINTK("PIOaddr: %4hx seg/intr: %2x mmio base: %08X intr: %d\n", PIOaddr, (int) segment, t_mmio, (int) intr); /* - * Now we will compare expected 'channelid' strings with - * what we is there to learn of ISA/MCA or not TR card + * Now we will compare expected 'channelid' strings with + * what we is there to learn of ISA/MCA or not TR card */ - - cd_chanid = (CHANNEL_ID + t_mmio); /* for efficiency */ - tchanid=pcchannelid; - cardpresent=TR_ISA; /* try ISA */ - +#ifdef PCMCIA + ti = dev->priv; /*BMS moved up here */ + t_mmio = ti->mmio; /*BMS to get virtual address */ + irq = ti->irq; /*BMS to display the irq! */ +#endif + cd_chanid = (CHANNEL_ID + t_mmio); /* for efficiency */ + tchanid = pcchannelid; + cardpresent = TR_ISA; /* try ISA */ /* - * Suboptimize knowing first byte different + * Suboptimize knowing first byte different */ - ctemp = readb(cd_chanid) & 0x0f; - if (ctemp != *tchanid) { /* NOT ISA card, try MCA */ - tchanid=mcchannelid; - cardpresent=TR_MCA; - if (ctemp != *tchanid) /* Neither ISA nor MCA */ - cardpresent=NOTOK; + if (ctemp != *tchanid) { /* NOT ISA card, try MCA */ + tchanid = mcchannelid; + cardpresent = TR_MCA; + if (ctemp != *tchanid) /* Neither ISA nor MCA */ + cardpresent = NOTOK; } - - if (cardpresent != NOTOK) - { + if (cardpresent != NOTOK) { /* - * Know presumed type, try rest of ID + * Know presumed type, try rest of ID */ - for (i=2,j=1; i<=46; i=i+2,j++) - { - if ((readb(cd_chanid+i) & 0x0f) != tchanid[j]) { - cardpresent=NOTOK; /* match failed, not TR card */ + for (i = 2, j = 1; i <= 46; i = i + 2, j++) { + if ((readb(cd_chanid + i) & 0x0f) != tchanid[j]) { + cardpresent = NOTOK; /* match failed, not TR card */ break; } } } - /* - * If we have an ISA board check for the ISA P&P version, - * as it has different IRQ settings + * If we have an ISA board check for the ISA P&P version, + * as it has different IRQ settings */ - - if (cardpresent == TR_ISA && (readb(AIPFID + t_mmio)==0x0e)) - cardpresent=TR_ISAPNP; - - if (cardpresent == NOTOK) { /* "channel_id" did not match, report */ + if (cardpresent == TR_ISA && (readb(AIPFID + t_mmio) == 0x0e)) + cardpresent = TR_ISAPNP; + if (cardpresent == NOTOK) { /* "channel_id" did not match, report */ if (ibmtr_debug_trace & TRC_INIT) { DPRINTK("Channel ID string not found for PIOaddr: %4hx\n", PIOaddr); - DPRINTK("Expected for ISA: "); PrtChanID(pcchannelid,1); - DPRINTK(" found: "); HWPrtChanID(cd_chanid,2); - DPRINTK("Expected for MCA: "); PrtChanID(mcchannelid,1); + DPRINTK("Expected for ISA: "); + PrtChanID(pcchannelid, 1); + DPRINTK(" found: "); + HWPrtChanID(cd_chanid, 2); + DPRINTK("Expected for MCA: "); + PrtChanID(mcchannelid, 1); } - return -ENODEV; + return -ENODEV; } - /* Now, allocate some of the pl0 buffers for this driver.. */ /* If called from PCMCIA, ti is already set up, so no need to waste the memory, just use the existing structure */ #ifndef PCMCIA - ti = (struct tok_info *)kmalloc(sizeof(struct tok_info), GFP_KERNEL); - if (ti == NULL) + ti = (struct tok_info *) kmalloc(sizeof(struct tok_info), GFP_KERNEL); + if (ti == NULL) return -ENOMEM; - memset(ti, 0, sizeof(struct tok_info)); -#else - ti = dev->priv ; + ti->mmio = t_mmio; + dev->priv = ti; /* this seems like the logical use of the + field ... let's try some empirical tests + using the token-info structure -- that + should fit with out future hope of multiple + adapter support as well /dwm */ #endif - ti->mmio= t_mmio; ti->readlog_pending = 0; - dev->priv = ti; /* this seems like the logical use of the - field ... let's try some empirical tests - using the token-info structure -- that - should fit with out future hope of multiple - adapter support as well /dwm */ + /* We ignore the retry count except for autonomous reopens so that we * + * don't hold up the operating system. */ + ti->retry_count = TR_RETRIES; - /* if PCMCIA, then the card is recognized as TR_ISAPNP - * and there is no need to set up the interrupt, it is already done. */ - + /* if PCMCIA, the card can be recognized as either TR_ISA or TR_ISAPNP + * depending which card is inserted. */ + #ifndef PCMCIA - switch (cardpresent) - { - case TR_ISA: - if (intr==0) - irq=9; /* irq2 really is irq9 */ - if (intr==1) - irq=3; - if (intr==2) - irq=6; - if (intr==3) - irq=7; - ti->global_int_enable=GLOBAL_INT_ENABLE+((irq==9) ? 2 : irq); - ti->adapter_int_enable=PIOaddr+ADAPTINTREL; - ti->sram=0; -#if !TR_NEWFORMAT - DPRINTK("ti->global_int_enable: %04X\n",ti->global_int_enable); -#endif - break; - case TR_MCA: - if (intr==0) - irq=9; - if (intr==1) - irq=3; - if (intr==2) - irq=10; - if (intr==3) - irq=11; - ti->global_int_enable=0; - ti->adapter_int_enable=0; - ti->sram=((__u32)(inb(PIOaddr+ADAPTRESETREL) & 0xfe) << 12); - break; - case TR_ISAPNP: - if (intr==0) - irq=9; - if (intr==1) - irq=3; - if (intr==2) - irq=10; - if (intr==3) - irq=11; - timeout = jiffies + TR_SPIN_INTERVAL; - while(!readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)) - if (time_after(jiffies, timeout)) { - DPRINTK("Hardware timeout during initialization.\n"); - kfree_s(ti, sizeof(struct tok_info)); - return -ENODEV; - } - - ti->sram=((__u32)readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)<<12); - ti->global_int_enable=PIOaddr+ADAPTINTREL; - ti->adapter_int_enable=PIOaddr+ADAPTINTREL; - break; - } -#endif - - if (ibmtr_debug_trace & TRC_INIT) { /* just report int */ - DPRINTK("irq=%d",irq); - if (ibmtr_debug_trace & TRC_INITV) { /* full chat in verbose only */ - DPRINTK(", ti->mmio=%08X",ti->mmio); - printk(", segment=%02X",segment); + switch (cardpresent) { + case TR_ISA: + if (intr == 0) + irq = 9; /* irq2 really is irq9 */ + if (intr == 1) + irq = 3; + if (intr == 2) + irq = 6; + if (intr == 3) + irq = 7; + ti->global_int_enable = GLOBAL_INT_ENABLE + ((irq == 9) ? 2 : irq); + ti->adapter_int_enable = PIOaddr + ADAPTINTREL; + break; + case TR_MCA: + if (intr == 0) + irq = 9; + if (intr == 1) + irq = 3; + if (intr == 2) + irq = 10; + if (intr == 3) + irq = 11; + ti->global_int_enable = 0; + ti->adapter_int_enable = 0; + ti->sram_virt = ((__u32) (inb(PIOaddr + ADAPTRESETREL) & 0xfe) << 12); + break; + case TR_ISAPNP: + if (intr == 0) + irq = 9; + if (intr == 1) + irq = 3; + if (intr == 2) + irq = 10; + if (intr == 3) + irq = 11; + timeout = jiffies + TR_SPIN_INTERVAL; + while (!readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN)) + if (time_after(jiffies, timeout)) { + DPRINTK("Hardware timeout during initialization.\n"); + kfree_s(ti, sizeof(struct tok_info)); + return -ENODEV; + } + ti->sram_virt = ((__u32) readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN) << 12); + ti->global_int_enable = PIOaddr + ADAPTINTREL; + ti->adapter_int_enable = PIOaddr + ADAPTINTREL; + break; + } /*end switch (cardpresent) */ +#endif /*not PCMCIA */ + + if (ibmtr_debug_trace & TRC_INIT) { /* just report int */ + DPRINTK("irq=%d", irq); + printk(", sram_virt=0x%x", ti->sram_virt); + if (ibmtr_debug_trace & TRC_INITV) { /* full chat in verbose only */ + DPRINTK(", ti->mmio=%08X", ti->mmio); + printk(", segment=%02X", segment); } printk(".\n"); } /* Get hw address of token ring card */ -#if !TR_NEWFORMAT - DPRINTK("hw address: "); -#endif - j=0; - for (i=0; i<0x18; i=i+2) - { + j = 0; + for (i = 0; i < 0x18; i = i + 2) { /* technical reference states to do this */ temp = readb(ti->mmio + AIP + i) & 0x0f; -#if !TR_NEWFORMAT - printk("%1X",ti->hw_address[j]=temp); -#else - ti->hw_address[j]=temp; -#endif - if(j&1) - dev->dev_addr[(j/2)]=ti->hw_address[j]+(ti->hw_address[j-1]<<4); + ti->hw_address[j] = temp; + if (j & 1) + dev->dev_addr[(j / 2)] = ti->hw_address[j] + (ti->hw_address[j - 1] << 4); ++j; } -#ifndef TR_NEWFORMAT - printk("\n"); -#endif - /* get Adapter type: 'F' = Adapter/A, 'E' = 16/4 Adapter II,...*/ + /* get Adapter type: 'F' = Adapter/A, 'E' = 16/4 Adapter II,... */ ti->adapter_type = readb(ti->mmio + AIPADAPTYPE); /* get Data Rate: F=4Mb, E=16Mb, D=4Mb & 16Mb ?? */ @@ -523,292 +497,263 @@ __initfunc(static int ibmtr_probe1(struct device *dev, int PIOaddr)) ti->token_release = readb(ti->mmio + AIPEARLYTOKEN); /* How much shared RAM is on adapter ? */ -#ifdef PCMCIA - ti->avail_shared_ram = pcmcia_reality_check(get_sram_size(ti)); - ibmtr_mem_base = ti->sram_base << 12 ; -#else - ti->avail_shared_ram = get_sram_size(ti); -#endif + ti->avail_shared_ram = get_sram_size(ti); /* in 512 byte units */ + /* We need to set or do a bunch of work here based on previous results.. */ /* Support paging? What sizes?: F=no, E=16k, D=32k, C=16 & 32k */ ti->shared_ram_paging = readb(ti->mmio + AIPSHRAMPAGE); - /* Available DHB 4Mb size: F=2048, E=4096, D=4464 */ + /* Available DHB 4Mb size: F=2048, E=4096, D=4464 */ switch (readb(ti->mmio + AIP4MBDHB)) { - case 0xe : + case 0xe: ti->dhb_size4mb = 4096; - break; - case 0xd : + break; + case 0xd: ti->dhb_size4mb = 4464; - break; - default : + break; + default: ti->dhb_size4mb = 2048; - break; + break; } - /* Available DHB 16Mb size: F=2048, E=4096, D=8192, C=16384, B=17960 */ switch (readb(ti->mmio + AIP16MBDHB)) { - case 0xe : + case 0xe: ti->dhb_size16mb = 4096; - break; - case 0xd : + break; + case 0xd: ti->dhb_size16mb = 8192; - break; - case 0xc : + break; + case 0xc: ti->dhb_size16mb = 16384; - break; - case 0xb : + break; + case 0xb: ti->dhb_size16mb = 17960; - break; - default : + break; + default: ti->dhb_size16mb = 2048; - break; + break; } -#if !TR_NEWFORMAT - DPRINTK("atype=%x, drate=%x, trel=%x, asram=%dK, srp=%x, " - "dhb(4mb=%x, 16mb=%x)\n",ti->adapter_type, - ti->data_rate, ti->token_release, ti->avail_shared_ram/2, - ti->shared_ram_paging, ti->dhb_size4mb, ti->dhb_size16mb); -#endif - - /* We must figure out how much shared memory space this adapter - * will occupy so that if there are two adapters we can fit both - * in. Given a choice, we will limit this adapter to 32K. The - * maximum space will will use for two adapters is 64K so if the - * adapter we are working on demands 64K (it also doesn't support - * paging), then only one adapter can be supported. + /* We must figure out how much shared memory space this adapter + * will occupy so that if there are two adapters we can fit both + * in. Given a choice, we will limit this adapter to 32K. The + * maximum space will will use for two adapters is 64K so if the + * adapter we are working on demands 64K (it also doesn't support + * paging), then only one adapter can be supported. */ /* - * determine how much of total RAM is mapped into PC space + * determine how much of total RAM is mapped into PC space */ - ti->mapped_ram_size=1<<((((readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)) >>2) & 0x03) + 4); - ti->page_mask=0; - if (ti->shared_ram_paging == 0xf) { /* No paging in adapter */ - ti->mapped_ram_size = ti->avail_shared_ram; + ti->mapped_ram_size = /* sixteen to one hundred twenty eight 512byte blocks */ + 1 << (((readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_ODD) >> 2) & 0x03) + 4); + ti->page_mask = 0; + if (ti->shared_ram_paging == 0xf) { /* No paging in adapter */ } else { #ifdef ENABLE_PAGING - unsigned char pg_size=0; -#endif - -#if !TR_NEWFORMAT - DPRINTK("shared ram page size: %dK\n",ti->mapped_ram_size/2); -#endif -#ifdef ENABLE_PAGING - switch(ti->shared_ram_paging) - { + unsigned char pg_size = 0; + /* BMS: page size: PCMCIA, use configuration register; + ISAPNP, use LANAIDC config tool from www.ibm.com */ + switch (ti->shared_ram_paging) { case 0xf: break; case 0xe: - ti->page_mask=(ti->mapped_ram_size==32) ? 0xc0 : 0; - pg_size=32; /* 16KB page size */ + ti->page_mask = (ti->mapped_ram_size == 32) ? 0xc0 : 0; + pg_size = 32; /* 16KB page size */ break; case 0xd: - ti->page_mask=(ti->mapped_ram_size==64) ? 0x80 : 0; - pg_size=64; /* 32KB page size */ + ti->page_mask = (ti->mapped_ram_size == 64) ? 0x80 : 0; + pg_size = 64; /* 32KB page size */ break; case 0xc: - switch (ti->mapped_ram_size) { - case 32: - ti->page_mask=0xc0; - pg_size=32; - break; - case 64: - ti->page_mask=0x80; - pg_size=64; - break; - } + switch (ti->mapped_ram_size) { + case 32: + ti->page_mask = 0xc0; + pg_size = 32; + break; + case 64: + ti->page_mask = 0x80; + pg_size = 64; + break; + } break; default: - DPRINTK("Unknown shared ram paging info %01X\n",ti->shared_ram_paging); + DPRINTK("Unknown shared ram paging info %01X\n", ti->shared_ram_paging); kfree_s(ti, sizeof(struct tok_info)); return -ENODEV; break; + } /*end switch shared_ram_paging */ + if (ibmtr_debug_trace & TRC_INIT) + DPRINTK("Shared RAM paging code: " + "%02X, mapped RAM size: %dK, shared RAM size: %dK, page mask: %02X\n:", + ti->shared_ram_paging, ti->mapped_ram_size / 2, ti->avail_shared_ram / 2, ti->page_mask); +#endif /*ENABLE_PAGING */ } - if (ibmtr_debug_trace & TRC_INIT) - DPRINTK("Shared RAM paging code: " - "%02X mapped RAM size: %dK shared RAM size: %dK page mask: %0xX\n:", - ti->shared_ram_paging, ti->mapped_ram_size/2, ti->avail_shared_ram/2, ti->page_mask); - - if (ti->page_mask) { - if (pg_size > ti->mapped_ram_size) { - DPRINTK("Page size (%d) > mapped ram window (%d), can't page.\n", - pg_size/2, ti->mapped_ram_size/2); - ti->page_mask = 0; /* reset paging */ - } - } else if (pg_size > ti->mapped_ram_size) { - DPRINTK("Page size (%d) > mapped ram window (%d), can't page.\n", - pg_size/2, ti->mapped_ram_size/2); - } - -#endif - } +#ifndef PCMCIA /* finish figuring the shared RAM address */ - if (cardpresent==TR_ISA) { - static __u32 ram_bndry_mask[]={0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000}; + if (cardpresent == TR_ISA) { + static __u32 ram_bndry_mask[] = { 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000 }; __u32 new_base, rrr_32, chk_base, rbm; - rrr_32 = ((readb(ti->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD))>>2) & 0x00000003; + rrr_32 = ((readb(ti->mmio + ACA_OFFSET + ACA_RW + RRR_ODD)) >> 2) & 0x03; rbm = ram_bndry_mask[rrr_32]; - new_base = (ibmtr_mem_base + (~rbm)) & rbm; /* up to boundary */ - chk_base = new_base + (ti->mapped_ram_size<<9); + new_base = (ibmtr_mem_base + (~rbm)) & rbm; /* up to boundary */ + chk_base = new_base + (ti->mapped_ram_size << 9); if (chk_base > (ibmtr_mem_base + IBMTR_SHARED_RAM_SIZE)) { - DPRINTK("Shared RAM for this adapter (%05x) exceeds driver" - " limit (%05x), adapter not started.\n", - chk_base, ibmtr_mem_base + IBMTR_SHARED_RAM_SIZE); + DPRINTK("Shared RAM for this adapter (%05x) exceeds driver" " limit (%05x), adapter not started.\n", chk_base, ibmtr_mem_base + IBMTR_SHARED_RAM_SIZE); kfree_s(ti, sizeof(struct tok_info)); - return -ENODEV; - } else { /* seems cool, record what we have figured out */ + return -ENODEV; + } else { /* seems cool, record what we have figured out */ ti->sram_base = new_base >> 12; ibmtr_mem_base = chk_base; } } - -#if !TR_NEWFORMAT - DPRINTK("Using %dK shared RAM\n",ti->mapped_ram_size/2); -#endif + else ti->sram_base = ti->sram_virt >> 12; /* The PCMCIA has already got the interrupt line and the io port, so no chance of anybody else getting it - MLP */ - -#ifndef PCMCIA - if (request_irq (dev->irq = irq, &tok_interrupt,0,"ibmtr", dev) != 0) { - DPRINTK("Could not grab irq %d. Halting Token Ring driver.\n",irq); + if (request_irq(dev->irq = irq, &tok_interrupt, 0, "ibmtr", dev) != 0) { + DPRINTK("Could not grab irq %d. Halting Token Ring driver.\n", irq); kfree_s(ti, sizeof(struct tok_info)); return -ENODEV; } - /*?? Now, allocate some of the PIO PORTs for this driver.. */ - request_region(PIOaddr,IBMTR_IO_EXTENT,"ibmtr"); /* record PIOaddr range as busy */ -#endif - -#if !TR_NEWFORMAT - DPRINTK("%s",version); /* As we have passed card identification, - let the world know we're here! */ -#else - + /* record PIOaddr range as busy */ + request_region(PIOaddr, IBMTR_IO_EXTENT, "ibmtr"); +#endif /*not PCMCIA */ +#ifndef PCMCIA if (version) { - printk("%s",version); - version = NULL; - } - DPRINTK("%s %s found\n", - channel_def[cardpresent-1], adapter_def(ti->adapter_type)); - DPRINTK("using irq %d, PIOaddr %hx, %dK shared RAM.\n", - irq, PIOaddr, ti->mapped_ram_size/2); - DPRINTK("Hardware address : %02X:%02X:%02X:%02X:%02X:%02X\n", - dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], - dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); - if (ti->page_mask) - DPRINTK("Shared RAM paging enabled. Page size: %uK Shared Ram size %dK\n", - ((ti->page_mask ^ 0xff)+1)>>2,ti->avail_shared_ram/2); - else - DPRINTK("Shared RAM paging disabled. ti->page_mask %x\n",ti->page_mask); + printk("%s", version); + version = NULL; + } #endif + DPRINTK("%s %s found\n", channel_def[cardpresent - 1], adapter_def(ti->adapter_type)); + DPRINTK("using irq %d, PIOaddr %hx, %dK shared RAM.\n", irq, PIOaddr, ti->mapped_ram_size / 2); + DPRINTK("Hardware address : %02X:%02X:%02X:%02X:%02X:%02X\n", dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + if (ti->page_mask) + DPRINTK("Shared RAM paging enabled. Page size: %uK Shared Ram size %dK\n", ((ti->page_mask ^ 0xff) + 1) >> 2, ti->avail_shared_ram / 2); + else + DPRINTK("Shared RAM paging disabled. ti->page_mask %x\n", ti->page_mask); + /* Calculate the maximum DHB we can use */ if (!ti->page_mask) { - ti->avail_shared_ram=ti->mapped_ram_size; + /* two cases where avail_shared_ram doesn't equal mapped_ram_size: + 1. avail_shared_ram is 127 but mapped_ram_size is 128 (typical) + 2. user has configured adapter for less than avail_shared_ram + but is not using paging (she should use paging, I believe) + */ + ti->avail_shared_ram=MIN(ti->mapped_ram_size,ti->avail_shared_ram); } switch (ti->avail_shared_ram) { - case 16 : /* 8KB shared RAM */ - ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); + case 16: /* 8KB shared RAM */ + ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); ti->rbuf_len4 = 1032; - ti->rbuf_cnt4 = 2; + ti->rbuf_cnt4=2; ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048); ti->rbuf_len16 = 1032; - ti->rbuf_cnt16 = 2; + ti->rbuf_cnt16=2; break; - case 32 : /* 16KB shared RAM */ - ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); - ti->rbuf_len4 = 520; - ti->rbuf_cnt4 = 9; - ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048); - ti->rbuf_len16 = 1032; /* 1024 usable */ - ti->rbuf_cnt16 = 4; + case 32: /* 16KB shared RAM */ + ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); + ti->rbuf_len4 = 1032; + ti->rbuf_cnt4=4; + ti->dhb_size16mb = MIN(ti->dhb_size16mb, 4096); + ti->rbuf_len16 = 1032; /*1024 usable */ + ti->rbuf_cnt16=4; break; - case 64 : /* 32KB shared RAM */ - ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); + case 64: /* 32KB shared RAM */ + ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); ti->rbuf_len4 = 1032; - ti->rbuf_cnt4 = 6; - ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048); + ti->rbuf_cnt4=6; + ti->dhb_size16mb = MIN(ti->dhb_size16mb, 10240); ti->rbuf_len16 = 1032; - ti->rbuf_cnt16 = 10; + ti->rbuf_cnt16=6; break; - case 127 : /* 63KB shared RAM */ - ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); + case 127: /* 63.5KB shared RAM */ + ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); ti->rbuf_len4 = 1032; - ti->rbuf_cnt4 = 6; - ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048); + ti->rbuf_cnt4=6; + ti->dhb_size16mb = MIN(ti->dhb_size16mb, 16384); ti->rbuf_len16 = 1032; - ti->rbuf_cnt16 = 16; + ti->rbuf_cnt16=16; break; - case 128 : /* 64KB shared RAM */ - ti->dhb_size4mb = MIN(ti->dhb_size4mb, 2048); + case 128: /* 64KB shared RAM */ + ti->dhb_size4mb = MIN(ti->dhb_size4mb, 4464); ti->rbuf_len4 = 1032; - ti->rbuf_cnt4 = 6; - ti->dhb_size16mb = MIN(ti->dhb_size16mb, 2048); + ti->rbuf_cnt4=6; + ti->dhb_size16mb = MIN(ti->dhb_size16mb, 17960); ti->rbuf_len16 = 1032; - ti->rbuf_cnt16 = 18; + ti->rbuf_cnt16=16; break; - default : - ti->dhb_size4mb = 2048; + default: + ti->dhb_size4mb = 2048; ti->rbuf_len4 = 1032; - ti->rbuf_cnt4 = 2; + ti->rbuf_cnt4=2; ti->dhb_size16mb = 2048; ti->rbuf_len16 = 1032; - ti->rbuf_cnt16 = 2; + ti->rbuf_cnt16=2; break; } - - ti->maxmtu16 = (ti->rbuf_len16*ti->rbuf_cnt16)-((ti->rbuf_cnt16)<<3)-TR_HLEN; - ti->maxmtu4 = (ti->rbuf_len4*ti->rbuf_cnt4)-((ti->rbuf_cnt4)<<3)-TR_HLEN; - DPRINTK("Maximum MTU 16Mbps: %d, 4Mbps: %d\n", - ti->maxmtu16, ti->maxmtu4); - - dev->base_addr=PIOaddr; /* set the value for device */ - + /* these formulas are not smart enough for the paging case + ti->rbuf_cnt4 = (ti->avail_shared_ram * BLOCKSZ - + ADAPT_PRIVATE - ARBLENGTH - SSBLENGTH - + DLC_MAX_SAP * SAPLENGTH - DLC_MAX_STA * STALENGTH - ti->dhb_size4mb * NUM_DHB - SRBLENGTH - ASBLENGTH) / ti->rbuf_len4; + ti->rbuf_cnt16 = (ti->avail_shared_ram * BLOCKSZ - + ADAPT_PRIVATE - ARBLENGTH - SSBLENGTH - + DLC_MAX_SAP * SAPLENGTH - DLC_MAX_STA * STALENGTH - ti->dhb_size16mb * NUM_DHB - SRBLENGTH - ASBLENGTH) / ti->rbuf_len16; + */ + ti->maxmtu16 = (ti->rbuf_len16 - 8) * ti->rbuf_cnt16 - TR_HLEN; + ti->maxmtu4 = (ti->rbuf_len4 - 8) * ti->rbuf_cnt4 - TR_HLEN; + /*BMS assuming 18 bytes of Routing Information (usually works) */ + DPRINTK("Maximum Receive Internet Protocol MTU 16Mbps: %d, 4Mbps: %d\n", ti->maxmtu16, ti->maxmtu4); + + dev->base_addr = PIOaddr; /* set the value for device */ trdev_init(dev); tok_init_card(dev); + return 0; /* Return 0 to indicate we have found a Token Ring card. */ +} /*ibmtr_probe1() */ - return 0; /* Return 0 to indicate we have found a Token Ring card. */ -} +/*****************************************************************************/ /* query the adapter for the size of shared RAM */ +/* the function returns the RAM size in units of 512 bytes */ __initfunc(static unsigned char get_sram_size(struct tok_info *adapt_info)) { unsigned char avail_sram_code; - static unsigned char size_code[]={ 0,16,32,64,127,128 }; + static unsigned char size_code[] = { 0, 16, 32, 64, 127, 128 }; /* Adapter gives 'F' -- use RRR bits 3,2 'E' -- 8kb 'D' -- 16kb 'C' -- 32kb 'A' -- 64KB 'B' - 64KB less 512 bytes at top - (WARNING ... must zero top bytes in INIT */ + (WARNING ... must zero top bytes in INIT */ - avail_sram_code=0xf-readb(adapt_info->mmio + AIPAVAILSHRAM); + avail_sram_code = 0xf - readb(adapt_info->mmio + AIPAVAILSHRAM); if (avail_sram_code) return size_code[avail_sram_code]; - else /* for code 'F', must compute size from RRR(3,2) bits */ - return 1<<((readb(adapt_info->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)>>2)+4); + else /* for code 'F', must compute size from RRR(3,2) bits */ + return 1 << (((readb(adapt_info->mmio + ACA_OFFSET + ACA_RW + RRR_ODD) >> 2) & 0x03) + 4); } +/*****************************************************************************/ + __initfunc(static int trdev_init(struct device *dev)) { - struct tok_info *ti=(struct tok_info *)dev->priv; + struct tok_info *ti = (struct tok_info *) dev->priv; SET_PAGE(ti->srb_page); - ti->open_status = CLOSED; + ti->open_status = CLOSED; - dev->init = tok_init_card; - dev->open = tok_open; - dev->stop = tok_close; - dev->hard_start_xmit = tok_send_packet; - dev->get_stats = tok_get_stats; + dev->init = tok_init_card; + dev->open = tok_open; + dev->stop = tok_close; + dev->hard_start_xmit = tok_send_packet; + dev->get_stats = tok_get_stats; dev->set_multicast_list = tok_set_multicast_list; - dev->change_mtu = ibmtr_change_mtu; + dev->change_mtu = ibmtr_change_mtu; #ifndef MODULE #ifndef PCMCIA @@ -818,20 +763,141 @@ __initfunc(static int trdev_init(struct device *dev)) return 0; } +/*****************************************************************************/ + +static int tok_init_card(struct device *dev) +{ /* BMStok_init_card always returns zero */ + struct tok_info *ti; + short PIOaddr; + unsigned long i; + + PIOaddr = dev->base_addr; + ti = (struct tok_info *) dev->priv; + /* Special processing for first interrupt after reset */ + ti->do_tok_int = FIRST_INT; + /* Reset adapter */ + dev->tbusy = 1; /* nothing can be done before reset and open completed */ + writeb(~INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN); + outb(0, PIOaddr + ADAPTRESET); + for (i = jiffies + TR_RESET_INTERVAL; time_before_eq(jiffies, i);); /* wait 50ms */ + outb(0, PIOaddr + ADAPTRESETREL); +#ifdef ENABLE_PAGING + if (ti->page_mask) + writeb(SRPR_ENABLE_PAGING, ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN); +#endif + writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); + i = sleep_on_timeout(&ti->wait_for_reset, 4 * HZ); + return 0; +} + +/*****************************************************************************/ +static int tok_open(struct device *dev) +{ + struct tok_info *ti = (struct tok_info *) dev->priv; + int i; + const char *printstate[] = {"CLOSED","SUCCESS","FAILURE","AUTOREOPEN"} ; + + /*BMS the case where we were left in a failure state during a previous open */ + if (ti->open_status == FAILURE) { + printk("Last time you were disconnected, how about now?\n"); + printk("Look, you cannot insert with your ICS connector half-cocked.\n"); + ti->open_status = CLOSED; + } + /* init the spinlock */ + ti->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; + tok_open_adapter((unsigned long) dev); + i = sleep_on_timeout(&ti->wait_for_reset, 25 * HZ); + if (ti->open_status == SUCCESS) { + MOD_INC_USE_COUNT; + return 0; + } else { + printk("tok_open: returned with open_status==%s\n", printstate[ti->open_status]); /*BMS useful */ + return -EAGAIN; + } +} + +/*****************************************************************************/ + +void tok_open_adapter(unsigned long dev_addr) +{ + + struct device *dev = (struct device *) dev_addr; + struct tok_info *ti; + int i; + + ti = (struct tok_info *) dev->priv; + + writeb(~SRB_RESP_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); + writeb(~CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD); + + for (i = 0; i < sizeof(struct dir_open_adapter); i++) + writeb(0, ti->init_srb + i); + + writeb(DIR_OPEN_ADAPTER, ti->init_srb + offsetof(struct dir_open_adapter, command)); + writew(htons(OPEN_PASS_BCON_MAC), ti->init_srb + offsetof(struct dir_open_adapter, open_options)); + if (ti->ring_speed == 16) { + writew(htons(ti->dhb_size16mb), ti->init_srb + offsetof(struct dir_open_adapter, dhb_length)); + writew(htons(ti->rbuf_cnt16), ti->init_srb + offsetof(struct dir_open_adapter, num_rcv_buf)); + writew(htons(ti->rbuf_len16), ti->init_srb + offsetof(struct dir_open_adapter, rcv_buf_len)); + } else { + writew(htons(ti->dhb_size4mb), ti->init_srb + offsetof(struct dir_open_adapter, dhb_length)); + writew(htons(ti->rbuf_cnt4), ti->init_srb + offsetof(struct dir_open_adapter, num_rcv_buf)); + writew(htons(ti->rbuf_len4), ti->init_srb + offsetof(struct dir_open_adapter, rcv_buf_len)); + } + writeb(NUM_DHB, /* always 2 */ + ti->init_srb + offsetof(struct dir_open_adapter, num_dhb)); + writeb(DLC_MAX_SAP, ti->init_srb + offsetof(struct dir_open_adapter, dlc_max_sap)); + writeb(DLC_MAX_STA, ti->init_srb + offsetof(struct dir_open_adapter, dlc_max_sta)); + + ti->srb = ti->init_srb; /* We use this one in the interrupt handler */ + ti->srb_page = ti->init_srb_page; + DPRINTK("Opening adapter: Xmit bfrs: %d X %d, Rcv bfrs: %d X %d\n", + readb(ti->init_srb + offsetof(struct dir_open_adapter, num_dhb)), + ntohs(readw(ti->init_srb + offsetof(struct dir_open_adapter, dhb_length))), + ntohs(readw(ti->init_srb + offsetof(struct dir_open_adapter, num_rcv_buf))), ntohs(readw(ti->init_srb + offsetof(struct dir_open_adapter, rcv_buf_len)))); + + writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); + writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); + +} + +/*****************************************************************************/ + +static void open_sap(unsigned char type, struct device *dev) +{ + int i; + struct tok_info *ti = (struct tok_info *) dev->priv; + SET_PAGE(ti->srb_page); + for (i = 0; i < sizeof(struct dlc_open_sap); i++) + writeb(0, ti->srb + i); + + writeb(DLC_OPEN_SAP, ti->srb + offsetof(struct dlc_open_sap, command)); + writew(htons(MAX_I_FIELD), ti->srb + offsetof(struct dlc_open_sap, max_i_field)); + writeb(SAP_OPEN_IND_SAP | SAP_OPEN_PRIORITY, ti->srb + offsetof(struct dlc_open_sap, sap_options)); + writeb(SAP_OPEN_STATION_CNT, ti->srb + offsetof(struct dlc_open_sap, station_count)); + writeb(type, ti->srb + offsetof(struct dlc_open_sap, sap_value)); + + writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); + +} + +/*****************************************************************************/ static void tok_set_multicast_list(struct device *dev) { - struct tok_info *ti=(struct tok_info *)dev->priv; + struct tok_info *ti = (struct tok_info *) dev->priv; struct dev_mc_list *mclist; unsigned char address[4]; int i; + /*BMS the next line is CRUCIAL or you may be sad when you */ + /*BMS ifconfig tr down or hot unplug a PCMCIA card */ + if (dev->start == 0 || ti->open_status != SUCCESS) + return; address[0] = address[1] = address[2] = address[3] = 0; - mclist = dev->mc_list; - for (i=0; i< dev->mc_count; i++) - { + for (i = 0; i < dev->mc_count; i++) { address[0] |= mclist->dmi_addr[2]; address[1] |= mclist->dmi_addr[3]; address[2] |= mclist->dmi_addr[4]; @@ -839,80 +905,102 @@ static void tok_set_multicast_list(struct device *dev) mclist = mclist->next; } SET_PAGE(ti->srb_page); - for (i=0; isrb+i); - - writeb(DIR_SET_FUNC_ADDR, - ti->srb + offsetof(struct srb_set_funct_addr, command)); + for (i = 0; i < sizeof(struct srb_set_funct_addr); i++) + writeb(0, ti->srb + i); + writeb(DIR_SET_FUNC_ADDR, ti->srb + offsetof(struct srb_set_funct_addr, command)); + for (i = 0; i < 4; i++) + writeb(address[i], ti->srb + offsetof(struct srb_set_funct_addr, funct_address) + i); + writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); +#if TR_VERBOSE DPRINTK("Setting functional address: "); - - for (i=0; i<4; i++) - { - writeb(address[i], - ti->srb + offsetof(struct srb_set_funct_addr, funct_address)+i); + for (i=0;i<4;i++) { printk("%02X ", address[i]); } - writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); printk("\n"); +#endif } -static int tok_open(struct device *dev) +/*****************************************************************************/ + +static int tok_send_packet(struct sk_buff *skb, struct device *dev) { - struct tok_info *ti=(struct tok_info *)dev->priv; + struct tok_info *ti; + ti = (struct tok_info *) dev->priv; - /* init the spinlock */ - ti->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; + if (dev->tbusy) { + int ticks_waited; - if (ti->open_status==CLOSED) tok_init_card(dev); + ticks_waited = jiffies - dev->trans_start; + if (ticks_waited < TR_BUSY_INTERVAL) + return 1; - if (ti->open_status==IN_PROGRESS) sleep_on(&ti->wait_for_reset); + DPRINTK("Arrg. Transmitter busy.\n"); + dev->trans_start += 5; /* we fake the transmission start time... */ + return 1; + } - if (ti->open_status==SUCCESS) { - dev->tbusy=0; - dev->interrupt=0; - dev->start=1; - /* NEED to see smem size *AND* reset high 512 bytes if needed */ + if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) + DPRINTK("Transmitter access conflict\n"); + else { + int flags; - MOD_INC_USE_COUNT; + /* lock against other CPUs */ + spin_lock_irqsave(&(ti->lock), flags); - return 0; - } else return -EAGAIN; + /* Save skb; we'll need it when the adapter asks for the data */ + ti->current_skb = skb; + SET_PAGE(ti->srb_page); + writeb(XMIT_UI_FRAME, ti->srb + offsetof(struct srb_xmit, command)); + writew(ti->exsap_station_id, ti->srb + offsetof(struct srb_xmit, station_id)); + writeb(CMD_IN_SRB, (ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)); + spin_unlock_irqrestore(&(ti->lock), flags); + + dev->trans_start = jiffies; + } + return 0; } +/*****************************************************************************/ + static int tok_close(struct device *dev) { - struct tok_info *ti=(struct tok_info *) dev->priv; - - SET_PAGE(ti->srb_page); - writeb(DIR_CLOSE_ADAPTER, - ti->srb + offsetof(struct srb_close_adapter, command)); - writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - - ti->open_status=CLOSED; - - sleep_on(&ti->wait_for_tok_int); + struct tok_info *ti = (struct tok_info *) dev->priv; + char myclose = 0; + int x; + unsigned short y; - SET_PAGE(ti->srb_page); - if (readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))) - DPRINTK("close adapter failed: %02X\n", - (int)readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))); - dev->start = 0; -#ifdef PCMCIA - ti->sram = 0 ; -#endif - DPRINTK("Adapter closed.\n"); + x = del_timer(&ti->tr_timer); /*BMS Important for PCMCIA hot unplug */ + /* next line is crucial for PCMCIA */ + if (ti->open_status == SUCCESS && dev->start) { + myclose = 1; + SET_PAGE(ti->srb_page); + writeb(DIR_CLOSE_ADAPTER, ti->srb + offsetof(struct srb_close_adapter, command)); + writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); + } + ti->open_status = CLOSED; /* indicator for popped timers */ + if (myclose) { + y = sleep_on_timeout(&ti->wait_for_tok_int, 2 * HZ); + /*BMSprintk("tok_close: returning from sleep, timeout=%d\n",y); */ + SET_PAGE(ti->srb_page); + if (readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))) + DPRINTK("close adapter failed: %02X\n", (int) readb(ti->srb + offsetof(struct srb_close_adapter, ret_code))); + } + dev->start = 0; + DPRINTK("Adapter is closed.\n"); MOD_DEC_USE_COUNT; - return 0; } -void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) +/*****************************************************************************/ + +void tok_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - unsigned char status; + unsigned char status, prior_open_status; + /* unsigned char status_even ; */ struct tok_info *ti; struct device *dev; #ifdef ENABLE_PAGING @@ -921,427 +1009,353 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs) dev = dev_id; #if TR_VERBOSE - DPRINTK("Int from tok_driver, dev : %p\n",dev); + DPRINTK("Int from tok_driver, dev : %p\n", dev); #endif - ti = (struct tok_info *) dev->priv; + ti = (struct tok_info *) dev->priv; + if (ti->sram_virt & 1) + return; /* PCMCIA card extraction flag */ spin_lock(&(ti->lock)); #ifdef ENABLE_PAGING - save_srpr=readb(ti->mmio+ACA_OFFSET+ACA_RW+SRPR_EVEN); + save_srpr = readb(ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN); #endif - /* Disable interrupts till processing is finished */ - dev->interrupt=1; + /* Disable interrupts till processing is finished */ + dev->interrupt = 1; writeb((~INT_ENABLE), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN); /* Reset interrupt for ISA boards */ - if (ti->adapter_int_enable) - outb(0,ti->adapter_int_enable); + if (ti->adapter_int_enable) + outb(0, ti->adapter_int_enable); else - outb(0,ti->global_int_enable); - + outb(0, ti->global_int_enable); switch (ti->do_tok_int) { - - case NOT_FIRST: - - /* Begin the regular interrupt handler HERE inline to avoid - the extra levels of logic and call depth for the - original solution. */ - - status=readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_ODD); -#ifdef PCMCIA - /* Check if the PCMCIA card was pulled. */ - if (status == 0xFF) - { - DPRINTK("PCMCIA card removed.\n"); - dev->interrupt = 0; - goto return_point; - } - - /* Check ISRP EVEN too. */ - if ( readb (ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) == 0xFF) - { - DPRINTK("PCMCIA card removed.\n"); - dev->interrupt = 0; - goto return_point; - } -#endif - - + case NOT_FIRST: + /* Begin the regular interrupt handler HERE inline to avoid the extra + levels of logic and call depth for the original solution. */ + status = readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_ODD); + /*BMSstatus_even = readb (ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) */ + /*BMSdebugprintk("tok_interrupt: ISRP_ODD = 0x%x ISRP_EVEN = 0x%x\n", */ + /*BMS status,status_even); */ if (status & ADAP_CHK_INT) { - int i; __u32 check_reason; - __u8 check_reason_page=0; - - check_reason=ntohs(readw(ti->sram + ACA_OFFSET + ACA_RW +WWCR_EVEN)); + __u8 check_reason_page = 0; + check_reason = ntohs(readw(ti->sram_virt + ACA_OFFSET + ACA_RW + WWCR_EVEN)); if (ti->page_mask) { - check_reason_page=(check_reason>>8) & ti->page_mask; - check_reason &= ~(ti->page_mask << 8); + check_reason_page = (check_reason >> 8) & ti->page_mask; + check_reason &= ~(ti->page_mask << 8); } - check_reason += ti->sram; + check_reason += ti->sram_virt; SET_PAGE(check_reason_page); DPRINTK("Adapter check interrupt\n"); DPRINTK("8 reason bytes follow: "); - for(i=0; i<8; i++, check_reason++) - printk("%02X ", (int)readb(check_reason)); + for (i = 0; i < 8; i++, check_reason++) + printk("%02X ", (int) readb(check_reason)); printk("\n"); - writeb((~ADAP_CHK_INT), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); - writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); - dev->interrupt=0; - + writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); + dev->interrupt = 0; } else if (readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN) - & (TCR_INT | ERR_INT | ACCESS_INT)) { - - DPRINTK("adapter error: ISRP_EVEN : %02x\n", - (int)readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN)); - writeb(~(TCR_INT | ERR_INT | ACCESS_INT), - ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN); - writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); - dev->interrupt=0; - - } else if (status - & (SRB_RESP_INT | ASB_FREE_INT | ARB_CMD_INT | SSB_RESP_INT)) { + & (TCR_INT | ERR_INT | ACCESS_INT)) { + DPRINTK("adapter error: ISRP_EVEN : %02x\n", (int) readb(ti->mmio + ACA_OFFSET + ACA_RW + ISRP_EVEN)); + writeb(~(TCR_INT | ERR_INT | ACCESS_INT), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN); + writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); + dev->interrupt = 0; + } else if (status & (SRB_RESP_INT | ASB_FREE_INT | ARB_CMD_INT | SSB_RESP_INT)) { /* SRB, ASB, ARB or SSB response */ - - if (status & SRB_RESP_INT) { /* SRB response */ - SET_PAGE(ti->srb_page); + if (status & SRB_RESP_INT) { /* SRB response */ + SET_PAGE(ti->srb_page); #if TR_VERBOSE - DPRINTK("SRB resp: cmd=%02X rsp=%02X\n", - readb(ti->srb), - readb(ti->srb + offsetof(struct srb_xmit, ret_code))); + DPRINTK("SRB resp: cmd=%02X rsp=%02X\n", readb(ti->srb), readb(ti->srb + offsetof(struct srb_xmit, ret_code))); #endif - switch(readb(ti->srb)) { /* SRB command check */ - - case XMIT_DIR_FRAME: { - unsigned char xmit_ret_code; - - xmit_ret_code=readb(ti->srb + offsetof(struct srb_xmit, ret_code)); - if (xmit_ret_code != 0xff) { - DPRINTK("error on xmit_dir_frame request: %02X\n", - xmit_ret_code); - if (ti->current_skb) { - dev_kfree_skb(ti->current_skb); - ti->current_skb=NULL; - } - dev->tbusy=0; - if (ti->readlog_pending) ibmtr_readlog(dev); - } - } - break; - - case XMIT_UI_FRAME: { - unsigned char xmit_ret_code; - - xmit_ret_code=readb(ti->srb + offsetof(struct srb_xmit, ret_code)); - if (xmit_ret_code != 0xff) { - DPRINTK("error on xmit_ui_frame request: %02X\n", - xmit_ret_code); - if (ti->current_skb) { - dev_kfree_skb(ti->current_skb); - ti->current_skb=NULL; - } - dev->tbusy=0; - if (ti->readlog_pending) ibmtr_readlog(dev); - } - } - break; - - case DIR_OPEN_ADAPTER: { - unsigned char open_ret_code; - __u16 open_error_code; - - ti->srb=ntohs(readw(ti->init_srb +offsetof(struct srb_open_response, srb_addr))); - ti->ssb=ntohs(readw(ti->init_srb +offsetof(struct srb_open_response, ssb_addr))); - ti->arb=ntohs(readw(ti->init_srb +offsetof(struct srb_open_response, arb_addr))); - ti->asb=ntohs(readw(ti->init_srb +offsetof(struct srb_open_response, asb_addr))); - if (ti->page_mask) { - ti->srb_page=(ti->srb>>8) & ti->page_mask; - ti->srb &= ~(ti->page_mask<<8); - ti->ssb_page=(ti->ssb>>8) & ti->page_mask; - ti->ssb &= ~(ti->page_mask<<8); - ti->arb_page=(ti->arb>>8) & ti->page_mask; - ti->arb &= ~(ti->page_mask<<8); - ti->asb_page=(ti->asb>>8) & ti->page_mask; - ti->asb &= ~(ti->page_mask<<8); - } - ti->srb+=ti->sram; - ti->ssb+=ti->sram; - ti->arb+=ti->sram; - ti->asb+=ti->sram; - - ti->current_skb=NULL; - - open_ret_code = readb(ti->init_srb +offsetof(struct srb_open_response, ret_code)); - open_error_code = ntohs(readw(ti->init_srb +offsetof(struct srb_open_response, error_code))); - - if (open_ret_code==7) { - - if (!ti->auto_ringspeedsave && (open_error_code==0x24)) { - DPRINTK("Open failed: Adapter speed must match ring " - "speed if Automatic Ring Speed Save is disabled.\n"); - ti->open_status=FAILURE; - wake_up(&ti->wait_for_reset); - } else if (open_error_code==0x24) - DPRINTK("Retrying open to adjust to ring speed.\n"); - else if ((open_error_code==0x2d) && ti->auto_ringspeedsave) - DPRINTK("No signal detected for Auto Speed Detection.\n"); - else if (open_error_code==0x11) - { - if (ti->retry_count--) - DPRINTK("Ring broken/disconnected, retrying...\n"); - else { - DPRINTK("Ring broken/disconnected, open failed.\n"); - ti->open_status = FAILURE; - } - } - else DPRINTK("Unrecoverable error: error code = %04x.\n", - open_error_code); - - } else if (!open_ret_code) { -#if !TR_NEWFORMAT - DPRINTK("board opened...\n"); -#else - DPRINTK("Adapter initialized and opened.\n"); -#endif - writeb(~(SRB_RESP_INT), - ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); - writeb(~(CMD_IN_SRB), - ti->mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD); - open_sap(EXTENDED_SAP,dev); - - /* YdW probably hates me */ - goto skip_reset; - } else - DPRINTK("open failed: ret_code = %02X, retrying\n", - open_ret_code); - - if (ti->open_status != FAILURE) { - ibmtr_reset_timer(&(ti->tr_timer), dev); - } - - } - break; - - case DIR_CLOSE_ADAPTER: + switch (readb(ti->srb)) { /* SRB command check */ + case XMIT_DIR_FRAME:{ + unsigned char xmit_ret_code; + xmit_ret_code = readb(ti->srb + offsetof(struct srb_xmit, ret_code)); + if (xmit_ret_code != 0xff) { + DPRINTK("error on xmit_dir_frame request: %02X\n", xmit_ret_code); + if (ti->current_skb) { + dev_kfree_skb(ti->current_skb); + ti->current_skb = NULL; + } + dev->tbusy = 0; + if (ti->readlog_pending) + ibmtr_readlog(dev); + } + } + break; + case XMIT_UI_FRAME:{ + unsigned char xmit_ret_code; + + xmit_ret_code = readb(ti->srb + offsetof(struct srb_xmit, ret_code)); + if (xmit_ret_code != 0xff) { + DPRINTK("error on xmit_ui_frame request: %02X\n", xmit_ret_code); + if (ti->current_skb) { + dev_kfree_skb(ti->current_skb); + ti->current_skb = NULL; + } + dev->tbusy = 0; + if (ti->readlog_pending) + ibmtr_readlog(dev); + } + } + break; + case DIR_OPEN_ADAPTER:{ + unsigned char open_ret_code; + __u16 open_error_code; + ti->srb = ntohs(readw(ti->init_srb + offsetof(struct srb_open_response, srb_addr))); + ti->ssb = ntohs(readw(ti->init_srb + offsetof(struct srb_open_response, ssb_addr))); + ti->arb = ntohs(readw(ti->init_srb + offsetof(struct srb_open_response, arb_addr))); + ti->asb = ntohs(readw(ti->init_srb + offsetof(struct srb_open_response, asb_addr))); + if (ti->page_mask) { + ti->srb_page = (ti->srb >> 8) & ti->page_mask; + ti->srb &= ~(ti->page_mask << 8); + ti->ssb_page = (ti->ssb >> 8) & ti->page_mask; + ti->ssb &= ~(ti->page_mask << 8); + ti->arb_page = (ti->arb >> 8) & ti->page_mask; + ti->arb &= ~(ti->page_mask << 8); + ti->asb_page = (ti->asb >> 8) & ti->page_mask; + ti->asb &= ~(ti->page_mask << 8); + } + ti->srb += ti->sram_virt; + ti->ssb += ti->sram_virt; + ti->arb += ti->sram_virt; + ti->asb += ti->sram_virt; + + ti->current_skb = NULL; + open_ret_code = readb(ti->init_srb + offsetof(struct srb_open_response, ret_code)); + open_error_code = ntohs(readw(ti->init_srb + offsetof(struct srb_open_response, error_code))); + prior_open_status = ti->open_status; + if (!open_ret_code) { + if (ti->open_status == AUTOREOPEN) { + DPRINTK("Adapter reopened.\n"); + ti->retry_count = TR_RETRIES; + } + writeb(~(SRB_RESP_INT), ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); + writeb(~(CMD_IN_SRB), ti->mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD); + open_sap(EXTENDED_SAP, dev); + /* YdW probably hates me */ + goto skip_reset; + } else if (open_ret_code == 7) { + if (ti->open_status == CLOSED || ti->retry_count == 0) { + /* Don't delay the operating system */ + ti->open_status = FAILURE; + DPRINTK("Token Ring Adapter Open failed with adapter error"); + printk(" code 0x%x, Sianara\n until ifconfig tr up\n", open_error_code); + } else { + if (open_error_code == 0x24) { + if (!ti->auto_ringspeedsave) { + DPRINTK("Open failed: Adapter speed must match ring " + "speed if Automatic Ring Speed Save is disabled.\n"); + ti->open_status = FAILURE; + } else { + DPRINTK("Retrying open to adjust to ring speed.\n"); + } + } else if (open_error_code == 0x2d) { + DPRINTK("Physical Insertion: No Monitor Detected,"); + printk(" retrying after 30s delay...\n"); + } else if (open_error_code == 0x11) { + DPRINTK("Lobe Media Function Failure (0x11), "); + printk("retrying after 30s delay...\n"); + } else { + DPRINTK("TR Adapter misc open failure, error code = "); + printk("0x%x, retrying after 30s delay...\n", open_error_code); + } + } + } /*if open_ret_code==7 */ + else { + if (ti->open_status == CLOSED || ti->retry_count == 0) + /* Don't delay the operating system */ + ti->open_status = FAILURE; + DPRINTK("open failed: ret_code = %02X..., ", open_ret_code); + } + if (ti->retry_count) + ti->retry_count--; + if (ti->open_status != FAILURE) { + ibmtr_reset_timer(&(ti->tr_timer), dev); + } else { + if (prior_open_status == CLOSED) + wake_up(&ti->wait_for_reset); + else + ti->retry_count = TR_RETRIES; + } + } /*case DIR_OPEN_ADAPTER */ + break; + case DIR_CLOSE_ADAPTER: wake_up(&ti->wait_for_tok_int); break; - - case DLC_OPEN_SAP: - if (readb(ti->srb+offsetof(struct dlc_open_sap, ret_code))) { - DPRINTK("open_sap failed: ret_code = %02X,retrying\n", - (int)readb(ti->srb+offsetof(struct dlc_open_sap, ret_code))); + case DLC_OPEN_SAP: + if (readb(ti->srb + offsetof(struct dlc_open_sap, ret_code))) { + DPRINTK("open_sap failed: ret_code = %02X,retrying\n", (int) readb(ti->srb + offsetof(struct dlc_open_sap, ret_code))); ibmtr_reset_timer(&(ti->tr_timer), dev); } else { - ti->exsap_station_id= - readw(ti->srb+offsetof(struct dlc_open_sap, station_id)); - ti->open_status=SUCCESS; /* TR adapter is now available */ - wake_up(&ti->wait_for_reset); + ti->exsap_station_id = readw(ti->srb + offsetof(struct dlc_open_sap, station_id)); + prior_open_status = ti->open_status; + ti->open_status = SUCCESS; /* TR adapter is now available */ + /*debugprintk("tok_interrupt: ti->open_status=SUCCESS\n"); */ + /*BMS I moved these two lines from tok_open so I don't have to sleep */ + dev->tbusy = 0; + dev->start = 1; + if (prior_open_status == CLOSED) + wake_up(&ti->wait_for_reset); } break; - - case DIR_INTERRUPT: - case DIR_MOD_OPEN_PARAMS: - case DIR_SET_GRP_ADDR: - case DIR_SET_FUNC_ADDR: - case DLC_CLOSE_SAP: - if (readb(ti->srb+offsetof(struct srb_interrupt, ret_code))) - DPRINTK("error on %02X: %02X\n", - (int)readb(ti->srb+offsetof(struct srb_interrupt, command)), - (int)readb(ti->srb+offsetof(struct srb_interrupt, ret_code))); + case DIR_INTERRUPT: + case DIR_MOD_OPEN_PARAMS: + case DIR_SET_GRP_ADDR: + case DIR_SET_FUNC_ADDR: + case DLC_CLOSE_SAP: + if (readb(ti->srb + offsetof(struct srb_interrupt, ret_code))) + DPRINTK("error on %02X: %02X\n", + (int) readb(ti->srb + offsetof(struct srb_interrupt, command)), + (int) readb(ti->srb + offsetof(struct srb_interrupt, ret_code))); break; - - case DIR_READ_LOG: - if (readb(ti->srb+offsetof(struct srb_read_log, ret_code))) - DPRINTK("error on dir_read_log: %02X\n", - (int)readb(ti->srb+offsetof(struct srb_read_log, ret_code))); - else - if (IBMTR_DEBUG_MESSAGES) { - DPRINTK( - "Line errors %02X, Internal errors %02X, Burst errors %02X\n" + case DIR_READ_LOG: + if (readb(ti->srb + offsetof(struct srb_read_log, ret_code))) + DPRINTK("error on dir_read_log: %02X\n", (int) readb(ti->srb + offsetof(struct srb_read_log, ret_code))); + else if (IBMTR_DEBUG_MESSAGES) { + DPRINTK("Line errors %02X, Internal errors %02X, Burst errors %02X\n" "A/C errors %02X, Abort delimiters %02X, Lost frames %02X\n" "Receive congestion count %02X, Frame copied errors %02X\n" "Frequency errors %02X, Token errors %02X\n", - (int)readb(ti->srb+offsetof(struct srb_read_log, - line_errors)), - (int)readb(ti->srb+offsetof(struct srb_read_log, - internal_errors)), - (int)readb(ti->srb+offsetof(struct srb_read_log, - burst_errors)), - (int)readb(ti->srb+offsetof(struct srb_read_log, A_C_errors)), - (int)readb(ti->srb+offsetof(struct srb_read_log, - abort_delimiters)), - (int)readb(ti->srb+offsetof(struct srb_read_log, - lost_frames)), - (int)readb(ti->srb+offsetof(struct srb_read_log, - recv_congest_count)), - (int)readb(ti->srb+offsetof(struct srb_read_log, - frame_copied_errors)), - (int)readb(ti->srb+offsetof(struct srb_read_log, - frequency_errors)), - (int)readb(ti->srb+offsetof(struct srb_read_log, - token_errors))); - } - dev->tbusy=0; + (int) readb(ti->srb + offsetof(struct srb_read_log, line_errors)), + (int) readb(ti->srb + offsetof(struct srb_read_log, internal_errors)), + (int) readb(ti->srb + offsetof(struct srb_read_log, burst_errors)), + (int) readb(ti->srb + offsetof(struct srb_read_log, A_C_errors)), + (int) readb(ti->srb + offsetof(struct srb_read_log, abort_delimiters)), + (int) readb(ti->srb + offsetof(struct srb_read_log, lost_frames)), + (int) readb(ti->srb + offsetof(struct srb_read_log, recv_congest_count)), + (int) readb(ti->srb + offsetof(struct srb_read_log, frame_copied_errors)), + (int) readb(ti->srb + offsetof(struct srb_read_log, frequency_errors)), + (int) readb(ti->srb + offsetof(struct srb_read_log, token_errors))); + } + dev->tbusy = 0; break; - - default: - DPRINTK("Unknown command %02X encountered\n", - (int)readb(ti->srb)); - - } /* SRB command check */ - + default: + DPRINTK("Unknown command %02X encountered\n", (int) readb(ti->srb)); + } /* end switch SRB command check */ writeb(~CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD); writeb(~SRB_RESP_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); - - skip_reset: - } /* SRB response */ - - if (status & ASB_FREE_INT) { /* ASB response */ - SET_PAGE(ti->asb_page); + skip_reset: + } /* if SRB response */ + if (status & ASB_FREE_INT) { /* ASB response */ + SET_PAGE(ti->asb_page); #if TR_VERBOSE - DPRINTK("ASB resp: cmd=%02X\n", readb(ti->asb)); + DPRINTK("ASB resp: cmd=%02X\n", readb(ti->asb)); #endif - switch(readb(ti->asb)) { /* ASB command check */ - - case REC_DATA: - case XMIT_UI_FRAME: - case XMIT_DIR_FRAME: + switch (readb(ti->asb)) { /* ASB command check */ + case REC_DATA: + case XMIT_UI_FRAME: + case XMIT_DIR_FRAME: break; - - default: - DPRINTK("unknown command in asb %02X\n", - (int)readb(ti->asb)); - - } /* ASB command check */ - - if (readb(ti->asb+2)!=0xff) /* checks ret_code */ - DPRINTK("ASB error %02X in cmd %02X\n", - (int)readb(ti->asb+2),(int)readb(ti->asb)); + default: + DPRINTK("unknown command in asb %02X\n", (int) readb(ti->asb)); + } /* switch ASB command check */ + if (readb(ti->asb + 2) != 0xff) /* checks ret_code */ + DPRINTK("ASB error %02X in cmd %02X\n", (int) readb(ti->asb + 2), (int) readb(ti->asb)); writeb(~ASB_FREE_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); - - } /* ASB response */ - - if (status & ARB_CMD_INT) { /* ARB response */ - SET_PAGE(ti->arb_page); -#if TR_VERBOSE - DPRINTK("ARB resp: cmd=%02X rsp=%02X\n", - readb(ti->arb), - readb(ti->arb + offsetof(struct arb_dlc_status, status))); + } /* if ASB response */ + if (status & ARB_CMD_INT) { /* ARB response */ + SET_PAGE(ti->arb_page); +#if TR_VERBOSE + DPRINTK("ARB resp: cmd=%02X\n", readb(ti->arb)); #endif - switch (readb(ti->arb)) { /* ARB command check */ - - case DLC_STATUS: + switch (readb(ti->arb)) { /* ARB command check */ + case DLC_STATUS: DPRINTK("DLC_STATUS new status: %02X on station %02X\n", ntohs(readw(ti->arb + offsetof(struct arb_dlc_status, status))), - ntohs(readw(ti->arb - +offsetof(struct arb_dlc_status, station_id)))); + ntohs(readw(ti->arb + offsetof(struct arb_dlc_status, station_id)))); break; - - case REC_DATA: + case REC_DATA: tr_rx(dev); break; - - case RING_STAT_CHANGE: { - unsigned short ring_status; - - ring_status=ntohs(readw(ti->arb - +offsetof(struct arb_ring_stat_change, ring_status))); - - if (ring_status & (SIGNAL_LOSS | LOBE_FAULT)) { - - DPRINTK("Signal loss/Lobe fault\n"); - DPRINTK("We try to reopen the adapter.\n"); - ibmtr_reset_timer(&(ti->tr_timer), dev); - } else if (ring_status & (HARD_ERROR | XMIT_BEACON - | AUTO_REMOVAL | REMOVE_RECV | RING_RECOVER)) - DPRINTK("New ring status: %02X\n", ring_status); - - if (ring_status & LOG_OVERFLOW) { - if (dev->tbusy) - ti->readlog_pending = 1; - else - ibmtr_readlog(dev); - } - } - break; - - case XMIT_DATA_REQ: + case RING_STAT_CHANGE:{ + unsigned short ring_status; + ring_status = ntohs(readw(ti->arb + offsetof(struct arb_ring_stat_change, ring_status))); + if (ibmtr_debug_trace & TRC_INIT) + DPRINTK("Ring Status Change...(0x%x)\n", ring_status); + if (ring_status & (REMOVE_RECV | AUTO_REMOVAL | LOBE_FAULT)) { + DPRINTK("Remove received, or Auto-removal error, or Lobe fault\n"); + DPRINTK("We'll try to reopen the closed adapter after "); + printk("a 30 second delay.\n"); + /*we give this hint for tok_close; he need not do another close */ + /*BMS the following "if" could probably be replaced with "if 1" */ + /*BMS I was confused because I saw the ibmtr keep reopening but */ + /*BMS I forgot that with an RJ45 plugged into an RJ45/ICS adapter */ + /*BMS but that adapter not in the ring, the TR will successfully */ + /*BMS open, and then shortly afterwards close and come here. */ + if (ti->open_status != AUTOREOPEN) { + ti->open_status = AUTOREOPEN; + ibmtr_reset_timer(&(ti->tr_timer), dev); + } + } else { + if (ring_status & LOG_OVERFLOW) { + if (dev->tbusy) + ti->readlog_pending = 1; + else + ibmtr_readlog(dev); + } + } + } + break; + case XMIT_DATA_REQ: tr_tx(dev); break; - - default: - DPRINTK("Unknown command %02X in arb\n", - (int)readb(ti->arb)); + default: + DPRINTK("Unknown command %02X in arb\n", (int) readb(ti->arb)); break; - - } /* ARB command check */ - + } /* switch ARB command check */ writeb(~ARB_CMD_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); writeb(ARB_FREE, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - - } /* ARB response */ - - if (status & SSB_RESP_INT) { /* SSB response */ + } /* if ARB response */ + if (status & SSB_RESP_INT) { /* SSB response */ unsigned char retcode; - SET_PAGE(ti->ssb_page); + SET_PAGE(ti->ssb_page); #if TR_VERBOSE - DPRINTK("SSB resp: cmd=%02X rsp=%02X\n", - readb(ti->ssb), readb(ti->ssb+2)); + DPRINTK("SSB resp: cmd=%02X rsp=%02X\n", readb(ti->ssb), readb(ti->ssb + 2)); #endif - switch (readb(ti->ssb)) { /* SSB command check */ - - case XMIT_DIR_FRAME: - case XMIT_UI_FRAME: - retcode = readb(ti->ssb+2); - if (retcode && (retcode != 0x22)) /* checks ret_code */ - DPRINTK("xmit ret_code: %02X xmit error code: %02X\n", - (int)retcode, (int)readb(ti->ssb+6)); - else ti->tr_stats.tx_packets++; - break; - case XMIT_XID_CMD: - DPRINTK("xmit xid ret_code: %02X\n", (int)readb(ti->ssb+2)); + switch (readb(ti->ssb)) { /* SSB command check */ + case XMIT_DIR_FRAME: + case XMIT_UI_FRAME: + retcode = readb(ti->ssb + 2); + if (retcode && (retcode != 0x22)) /* checks ret_code */ + DPRINTK("xmit ret_code: %02X xmit error code: %02X\n", (int) retcode, (int) readb(ti->ssb + 6)); + else + ti->tr_stats.tx_packets++; break; - - default: - DPRINTK("Unknown command %02X in ssb\n", (int)readb(ti->ssb)); - - } /* SSB command check */ - + case XMIT_XID_CMD: + DPRINTK("xmit xid ret_code: %02X\n", (int) readb(ti->ssb + 2)); + default: + DPRINTK("Unknown command %02X in ssb\n", (int) readb(ti->ssb)); + } /* SSB command check */ writeb(~SSB_RESP_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); writeb(SSB_FREE, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - - } /* SSB response */ - - } /* SRB, ARB, ASB or SSB response */ - - dev->interrupt=0; + } /* if SSB response */ + } /* if SRB, ARB, ASB or SSB response */ + dev->interrupt = 0; writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); break; - - case FIRST_INT: + case FIRST_INT: initial_tok_int(dev); break; - - default: + default: DPRINTK("Unexpected interrupt from tr adapter\n"); - } -#ifdef PCMCIA - return_point: -#endif #ifdef ENABLE_PAGING - writeb(save_srpr, ti->mmio+ACA_OFFSET+ACA_RW+SRPR_EVEN); + writeb(save_srpr, ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN); #endif + spin_unlock(&(ti->lock)); -} +} /*tok_interrupt */ + +/*****************************************************************************/ static void initial_tok_int(struct device *dev) { @@ -1349,268 +1363,118 @@ static void initial_tok_int(struct device *dev) __u32 encoded_addr; __u32 hw_encoded_addr; struct tok_info *ti; - ti=(struct tok_info *) dev->priv; - - ti->do_tok_int=NOT_FIRST; + ti = (struct tok_info *) dev->priv; -#ifndef TR_NEWFORMAT - DPRINTK("Initial tok int received\n"); -#endif + ti->do_tok_int = NOT_FIRST; /* we assign the shared-ram address for ISA devices */ - if(!ti->sram) { - writeb(ti->sram_base, ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN); - ti->sram=((__u32)ti->sram_base << 12); - } - ti->init_srb=ntohs((unsigned short)readw(ti->mmio+ ACA_OFFSET + WRBR_EVEN)); + writeb(ti->sram_base, ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN); +#ifndef PCMCIA + ti->sram_virt=((__u32)ti->sram_base << 12); +#endif + ti->init_srb = ntohs((unsigned short) readw(ti->mmio + ACA_OFFSET + WRBR_EVEN)); if (ti->page_mask) { - ti->init_srb_page=(ti->init_srb>>8)&ti->page_mask; - ti->init_srb &= ~(ti->page_mask<<8); + ti->init_srb_page = (ti->init_srb >> 8) & ti->page_mask; + ti->init_srb &= ~(ti->page_mask << 8); + } + ti->init_srb += ti->sram_virt; + if (ti->page_mask && ti->avail_shared_ram == 127) { + int last_512 = 0xfe00, i; + int last_512_page=0; + last_512_page=(last_512>>8)&ti->page_mask; + last_512 &= ~(ti->page_mask << 8); + /* initialize high section of ram (if necessary) */ + SET_PAGE(last_512_page); + for (i = 0; i < 512; i++) + writeb(0, ti->sram_virt + last_512 + i); } - ti->init_srb+=ti->sram; - - if (ti->avail_shared_ram == 127) { - int i; - int last_512=0xfe00; - if (ti->page_mask) { - last_512 &= ~(ti->page_mask<<8); - } - // initialize high section of ram (if necessary) - SET_PAGE(0xc0); - for (i=0; i<512; i++) { - writeb(0,ti->sram+last_512+i); - } - } SET_PAGE(ti->init_srb_page); - - dev->mem_start = ti->sram; - dev->mem_end = ti->sram + (ti->mapped_ram_size<<9) - 1; - + dev->mem_start = ti->sram_base << 12; + dev->mem_end = dev->mem_start + (ti->mapped_ram_size << 9) - 1; #if TR_VERBOSE { int i; - DPRINTK("init_srb(%lx):", (long)ti->init_srb); - for (i=0;i<17;i++) printk("%02X ", (int)readb(ti->init_srb+i)); + DPRINTK("ti->init_srb_page=0x%x\n", ti->init_srb_page); + DPRINTK("init_srb(%p):", ti->init_srb); + for (i = 0; i < 20; i++) + printk("%02X ", (int) readb(ti->init_srb + i)); printk("\n"); } #endif + hw_encoded_addr = readw(ti->init_srb + offsetof(struct srb_init_response, encoded_address)); + encoded_addr = ntohs(hw_encoded_addr); + ti->ring_speed = readb(ti->init_srb + offsetof(struct srb_init_response, init_status)) & 0x01 ? 16 : 4; + DPRINTK("Initial interrupt : %d Mbps, shared RAM base %08x.\n", ti->ring_speed, (unsigned int)dev->mem_start); + ti->auto_ringspeedsave = readb(ti->init_srb + offsetof(struct srb_init_response, init_status_2)) & 0x4 ? TRUE : FALSE; + wake_up(&ti->wait_for_reset); +} /*initial_tok_int() */ - hw_encoded_addr = readw(ti->init_srb - + offsetof(struct srb_init_response, encoded_address)); - -#if !TR_NEWFORMAT - DPRINTK("srb_init_response->encoded_address: %04X\n", hw_encoded_addr); - DPRINTK("ntohs(srb_init_response->encoded_address): %04X\n", - ntohs(hw_encoded_addr)); -#endif - - encoded_addr=(ti->sram + ntohs(hw_encoded_addr)); - ti->ring_speed = readb(ti->init_srb+offsetof(struct srb_init_response, init_status)) & 0x01 ? 16 : 4; -#if !TR_NEWFORMAT - DPRINTK("encoded addr (%04X,%04X,%08X): ", hw_encoded_addr, - ntohs(hw_encoded_addr), encoded_addr); -#else - DPRINTK("Initial interrupt : %d Mbps, shared RAM base %08x.\n", - ti->ring_speed, ti->sram); -#endif - - ti->auto_ringspeedsave=readb(ti->init_srb - +offsetof(struct srb_init_response, init_status_2)) & 0x4 ? TRUE : FALSE; - -#if !TR_NEWFORMAT - for(i=0;idev_addr[i]=readb(encoded_addr + i); - printk("%02X%s", dev->dev_addr[i], (i==TR_ALEN-1) ? "" : ":" ); - } - printk("\n"); -#endif - - tok_open_adapter((unsigned long)dev); -} - -static int tok_init_card(struct device *dev) -{ - struct tok_info *ti; - short PIOaddr; - unsigned long i; - PIOaddr = dev->base_addr; - ti=(struct tok_info *) dev->priv; - - /* Special processing for first interrupt after reset */ - ti->do_tok_int=FIRST_INT; - - /* Reset adapter */ - dev->tbusy=1; /* nothing can be done before reset and open completed */ - - - writeb(~INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_EVEN); - -#if !TR_NEWFORMAT - DPRINTK("resetting card\n"); -#endif - - outb(0, PIOaddr+ADAPTRESET); - for (i=jiffies+TR_RESET_INTERVAL; time_before_eq(jiffies, i);); /* wait 50ms */ - outb(0,PIOaddr+ADAPTRESETREL); -#ifdef ENABLE_PAGING - if(ti->page_mask) - writeb(SRPR_ENABLE_PAGING, ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN); -#endif - -#if !TR_NEWFORMAT - DPRINTK("card reset\n"); -#endif - - ti->open_status=IN_PROGRESS; - writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); - return 0; -} - -static void open_sap(unsigned char type,struct device *dev) -{ - int i; - struct tok_info *ti=(struct tok_info *) dev->priv; - - SET_PAGE(ti->srb_page); - for (i=0; isrb+i); - - writeb(DLC_OPEN_SAP, ti->srb + offsetof(struct dlc_open_sap, command)); - writew(htons(MAX_I_FIELD), - ti->srb + offsetof(struct dlc_open_sap, max_i_field)); - writeb(SAP_OPEN_IND_SAP | SAP_OPEN_PRIORITY, - ti->srb + offsetof(struct dlc_open_sap, sap_options)); - writeb(SAP_OPEN_STATION_CNT, - ti->srb + offsetof(struct dlc_open_sap, station_count)); - writeb(type, ti->srb + offsetof(struct dlc_open_sap, sap_value)); - - writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - -} - -void tok_open_adapter(unsigned long dev_addr) -{ - - struct device *dev=(struct device *)dev_addr; - struct tok_info *ti; - int i; - - ti=(struct tok_info *) dev->priv; - -#if !TR_NEWFORMAT - DPRINTK("now opening the board...\n"); -#endif - - writeb(~SRB_RESP_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD); - writeb(~CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_RESET + ISRA_ODD); - - for (i=0; iinit_srb+i); - - writeb(DIR_OPEN_ADAPTER, - ti->init_srb + offsetof(struct dir_open_adapter, command)); - writew(htons(OPEN_PASS_BCON_MAC), - ti->init_srb + offsetof(struct dir_open_adapter, open_options)); - if (ti->ring_speed == 16) { - writew(htons(ti->dhb_size16mb), - ti->init_srb + offsetof(struct dir_open_adapter, dhb_length)); - writew(htons(ti->rbuf_cnt16), - ti->init_srb + offsetof(struct dir_open_adapter, num_rcv_buf)); - writew(htons(ti->rbuf_len16), - ti->init_srb + offsetof(struct dir_open_adapter, rcv_buf_len)); - } else { - writew(htons(ti->dhb_size4mb), - ti->init_srb + offsetof(struct dir_open_adapter, dhb_length)); - writew(htons(ti->rbuf_cnt4), - ti->init_srb + offsetof(struct dir_open_adapter, num_rcv_buf)); - writew(htons(ti->rbuf_len4), - ti->init_srb + offsetof(struct dir_open_adapter, rcv_buf_len)); - } - writeb(NUM_DHB, /* always 2 */ - ti->init_srb + offsetof(struct dir_open_adapter, num_dhb)); - writeb(DLC_MAX_SAP, - ti->init_srb + offsetof(struct dir_open_adapter, dlc_max_sap)); - writeb(DLC_MAX_STA, - ti->init_srb + offsetof(struct dir_open_adapter, dlc_max_sta)); - - ti->srb=ti->init_srb; /* We use this one in the interrupt handler */ - ti->srb_page=ti->init_srb_page; - DPRINTK("Opend adapter: Xmit bfrs: %d X %d, Rcv bfrs: %d X %d\n", - readb(ti->init_srb+offsetof(struct dir_open_adapter,num_dhb)), - ntohs(readw(ti->init_srb+offsetof(struct dir_open_adapter,dhb_length))), - ntohs(readw(ti->init_srb+offsetof(struct dir_open_adapter,num_rcv_buf))), - ntohs(readw(ti->init_srb+offsetof(struct dir_open_adapter,rcv_buf_len))) ); - - writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); - writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - -} +/*****************************************************************************/ static void tr_tx(struct device *dev) { - struct tok_info *ti=(struct tok_info *) dev->priv; - struct trh_hdr *trhdr=(struct trh_hdr *)ti->current_skb->data; + struct tok_info *ti = (struct tok_info *) dev->priv; + struct trh_hdr *trhdr = (struct trh_hdr *) ti->current_skb->data; unsigned int hdr_len; - __u32 dhb; + __u32 dhb=0,dhb_base; unsigned char xmit_command; - int i; - struct trllc *llc; - struct srb_xmit xsrb; - __u8 dhb_page=0; - __u8 llc_ssap; - + int i,dhb_len=0x4000,src_len,src_offset; + struct trllc *llc; + struct srb_xmit xsrb; + __u8 dhb_page = 0; + __u8 llc_ssap; + SET_PAGE(ti->asb_page); - if (readb(ti->asb + offsetof(struct asb_xmit_resp, ret_code))!=0xFF) - DPRINTK("ASB not free !!!\n"); + if (readb(ti->asb + offsetof(struct asb_xmit_resp, ret_code)) != 0xFF) + DPRINTK("ASB not free !!!\n"); /* in providing the transmit interrupts, is telling us it is ready for data and providing a shared memory address for us to stuff with data. Here we compute the - effective address where we will place data.*/ - SET_PAGE(ti->arb_page); - dhb=ntohs(readw(ti->arb + offsetof(struct arb_xmit_req, dhb_address))); - if (ti->page_mask) { - dhb_page=(dhb >> 8) & ti->page_mask; - dhb &= ~(ti->page_mask << 8); - } - dhb+=ti->sram; - + effective address where we will place data. */ + SET_PAGE(ti->arb_page); + dhb=dhb_base=ntohs(readw(ti->arb + offsetof(struct arb_xmit_req, dhb_address))); + if (ti->page_mask) { + dhb_page = (dhb_base >> 8) & ti->page_mask; + dhb=dhb_base & ~(ti->page_mask << 8); + } + dhb += ti->sram_virt; + /* Figure out the size of the 802.5 header */ - if (!(trhdr->saddr[0] & 0x80)) /* RIF present? */ - hdr_len=sizeof(struct trh_hdr)-TR_MAXRIFLEN; - else - hdr_len=((ntohs(trhdr->rcf) & TR_RCF_LEN_MASK)>>8) - +sizeof(struct trh_hdr)-TR_MAXRIFLEN; + if (!(trhdr->saddr[0] & 0x80)) /* RIF present? */ + hdr_len = sizeof(struct trh_hdr) - TR_MAXRIFLEN; + else + hdr_len = ((ntohs(trhdr->rcf) & TR_RCF_LEN_MASK) >> 8) + + sizeof(struct trh_hdr) - TR_MAXRIFLEN; - llc = (struct trllc *)(ti->current_skb->data + hdr_len); + llc = (struct trllc *) (ti->current_skb->data + hdr_len); - llc_ssap=llc->ssap; - SET_PAGE(ti->srb_page); - memcpy_fromio(&xsrb, ti->srb, sizeof(xsrb)); - SET_PAGE(ti->asb_page); - xmit_command=xsrb.command; + llc_ssap = llc->ssap; + SET_PAGE(ti->srb_page); + memcpy_fromio(&xsrb, ti->srb, sizeof(xsrb)); + SET_PAGE(ti->asb_page); + xmit_command = xsrb.command; writeb(xmit_command, ti->asb + offsetof(struct asb_xmit_resp, command)); - writew(xsrb.station_id, - ti->asb + offsetof(struct asb_xmit_resp, station_id)); + writew(xsrb.station_id, ti->asb + offsetof(struct asb_xmit_resp, station_id)); writeb(llc_ssap, ti->asb + offsetof(struct asb_xmit_resp, rsap_value)); - writeb(xsrb.cmd_corr, - ti->asb + offsetof(struct asb_xmit_resp, cmd_corr)); + writeb(xsrb.cmd_corr, ti->asb + offsetof(struct asb_xmit_resp, cmd_corr)); writeb(0, ti->asb + offsetof(struct asb_xmit_resp, ret_code)); - if ((xmit_command==XMIT_XID_CMD) || (xmit_command==XMIT_TEST_CMD)) { + if ((xmit_command == XMIT_XID_CMD) || (xmit_command == XMIT_TEST_CMD)) { - writew(htons(0x11), - ti->asb + offsetof(struct asb_xmit_resp, frame_length)); + writew(htons(0x11), ti->asb + offsetof(struct asb_xmit_resp, frame_length)); writeb(0x0e, ti->asb + offsetof(struct asb_xmit_resp, hdr_length)); SET_PAGE(dhb_page); writeb(AC, dhb); - writeb(LLC_FRAME, dhb+1); + writeb(LLC_FRAME, dhb + 1); - for (i=0; immio + ACA_OFFSET + ACA_SET + ISRA_ODD); return; @@ -1622,80 +1486,102 @@ static void tr_tx(struct device *dev) * buffer identified in the command data received with the interrupt. */ writeb(hdr_len, ti->asb + offsetof(struct asb_xmit_resp, hdr_length)); - writew(htons(ti->current_skb->len), - ti->asb + offsetof(struct asb_xmit_resp, frame_length)); + writew(htons(ti->current_skb->len), ti->asb + offsetof(struct asb_xmit_resp, frame_length)); + + src_len=ti->current_skb->len; + src_offset=0; + dhb=dhb_base; + while(1) { + if (ti->page_mask) { + dhb_page=(dhb >> 8) & ti->page_mask; + dhb=dhb & ~(ti->page_mask << 8); + dhb_len=0x4000-dhb; /* remaining size of this page */ + } + dhb+=ti->sram_virt; + SET_PAGE(dhb_page); + if (src_len > dhb_len) { + memcpy_toio(dhb, &ti->current_skb->data[src_offset], dhb_len); + src_len -= dhb_len; + src_offset += dhb_len; + dhb_base+=dhb_len; + dhb=dhb_base; + } else { + memcpy_toio(dhb, &ti->current_skb->data[src_offset], src_len); + break; + } + } - memcpy_toio(dhb, ti->current_skb->data, ti->current_skb->len); writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - ti->tr_stats.tx_bytes+=ti->current_skb->len; - dev->tbusy=0; + ti->tr_stats.tx_bytes += ti->current_skb->len; + dev->tbusy = 0; dev_kfree_skb(ti->current_skb); - ti->current_skb=NULL; + ti->current_skb = NULL; mark_bh(NET_BH); - if (ti->readlog_pending) ibmtr_readlog(dev); -} + if (ti->readlog_pending) + ibmtr_readlog(dev); +} /*tr_tx */ + +/*****************************************************************************/ static void tr_rx(struct device *dev) { - struct tok_info *ti=(struct tok_info *) dev->priv; + struct tok_info *ti = (struct tok_info *) dev->priv; __u32 rbuffer, rbufdata; - __u8 rbuffer_page=0; + __u8 rbuffer_page = 0; __u32 llc; unsigned char *data; unsigned int rbuffer_len, lan_hdr_len, hdr_len, ip_len, length; + unsigned char dlc_hdr_len; struct sk_buff *skb; unsigned int skb_size = 0; - int IPv4_p = 0; + int IPv4_p = 0; unsigned int chksum = 0; struct iphdr *iph; struct arb_rec_req rarb; SET_PAGE(ti->arb_page); - memcpy_fromio(&rarb, ti->arb, sizeof(rarb)); - rbuffer=ntohs(rarb.rec_buf_addr)+2; + memcpy_fromio(&rarb, ti->arb, sizeof(rarb)); + rbuffer = ntohs(rarb.rec_buf_addr) + 2; if (ti->page_mask) { - rbuffer_page=(rbuffer >> 8) & ti->page_mask; - rbuffer &= ~(ti->page_mask<<8); + rbuffer_page = (rbuffer >> 8) & ti->page_mask; + rbuffer &= ~(ti->page_mask << 8); } - rbuffer += ti->sram; - + rbuffer += ti->sram_virt; + SET_PAGE(ti->asb_page); - - if(readb(ti->asb + offsetof(struct asb_rec, ret_code))!=0xFF) - DPRINTK("ASB not free !!!\n"); - - writeb(REC_DATA, - ti->asb + offsetof(struct asb_rec, command)); - writew(rarb.station_id, - ti->asb + offsetof(struct asb_rec, station_id)); - writew(rarb.rec_buf_addr, - ti->asb + offsetof(struct asb_rec, rec_buf_addr)); - - lan_hdr_len=rarb.lan_hdr_len; + + if (readb(ti->asb + offsetof(struct asb_rec, ret_code)) != 0xFF) + DPRINTK("ASB not free !!!\n"); + + writeb(REC_DATA, ti->asb + offsetof(struct asb_rec, command)); + writew(rarb.station_id, ti->asb + offsetof(struct asb_rec, station_id)); + writew(rarb.rec_buf_addr, ti->asb + offsetof(struct asb_rec, rec_buf_addr)); + + lan_hdr_len = rarb.lan_hdr_len; + if (lan_hdr_len > sizeof(struct trh_hdr)) { + DPRINTK("Linux cannot handle greater than 18 bytes RIF\n"); + return; + } /*BMS I added this above just to be very safe */ + dlc_hdr_len = readb(ti->arb + offsetof(struct arb_rec_req, dlc_hdr_len)); hdr_len = lan_hdr_len + sizeof(struct trllc) + sizeof(struct iphdr); - + SET_PAGE(rbuffer_page); - llc=(rbuffer + offsetof(struct rec_buf, data) + lan_hdr_len); + llc = (rbuffer + offsetof(struct rec_buf, data) + lan_hdr_len); #if TR_VERBOSE - DPRINTK("offsetof data: %02X lan_hdr_len: %02X\n", - (unsigned int)offsetof(struct rec_buf,data), (unsigned int)lan_hdr_len); - DPRINTK("llc: %08X rec_buf_addr: %04X ti->sram: %lx\n", llc, - ntohs(rarb.rec_buf_addr), - (long)ti->sram); + DPRINTK("offsetof data: %02X lan_hdr_len: %02X\n", (unsigned int) offsetof(struct rec_buf, data), (unsigned int) lan_hdr_len); + DPRINTK("llc: %08X rec_buf_addr: %04X dev->mem_start: %p\n", llc, ntohs(rarb.rec_buf_addr), dev->mem_start); DPRINTK("dsap: %02X, ssap: %02X, llc: %02X, protid: %02X%02X%02X, " "ethertype: %04X\n", - (int)readb(llc + offsetof(struct trllc, dsap)), - (int)readb(llc + offsetof(struct trllc, ssap)), - (int)readb(llc + offsetof(struct trllc, llc)), - (int)readb(llc + offsetof(struct trllc, protid)), - (int)readb(llc + offsetof(struct trllc, protid)+1), - (int)readb(llc + offsetof(struct trllc, protid)+2), - (int)readw(llc + offsetof(struct trllc, ethertype))); + (int) readb(llc + offsetof(struct trllc, dsap)), + (int) readb(llc + offsetof(struct trllc, ssap)), + (int) readb(llc + offsetof(struct trllc, llc)), + (int) readb(llc + offsetof(struct trllc, protid)), + (int) readb(llc + offsetof(struct trllc, protid) + 1), (int) readb(llc + offsetof(struct trllc, protid) + 2), (int) readw(llc + offsetof(struct trllc, ethertype))); #endif - if (readb(llc + offsetof(struct trllc, llc))!=UI_CMD) { - SET_PAGE(ti->asb_page); + if (readb(llc + offsetof(struct trllc, llc)) != UI_CMD) { + SET_PAGE(ti->asb_page); writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code)); ti->tr_stats.rx_dropped++; writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); @@ -1703,62 +1589,60 @@ static void tr_rx(struct device *dev) } length = ntohs(rarb.frame_len); - if ((readb(llc + offsetof(struct trllc, dsap))==EXTENDED_SAP) && - (readb(llc + offsetof(struct trllc, ssap))==EXTENDED_SAP) && - (length>=hdr_len)) { - IPv4_p = 1; - } - + if ((readb(llc + offsetof(struct trllc, dsap)) == EXTENDED_SAP) && (readb(llc + offsetof(struct trllc, ssap)) == EXTENDED_SAP) && (length >= hdr_len)) { + IPv4_p = 1; + } #if TR_VERBOSE - if (!IPv4_p){ - - __u32 trhhdr; - - trhhdr=(rbuffer+offsetof(struct rec_buf,data)); - - DPRINTK("Probably non-IP frame received.\n"); - DPRINTK("ssap: %02X dsap: %02X saddr: %02X:%02X:%02X:%02X:%02X:%02X " - "daddr: %02X:%02X:%02X:%02X:%02X:%02X\n", - (int)readb(llc + offsetof(struct trllc, ssap)), - (int)readb(llc + offsetof(struct trllc, dsap)), - (int)readb(trhhdr + offsetof(struct trh_hdr, saddr)), - (int)readb(trhhdr + offsetof(struct trh_hdr, saddr)+1), - (int)readb(trhhdr + offsetof(struct trh_hdr, saddr)+2), - (int)readb(trhhdr + offsetof(struct trh_hdr, saddr)+3), - (int)readb(trhhdr + offsetof(struct trh_hdr, saddr)+4), - (int)readb(trhhdr + offsetof(struct trh_hdr, saddr)+5), - (int)readb(trhhdr + offsetof(struct trh_hdr, daddr)), - (int)readb(trhhdr + offsetof(struct trh_hdr, daddr)+1), - (int)readb(trhhdr + offsetof(struct trh_hdr, daddr)+2), - (int)readb(trhhdr + offsetof(struct trh_hdr, daddr)+3), - (int)readb(trhhdr + offsetof(struct trh_hdr, daddr)+4), - (int)readb(trhhdr + offsetof(struct trh_hdr, daddr)+5)); - } + if (!IPv4_p) { + + __u32 trhhdr; + + trhhdr = (rbuffer + offsetof(struct rec_buf, data)); + + DPRINTK("Probably non-IP frame received.\n"); + DPRINTK("ssap: %02X dsap: %02X saddr: %02X:%02X:%02X:%02X:%02X:%02X " + "daddr: %02X:%02X:%02X:%02X:%02X:%02X\n", + (int) readb(llc + offsetof(struct trllc, ssap)), + (int) readb(llc + offsetof(struct trllc, dsap)), + (int) readb(trhhdr + offsetof(struct trh_hdr, saddr)), + (int) readb(trhhdr + offsetof(struct trh_hdr, saddr) + 1), + (int) readb(trhhdr + offsetof(struct trh_hdr, saddr) + 2), + (int) readb(trhhdr + offsetof(struct trh_hdr, saddr) + 3), + (int) readb(trhhdr + offsetof(struct trh_hdr, saddr) + 4), + (int) readb(trhhdr + offsetof(struct trh_hdr, saddr) + 5), + (int) readb(trhhdr + offsetof(struct trh_hdr, daddr)), + (int) readb(trhhdr + offsetof(struct trh_hdr, daddr) + 1), + (int) readb(trhhdr + offsetof(struct trh_hdr, daddr) + 2), + (int) readb(trhhdr + offsetof(struct trh_hdr, daddr) + 3), + (int) readb(trhhdr + offsetof(struct trh_hdr, daddr) + 4), (int) readb(trhhdr + offsetof(struct trh_hdr, daddr) + 5)); + } #endif - skb_size = length; - - if (!(skb=dev_alloc_skb(skb_size))) { - DPRINTK("out of memory. frame dropped.\n"); - ti->tr_stats.rx_dropped++; - writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code)); - writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - return; - } - - skb_put(skb, length); - skb_reserve(skb, sizeof(struct trh_hdr)-lan_hdr_len+sizeof(struct trllc)); - skb->dev=dev; - data=skb->data; - rbuffer_len=ntohs(readw(rbuffer + offsetof(struct rec_buf, buf_len))); - rbufdata = rbuffer + offsetof(struct rec_buf,data); + /*BMS handle the case she comes in with few hops but leaves with many */ + skb_size=length-lan_hdr_len+sizeof(struct trh_hdr)+sizeof(struct trllc); + + if (!(skb = dev_alloc_skb(skb_size))) { + DPRINTK("out of memory. frame dropped.\n"); + ti->tr_stats.rx_dropped++; + SET_PAGE(ti->asb_page); + writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code)); + writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); + return; + } + /*BMS again, if she comes in with few but leaves with many */ + skb_reserve(skb, sizeof(struct trh_hdr) - lan_hdr_len); + skb_put(skb, length); + skb->dev = dev; + data = skb->data; + rbuffer_len = ntohs(readw(rbuffer + offsetof(struct rec_buf, buf_len))); + rbufdata = rbuffer + offsetof(struct rec_buf, data); if (IPv4_p) { - /* Copy the headers without checksumming */ + /* Copy the headers without checksumming */ memcpy_fromio(data, rbufdata, hdr_len); /* Watch for padded packets and bogons */ - iph=(struct iphdr*)(data + lan_hdr_len + sizeof(struct trllc)); + iph = (struct iphdr *) (data + lan_hdr_len + sizeof(struct trllc)); ip_len = ntohs(iph->tot_len) - sizeof(struct iphdr); length -= hdr_len; if ((ip_len <= length) && (ip_len > 7)) @@ -1766,14 +1650,14 @@ static void tr_rx(struct device *dev) data += hdr_len; rbuffer_len -= hdr_len; rbufdata += hdr_len; - } + } /* Copy the payload... */ for (;;) { - if (IPv4_p) - chksum = csum_partial_copy(bus_to_virt(rbufdata), data, - length < rbuffer_len ? length : rbuffer_len, - chksum); + if (ibmtr_debug_trace && length < rbuffer_len) + DPRINTK("CURIOUS, length=%d < rbuffer_len=%d\n",length,rbuffer_len); + /*BMS*/ if (IPv4_p) + chksum = csum_partial_copy(bus_to_virt(rbufdata), data, length < rbuffer_len ? length : rbuffer_len, chksum); else memcpy_fromio(data, rbufdata, rbuffer_len); rbuffer = ntohs(readw(rbuffer)); @@ -1782,105 +1666,79 @@ static void tr_rx(struct device *dev) length -= rbuffer_len; data += rbuffer_len; if (ti->page_mask) { - rbuffer_page=(rbuffer>>8) & ti->page_mask; - rbuffer &= ~(ti->page_mask << 8); + rbuffer_page = (rbuffer >> 8) & ti->page_mask; + rbuffer &= ~(ti->page_mask << 8); } - rbuffer += ti->sram; + rbuffer += ti->sram_virt; SET_PAGE(rbuffer_page); rbuffer_len = ntohs(readw(rbuffer + offsetof(struct rec_buf, buf_len))); rbufdata = rbuffer + offsetof(struct rec_buf, data); } SET_PAGE(ti->asb_page); - writeb(0, ti->asb + offsetof(struct asb_rec, ret_code)); + writeb(0, ti->asb + offsetof(struct asb_rec, ret_code)); - writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); + writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); ti->tr_stats.rx_bytes += skb->len; - ti->tr_stats.rx_packets++; + ti->tr_stats.rx_packets++; - skb->protocol = tr_type_trans(skb,dev); - if (IPv4_p){ - skb->csum = chksum; + skb->protocol = tr_type_trans(skb, dev); + if (IPv4_p) { + skb->csum = chksum; skb->ip_summed = 1; } netif_rx(skb); -} - -static int tok_send_packet(struct sk_buff *skb, struct device *dev) -{ - struct tok_info *ti; - ti=(struct tok_info *) dev->priv; - - if (dev->tbusy) { - int ticks_waited; +} /*tr_rx */ - ticks_waited=jiffies - dev->trans_start; - if (ticks_waitedtrans_start+=5; /* we fake the transmission start time... */ - return 1; - } - - if (test_and_set_bit(0,(void *)&dev->tbusy)!=0) - DPRINTK("Transmitter access conflict\n"); - else { - int flags; - - /* lock against other CPUs */ - spin_lock_irqsave(&(ti->lock), flags); - - /* Save skb; we'll need it when the adapter asks for the data */ - ti->current_skb=skb; - SET_PAGE(ti->srb_page); - writeb(XMIT_UI_FRAME, ti->srb + offsetof(struct srb_xmit, command)); - writew(ti->exsap_station_id, ti->srb - +offsetof(struct srb_xmit, station_id)); - writeb(CMD_IN_SRB, (ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD)); - spin_unlock_irqrestore(&(ti->lock), flags); - - dev->trans_start=jiffies; - } - - return 0; -} - -void ibmtr_reset_timer(struct timer_list *tmr, struct device *dev) { - tmr->expires = jiffies + TR_RETRY_INTERVAL; - tmr->data = (unsigned long) dev; +void ibmtr_reset_timer(struct timer_list *tmr, struct device *dev) +{ + /*debugprintk("IBMTR_RESET_TIMER: adding an object\n"); */ + tmr->expires = jiffies + TR_RETRY_INTERVAL; + tmr->data = (unsigned long) dev; tmr->function = tok_open_adapter; init_timer(tmr); add_timer(tmr); } -void ibmtr_readlog(struct device *dev) { - struct tok_info *ti; - ti=(struct tok_info *) dev->priv; +/*****************************************************************************/ - ti->readlog_pending = 0; - SET_PAGE(ti->srb_page); - writeb(DIR_READ_LOG, ti->srb); - writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); - writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); - dev->tbusy=1; /* really srb busy... */ +void ibmtr_readlog(struct device *dev) +{ + struct tok_info *ti; + ti = (struct tok_info *) dev->priv; + + ti->readlog_pending = 0; + SET_PAGE(ti->srb_page); + writeb(DIR_READ_LOG, ti->srb); + writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN); + writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD); + dev->tbusy = 1; /* really srb busy... */ } +/*****************************************************************************/ + /* tok_get_stats(): Basically a scaffold routine which will return the address of the tr_statistics structure associated with this device -- the tr.... structure is an ethnet look-alike so at least for this iteration may suffice. */ -static struct net_device_stats * tok_get_stats(struct device *dev) { +static struct net_device_stats *tok_get_stats(struct device *dev) +{ struct tok_info *toki; - toki=(struct tok_info *) dev->priv; + toki = (struct tok_info *) dev->priv; return (struct net_device_stats *) &toki->tr_stats; } -int ibmtr_change_mtu(struct device *dev, int mtu) { +/*****************************************************************************/ + +int ibmtr_change_mtu(struct device *dev, int mtu) +{ struct tok_info *ti = (struct tok_info *) dev->priv; - + if (ti->ring_speed == 16 && mtu > ti->maxmtu16) return -EINVAL; if (ti->ring_speed == 4 && mtu > ti->maxmtu4) @@ -1889,13 +1747,14 @@ int ibmtr_change_mtu(struct device *dev, int mtu) { return 0; } +/*****************************************************************************/ #ifdef MODULE /* 3COM 3C619C supports 8 interrupts, 32 I/O ports */ -static struct device* dev_ibmtr[IBMTR_MAX_ADAPTERS]; -static int io[IBMTR_MAX_ADAPTERS] = {0xa20,0xa24}; -static int irq[IBMTR_MAX_ADAPTERS] = {0,0}; -static int mem[IBMTR_MAX_ADAPTERS] = {0,0}; +static struct device *dev_ibmtr[IBMTR_MAX_ADAPTERS]; +static int io[IBMTR_MAX_ADAPTERS] = { 0xa20, 0xa24 }; +static int irq[IBMTR_MAX_ADAPTERS] = { 0, 0 }; +static int mem[IBMTR_MAX_ADAPTERS] = { 0, 0 }; MODULE_PARM(io, "1-" __MODULE_STRING(IBMTR_MAX_ADAPTERS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(IBMTR_MAX_ADAPTERS) "i"); @@ -1903,46 +1762,46 @@ MODULE_PARM(mem, "1-" __MODULE_STRING(IBMTR_MAX_ADAPTERS) "i"); int init_module(void) { - int i; - for (i = 0; io[i] && (ibase_addr = io[i]; - dev_ibmtr[i]->irq = irq[i]; + dev_ibmtr[i]->base_addr = io[i]; + dev_ibmtr[i]->irq = irq[i]; dev_ibmtr[i]->mem_start = mem[i]; - dev_ibmtr[i]->init = &ibmtr_probe; + dev_ibmtr[i]->init = &ibmtr_probe; - if (register_trdev(dev_ibmtr[i]) != 0) { + if (register_trdev(dev_ibmtr[i]) != 0) { kfree_s(dev_ibmtr[i], sizeof(struct device)); dev_ibmtr[i] = NULL; - if (i == 0) { - printk("ibmtr: register_trdev() returned non-zero.\n"); - return -EIO; + if (i == 0) { + printk("ibmtr: register_trdev() returned non-zero.\n"); + return -EIO; } else { - return 0; + return 0; } - } + } } return 0; -} +} /*init_module */ void cleanup_module(void) { - int i; - - for (i = 0; i < IBMTR_MAX_ADAPTERS; i++) - if (dev_ibmtr[i]) { - unregister_trdev(dev_ibmtr[i]); - free_irq(dev_ibmtr[i]->irq, dev_ibmtr[i]); - release_region(dev_ibmtr[i]->base_addr, IBMTR_IO_EXTENT); - kfree_s(dev_ibmtr[i]->priv, sizeof(struct tok_info)); - kfree_s(dev_ibmtr[i], sizeof(struct device)); - dev_ibmtr[i] = NULL; - } + int i; + + for (i = 0; i < IBMTR_MAX_ADAPTERS; i++) + if (dev_ibmtr[i]) { + unregister_trdev(dev_ibmtr[i]); + free_irq(dev_ibmtr[i]->irq, dev_ibmtr[i]); + release_region(dev_ibmtr[i]->base_addr, IBMTR_IO_EXTENT); + kfree_s(dev_ibmtr[i]->priv, sizeof(struct tok_info)); + kfree_s(dev_ibmtr[i], sizeof(struct device)); + dev_ibmtr[i] = NULL; + } } -#endif /* MODULE */ +#endif /* MODULE */ diff --git a/drivers/net/ibmtr.h b/drivers/net/ibmtr.h index 18776a380002..d92833dfd005 100644 --- a/drivers/net/ibmtr.h +++ b/drivers/net/ibmtr.h @@ -3,11 +3,12 @@ /* ported to the Alpha architecture 02/20/96 (just used the HZ macro) */ -#define TR_RETRY_INTERVAL (5*HZ) /* 500 on PC = 5 s */ +#define TR_RETRY_INTERVAL (/*5BMS*/30*HZ) /* seconds * ticks/second */ #define TR_RESET_INTERVAL (HZ/20) /* 5 on PC = 50 ms */ #define TR_BUSY_INTERVAL (HZ/5) /* 5 on PC = 200 ms */ #define TR_SPIN_INTERVAL (3*HZ) /* 3 seconds before init timeout */ -#define TR_RETRIES 6 /* number of open retries */ +/*BMS I changed from 6 retries to 30 days of retries. Forever would be OK. */ +#define TR_RETRIES (30*24*60*60* HZ/TR_RETRY_INTERVAL) #define TR_ISA 1 #define TR_MCA 2 @@ -32,8 +33,20 @@ #define AIP16MBDHB 0X1FAC #define AIPFID 0X1FBA +#define ADAPT_PRIVATE 1416 /* Adapter Private Vars */ +#define ARBLENGTH 28 /* Adapter Request Block */ +#define SSBLENGTH 20 /* System Status Block */ +#define SAPLENGTH 64 /* Service Access Point */ +#define STALENGTH 144 /* Station Control Block */ +#define SRBLENGTH 28 /* System Request Block */ +#define ASBLENGTH 12 /* Adapter Status Block */ +#define BLOCKSZ 512 + /* Note, 0xA20 == 0x220 since motherboard decodes 10 bits. I left everything - the way my documentation had it, ie: 0x0A20. */ + the way my documentation had it, ie: 0x0A20. + * BMS motherboard and TR decode 16 bits. Some sound cards only decode 10 bits, + causing a potential conflict with a sound card addressed at 0x220. +*/ #define ADAPTINTCNTRL 0x02f0 /* Adapter interrupt control */ #define ADAPTRESET 0x1 /* Control Adapter reset (add to base) */ #define ADAPTRESETREL 0x2 /* Release Adapter from reset ( """) */ @@ -168,7 +181,7 @@ #define SET_PAGE(x) #endif -typedef enum { IN_PROGRESS, SUCCESS, FAILURE, CLOSED } open_state; +typedef enum { CLOSED, SUCCESS, FAILURE, AUTOREOPEN } open_state; /* do_tok_int possible values */ #define FIRST_INT 1 @@ -199,8 +212,8 @@ struct tok_info { /* Additions by Peter De Schrijver */ unsigned char page_mask; /* mask to select RAM page to Map*/ unsigned char mapped_ram_size; /* size of RAM page */ - __u32 sram; /* Shared memory base address */ - __u32 init_srb; /* Initial System Request Block address */ + __u32 sram_virt; /* Shared memory base address */ + __u32 init_srb; /* Initial System Request Block address */ __u32 srb; /* System Request Block address */ __u32 ssb; /* System Status Block address */ __u32 arb; /* Adapter Request Block address */ diff --git a/drivers/net/xpds/xpds.c b/drivers/net/xpds/xpds.c index 460ffda1981c..503264463b09 100644 --- a/drivers/net/xpds/xpds.c +++ b/drivers/net/xpds/xpds.c @@ -13,12 +13,8 @@ #ifndef __KERNEL__ #define __KERNEL__ 1 #endif -#ifndef MODULE -#define MODULE 1 -#endif #include - #include #include #include @@ -3767,7 +3763,7 @@ xpds_free_data (void) #ifdef MODULE int init_module (void) #else -int xpds_init(void) +int xpdsl_init(void) #endif { int i; diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index c439b2308db3..415ab99b5414 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -613,7 +613,7 @@ static struct signature { static void do_pause(unsigned amount) { /* Pause for amount*10 milliseconds */ - unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */ + unsigned long the_time = jiffies + (amount*HZ)/100; /* 0.01 seconds per jiffy */ while (time_before(jiffies, the_time)) barrier(); @@ -1068,7 +1068,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt) printk("aha152x: trying software interrupt, "); SETBITS(DMACNTRL0, SWINT); - the_time = jiffies + 100; + the_time = jiffies + HZ; while (!HOSTDATA(shpnt)->swint && time_before(jiffies, the_time)) barrier(); diff --git a/drivers/sound/i810_audio.c b/drivers/sound/i810_audio.c index 788131f305bc..0e3a8f6bb41e 100644 --- a/drivers/sound/i810_audio.c +++ b/drivers/sound/i810_audio.c @@ -1683,9 +1683,18 @@ static int __init i810_ac97_init(struct i810_card *card) struct ac97_codec *codec; u16 eid; int i=0; + u32 reg; - - outl(6 , card->iobase + GLOB_CNT); + reg = inl(card->iobase + GLOB_CNT); + + if((reg&2)==0) /* Cold required */ + reg|=2; + else + reg|=4; /* Warm */ + + reg&=~8; /* ACLink on */ + outl(reg , card->iobase + GLOB_CNT); + while(i<10) { if((inl(card->iobase+GLOB_CNT)&4)==0) diff --git a/drivers/sound/trident.c b/drivers/sound/trident.c index 4c8a5edbb040..ae74ef44f894 100644 --- a/drivers/sound/trident.c +++ b/drivers/sound/trident.c @@ -30,6 +30,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History + * v0.14.5c Oct 28 2000 Alan Cox + * Merged Ching-Ling Lee's ADC/DAC fix from the newer ALI work * v0.14.5b Sept 17 2000 Eric Brombaugh * Fix hang when trying ALi MIDI init on Trident * v0.14.5 June 3 2000 Ollie Lho @@ -1166,6 +1168,27 @@ static void trident_update_ptr(struct trident_state *state) __stop_adc(state); dmabuf->error++; } + if (dmabuf->count < (signed)dmabuf->dmasize/2) + wake_up(&dmabuf->wait); + } + } + + /* error handling and process wake up for DAC */ + if (dmabuf->enable == DAC_RUNNING) { + if (dmabuf->mapped) { + dmabuf->count += diff; + if (dmabuf->count >= (signed)dmabuf->fragsize) + wake_up(&dmabuf->wait); + } else { + dmabuf->count -= diff; + + if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) { + /* buffer underrun or buffer overrun, we have no way to recover + it here, just stop the machine and let the process force hwptr + and swptr to sync */ + __stop_dac(state); + dmabuf->error++; + } else if (!dmabuf->endcleared) { swptr = dmabuf->swptr; silence = (dmabuf->fmt & TRIDENT_FMT_16BIT ? 0 : 0x80); @@ -1183,7 +1206,6 @@ static void trident_update_ptr(struct trident_state *state) //clear the invalid data memset (dmabuf->rawbuf + swptr, silence, clear_cnt); - dmabuf->endcleared = 1; } } else if (dmabuf->count < (signed) dmabuf->fragsize) { @@ -1194,30 +1216,6 @@ static void trident_update_ptr(struct trident_state *state) dmabuf->endcleared = 1; } } - /* trident_update_ptr is called by interrupt handler or by process via - ioctl/poll, we only wake up the waiting process when we have more - than 1/2 buffer of data to process (always true for interrupt handler) */ - if (dmabuf->count > (signed)dmabuf->dmasize/2) - wake_up(&dmabuf->wait); - } - } - - /* error handling and process wake up for DAC */ - if (dmabuf->enable == DAC_RUNNING) { - if (dmabuf->mapped) { - dmabuf->count += diff; - if (dmabuf->count >= (signed)dmabuf->fragsize) - wake_up(&dmabuf->wait); - } else { - dmabuf->count -= diff; - - if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) { - /* buffer underrun or buffer overrun, we have no way to recover - it here, just stop the machine and let the process force hwptr - and swptr to sync */ - __stop_dac(state); - dmabuf->error++; - } /* trident_update_ptr is called by interrupt handler or by process via ioctl/poll, we only wake up the waiting process when we have more than 1/2 buffer free (always true for interrupt handler) */ diff --git a/drivers/usb/microtek.c b/drivers/usb/microtek.c index f36398e55452..d6454044fc00 100644 --- a/drivers/usb/microtek.c +++ b/drivers/usb/microtek.c @@ -493,7 +493,7 @@ void mts_int_submit_urb (struct urb* transfer, res = usb_submit_urb( transfer ); if ( res ) { - MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res ); + MTS_ERROR( "could not submit URB! Error was %d\n",(int)res ); context->srb->result = DID_ERROR << 16; context->state = mts_con_error; mts_transfer_cleanup(transfer); diff --git a/drivers/usb/mousedev.c b/drivers/usb/mousedev.c index 5413a1f9b1fe..e5b5b88e5b0c 100644 --- a/drivers/usb/mousedev.c +++ b/drivers/usb/mousedev.c @@ -276,7 +276,7 @@ static ssize_t mousedev_write(struct file * file, const char * buffer, size_t co for (i = 0; i < count; i++) { - c = buffer[i]; + get_user(c, buffer+i); if (c == mousedev_genius_seq[list->genseq]) { if (++list->genseq == MOUSEDEV_GENIUS_LEN) { diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c index 9d48c85824cc..90a005de4060 100644 --- a/drivers/video/fbcon.c +++ b/drivers/video/fbcon.c @@ -1806,12 +1806,13 @@ static unsigned long fbcon_getxy(struct vc_data *conp, unsigned long pos, int *p y += softback_lines; ret = pos + (conp->vc_cols - x) * 2; } else if (conp->vc_num == fg_console && softback_lines) { - unsigned long offset = (pos - softback_curr) / 2; + unsigned long offset = pos - softback_curr; + if (pos < softback_curr) + offset += softback_end - softback_buf; + offset /= 2; x = offset % conp->vc_cols; y = offset / conp->vc_cols; - if (pos < softback_curr) - y += (softback_end - softback_buf) / conp->vc_size_row; ret = pos + (conp->vc_cols - x) * 2; if (ret == softback_end) ret = softback_buf; diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index a99dd452a9a1..5d5b91b8076c 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -594,8 +594,8 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) bprm->argc++; } } - retval = -E2BIG; - if (!bprm->p) + retval = (long)bprm->p; + if ((long)bprm->p < 0) goto out_free_dentry; } diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c index d1992ca0643b..8d1b97bc7ae2 100644 --- a/fs/binfmt_em86.c +++ b/fs/binfmt_em86.c @@ -73,8 +73,8 @@ static int do_load_em86(struct linux_binprm *bprm,struct pt_regs *regs) } bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2); bprm->argc++; - if (!bprm->p) - return -E2BIG; + if ((long)bprm->p < 0) + return (long)bprm->p; /* * OK, now restart the process with the interpreter's inode. * Note that we use open_namei() as the name is now in kernel diff --git a/fs/binfmt_java.c b/fs/binfmt_java.c index ca1ad396c34b..43206da54b23 100644 --- a/fs/binfmt_java.c +++ b/fs/binfmt_java.c @@ -74,8 +74,8 @@ static int do_load_java(struct linux_binprm *bprm,struct pt_regs *regs) bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2); bprm->argc++; - if (!bprm->p) - return -E2BIG; + if ((long)bprm->p < 0) + return (long)bprm->p; /* * OK, now restart the process with the interpreter's dentry. */ @@ -121,8 +121,8 @@ static int do_load_applet(struct linux_binprm *bprm,struct pt_regs *regs) bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2); bprm->argc++; - if (!bprm->p) - return -E2BIG; + if ((long)bprm->p < 0) + return (long)bprm->p; /* * OK, now restart the process with the interpreter's dentry. */ diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index cb062d5b1076..20429dc2136b 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -214,8 +214,8 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) bprm->argc++; bprm->p = copy_strings(1, &iname_addr, bprm->page, bprm->p, 2); bprm->argc++; - retval = -E2BIG; - if (!bprm->p) + retval = (long)bprm->p; + if ((long)bprm->p < 0) goto _ret; bprm->filename = iname; /* for binfmt_script */ diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index 6aa1508a4b9b..336dc97ff93d 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c @@ -74,8 +74,8 @@ static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs) } bprm->p = copy_strings(1, &i_name, bprm->page, bprm->p, 2); bprm->argc++; - if (!bprm->p) - return -E2BIG; + if ((long)bprm->p < 0) + return (long)bprm->p; /* * OK, now restart the process with the interpreter's dentry. */ diff --git a/fs/buffer.c b/fs/buffer.c index c965a9ba08f0..b59b5b4bb740 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1468,10 +1468,13 @@ static int grow_buffers(int size) #define BUFFER_BUSY_BITS ((1<b_count || ((bh)->b_state & BUFFER_BUSY_BITS)) -static int sync_page_buffers(struct buffer_head *bh, int wait) +static int sync_page_buffers(struct page * page, int wait) { + struct buffer_head * bh = page->buffers; struct buffer_head * tmp = bh; + page->buffers = NULL; + do { struct buffer_head *p = tmp; tmp = tmp->b_this_page; @@ -1482,6 +1485,8 @@ static int sync_page_buffers(struct buffer_head *bh, int wait) ll_rw_block(WRITE, 1, &p); } while (tmp != bh); + page->buffers = bh; + do { struct buffer_head *p = tmp; tmp = tmp->b_this_page; @@ -1533,7 +1538,7 @@ int try_to_free_buffers(struct page * page_map, int wait) busy: too_many = (nr_buffers * bdf_prm.b_un.nfract/100); - if (!sync_page_buffers(bh, wait)) { + if (!sync_page_buffers(page_map, wait)) { /* If a high percentage of the buffers are dirty, * wake kflushd diff --git a/fs/exec.c b/fs/exec.c index 67d4220c7024..acd3044f89eb 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -705,6 +705,8 @@ void compute_creds(struct linux_binprm *bprm) if (current->euid != current->uid || current->egid != current->gid || !cap_issubset(new_permitted, current->cap_permitted)) current->dumpable = 0; + + current->keep_capabilities = 0; } diff --git a/include/asm-alpha/core_irongate.h b/include/asm-alpha/core_irongate.h index cf0114db60ca..10e0917d9a2c 100644 --- a/include/asm-alpha/core_irongate.h +++ b/include/asm-alpha/core_irongate.h @@ -505,21 +505,25 @@ __EXTERN_INLINE unsigned long irongate_readq(unsigned long addr) __EXTERN_INLINE void irongate_writeb(unsigned char b, unsigned long addr) { __kernel_stb(b, *(vucp)(XADDR + IRONGATE_MEM)); + mb(); } __EXTERN_INLINE void irongate_writew(unsigned short b, unsigned long addr) { __kernel_stw(b, *(vusp)(XADDR + IRONGATE_MEM)); + mb(); } __EXTERN_INLINE void irongate_writel(unsigned int b, unsigned long addr) { *(vuip)(XADDR + IRONGATE_MEM) = b; + mb(); } __EXTERN_INLINE void irongate_writeq(unsigned long b, unsigned long addr) { *(vulp)(XADDR + IRONGATE_MEM) = b; + mb(); } /* Find the DENSE memory area for a given bus address. */ diff --git a/include/asm-i386/math-emu.h b/include/asm-m68k/math-emu.h similarity index 100% rename from include/asm-i386/math-emu.h rename to include/asm-m68k/math-emu.h diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index 323a305c46ab..c42e0d2df730 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -17,6 +17,7 @@ struct ipv4_devconf int forwarding; int mc_forwarding; int hidden; + int arp_filter; void *sysctl; }; @@ -52,6 +53,9 @@ struct in_device || (!IN_DEV_FORWARD(in_dev) && \ (ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects))) +#define IN_DEV_ARPFILTER(in_dev) (ipv4_devconf.arp_filter || \ + (in_dev)->cnf.arp_filter) + struct in_ifaddr { struct in_ifaddr *ifa_next; diff --git a/include/linux/kcomp.h b/include/linux/kcomp.h index f97695d9cc73..95de8e4ee759 100644 --- a/include/linux/kcomp.h +++ b/include/linux/kcomp.h @@ -56,6 +56,9 @@ static inline void netif_device_attach(struct net_device *dev) #define NET_XMIT_CN 2 #define IORESOURCE_IO 1 -#define pci_resource_start(dev, i) (dev->base_address[i] & ~IORESOURCE_IO) +#define pci_resource_start(dev,bar) \ +(((dev)->base_address[(bar)] & PCI_BASE_ADDRESS_SPACE) ? \ + ((dev)->base_address[(bar)] & PCI_BASE_ADDRESS_IO_MASK) : \ + ((dev)->base_address[(bar)] & PCI_BASE_ADDRESS_MEM_MASK)) #define pci_resource_flags(dev, i) (dev->base_address[i] & IORESOURCE_IO) diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h index 0a2efb6e930d..fb24b8efb717 100644 --- a/include/linux/mc146818rtc.h +++ b/include/linux/mc146818rtc.h @@ -26,6 +26,8 @@ outb_p((addr),RTC_PORT(0)); \ outb_p((val),RTC_PORT(1)); \ }) +extern spinlock_t rtc_lock; /* You must hold this lock to use CMOS_* ops */ + /********************************************************************** * register summary **********************************************************************/ diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 5b503d75856a..b20219f34fb0 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -34,7 +34,7 @@ #endif #define NFS_MAX_FILE_IO_BUFFER_SIZE 32768 -#define NFS_DEF_FILE_IO_BUFFER_SIZE 1024 +#define NFS_DEF_FILE_IO_BUFFER_SIZE 4096 /* * The upper limit on timeouts for the exponential backoff algorithm. diff --git a/include/linux/prctl.h b/include/linux/prctl.h index f08f3c36ed40..1bb487888c7d 100644 --- a/include/linux/prctl.h +++ b/include/linux/prctl.h @@ -5,5 +5,8 @@ #define PR_SET_PDEATHSIG 1 /* Second arg is a signal */ +/* Get/set whether or not to drop capabilities on setuid() away from uid 0 */ +#define PR_GET_KEEPCAPS 7 +#define PR_SET_KEEPCAPS 8 #endif /* _LINUX_PRCTL_H */ diff --git a/include/linux/sched.h b/include/linux/sched.h index a7fcc397260e..146ee631fff3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -296,7 +296,8 @@ struct task_struct { gid_t gid,egid,sgid,fsgid; int ngroups; gid_t groups[NGROUPS]; - kernel_cap_t cap_effective, cap_inheritable, cap_permitted; + kernel_cap_t cap_effective, cap_inheritable, cap_permitted; + int keep_capabilities:1; struct user_struct *user; /* limits */ struct rlimit rlim[RLIM_NLIMITS]; @@ -385,7 +386,8 @@ struct task_struct { /* process credentials */ \ /* uid etc */ 0,0,0,0,0,0,0,0, \ /* suppl grps*/ 0, {0,}, \ -/* caps */ CAP_INIT_EFF_SET,CAP_INIT_INH_SET,CAP_FULL_SET, \ +/* caps */ CAP_INIT_EFF_SET,CAP_INIT_INH_SET,CAP_FULL_SET, \ +/* keep_caps */ 0, \ /* user */ NULL, \ /* rlimits */ INIT_RLIMITS, \ /* math */ 0, \ diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 793553cc5f0b..c6732dc8d967 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -272,7 +272,8 @@ enum NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE=9, NET_IPV4_CONF_BOOTP_RELAY=10, NET_IPV4_CONF_LOG_MARTIANS=11, - NET_IPV4_CONF_HIDDEN=12 + NET_IPV4_CONF_HIDDEN=12, + NET_IPV4_CONF_ARPFILTER=13 }; /* /proc/sys/net/ipv6 */ diff --git a/include/net/snmp.h b/include/net/snmp.h index fcbf733ea337..bb1aaf31c218 100644 --- a/include/net/snmp.h +++ b/include/net/snmp.h @@ -179,6 +179,7 @@ struct linux_mib unsigned long OutOfWindowIcmps; unsigned long LockDroppedIcmps; unsigned long SockMallocOOM; + unsigned long ArpFilter; }; #endif diff --git a/kernel/printk.c b/kernel/printk.c index d7d22d557234..8101fb1a8e0e 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -111,8 +111,8 @@ void __init console_setup(char *str, int *ints) * 0 -- Close the log. Currently a NOP. * 1 -- Open the log. Currently a NOP. * 2 -- Read from the log. - * 3 -- Read up to the last 4k of messages in the ring buffer. - * 4 -- Read and clear last 4k of messages in the ring buffer + * 3 -- Read all messages remaining in the ring buffer. + * 4 -- Read and clear all messages remaining in the ring buffer * 5 -- Clear ring buffer. * 6 -- Disable printk's to console * 7 -- Enable printk's to console diff --git a/kernel/sys.c b/kernel/sys.c index 97fc5830ba1e..bbb06a5cb958 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -323,12 +323,23 @@ asmlinkage int sys_setgid(gid_t gid) * never happen. * * -astor + * + * cevans - New behaviour, Oct '99 + * A process may, via prctl(), elect to keep its capabilities when it + * calls setuid() and switches away from uid==0. Both permitted and + * effective sets will be retained. + * Without this change, it was impossible for a daemon to drop only some + * of its privilege. The call to setuid(!=0) would drop all privileges! + * Keeping uid 0 is not an option because uid 0 owns too many vital + * files.. + * Thanks to Olaf Kirch and Peter Benie for spotting this. */ extern inline void cap_emulate_setxuid(int old_ruid, int old_euid, int old_suid) { if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) && - (current->uid != 0 && current->euid != 0 && current->suid != 0)) { + (current->uid != 0 && current->euid != 0 && current->suid != 0) && + !current->keep_capabilities) { cap_clear(current->cap_permitted); cap_clear(current->cap_effective); } @@ -1016,6 +1027,18 @@ asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3, } current->pdeath_signal = sig; break; + + case PR_GET_KEEPCAPS: + if (current->keep_capabilities) + error = 1; + break; + case PR_SET_KEEPCAPS: + if (arg2 != 0 && arg2 != 1) { + error = -EINVAL; + break; + } + current->keep_capabilities = arg2; + break; default: error = -EINVAL; break; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 2d9114c7c8ac..62c02cc39f0a 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -339,6 +339,22 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) dst_ha, dev->dev_addr, NULL); } +static int arp_filter(__u32 sip, __u32 tip, struct device *dev) +{ + struct rtable *rt; + int flag = 0; + //unsigned long now; + + if (ip_route_output(&rt, sip, tip, 0, 0) < 0) + return 1; + if (rt->u.dst.dev != dev) { + net_statistics.ArpFilter++; + flag = 1; + } + ip_rt_put(rt); + return flag; +} + /* OBSOLETE FUNCTIONS */ /* @@ -689,6 +705,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) if (addr_type == RTN_LOCAL) { n = neigh_event_ns(&arp_tbl, sha, &sip, dev); if (n) { + int dont_send = 0; if (ipv4_devconf.hidden && skb->pkt_type != PACKET_HOST) { struct device *dev2; @@ -698,12 +715,14 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) dev2 != dev && (in_dev2 = dev2->ip_ptr) != NULL && IN_DEV_HIDDEN(in_dev2)) { - neigh_release(n); - goto out; - } + dont_send = 1; + } } + if (IN_DEV_ARPFILTER(in_dev)) + dont_send |= arp_filter(sip,tip,dev); - arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); + if (!dont_send) + arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); neigh_release(n); } goto out; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 24f486815027..833334cfa570 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -925,7 +925,7 @@ int devinet_sysctl_forward(ctl_table *ctl, int write, struct file * filp, static struct devinet_sysctl_table { struct ctl_table_header *sysctl_header; - ctl_table devinet_vars[13]; + ctl_table devinet_vars[14]; ctl_table devinet_dev[2]; ctl_table devinet_conf_dir[2]; ctl_table devinet_proto_dir[2]; @@ -968,6 +968,9 @@ static struct devinet_sysctl_table {NET_IPV4_CONF_HIDDEN, "hidden", &ipv4_devconf.hidden, sizeof(int), 0644, NULL, &proc_dointvec}, + {NET_IPV4_CONF_ARPFILTER, "arp_filter", + &ipv4_devconf.arp_filter, sizeof(int), 0644, NULL, + &proc_dointvec}, {0}}, {{NET_PROTO_CONF_ALL, "all", NULL, 0, 0555, devinet_sysctl.devinet_vars},{0}}, diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 5cc3a13d13ae..e924bfee982c 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -7,7 +7,7 @@ * PROC file system. It is mainly used for debugging and * statistics. * - * Version: $Id: proc.c,v 1.34.2.3 2000/06/21 02:14:45 davem Exp $ + * Version: $Id: proc.c,v 1.34.2.4 2000/10/18 17:50:41 davem Exp $ * * Authors: Fred N. van Kempen, * Gerald J. Heim, @@ -186,7 +186,7 @@ get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t of if (req->sk) continue; pos += 128; - if (pos < offset) + if (pos <= offset) continue; get__openreq(sp, req, tmpbuf, i); len += sprintf(buffer+len, "%-127s\n", tmpbuf); @@ -196,7 +196,7 @@ get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t of } pos += 128; - if (pos < offset) + if (pos <= offset) goto next; get__sock(sp, tmpbuf, i, format); @@ -371,6 +371,10 @@ int netstat_get_info(char *buffer, char **start, off_t offset, int length, int d net_statistics.OutOfWindowIcmps, net_statistics.LockDroppedIcmps, net_statistics.SockMallocOOM); + len += sprintf(buffer + len, + "IpExt: ArpFilter\n" + "IpExt: %lu\n", + net_statistics.ArpFilter); if (offset >= len) { -- 2.39.5