## Automatically generated incremental diff ## From: linux-2.5.65-bk2 ## To: linux-2.5.65-bk3 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.5.65-bk2/Documentation/filesystems/sysfs.txt linux-2.5.65-bk3/Documentation/filesystems/sysfs.txt --- linux-2.5.65-bk2/Documentation/filesystems/sysfs.txt Mon Mar 17 13:43:42 2003 +++ linux-2.5.65-bk3/Documentation/filesystems/sysfs.txt Mon Mar 31 12:41:39 2003 @@ -60,7 +60,7 @@ you publically humiliated and your code rewritten without notice. -An attriubte definition is simply: +An attribute definition is simply: struct attribute { char * name; @@ -261,7 +261,7 @@ that point to the device's directory under root/. drivers/ contains a directory for each device driver that is loaded -for devices on that particular bus (this assmumes that drivers do not +for devices on that particular bus (this assumes that drivers do not span multiple bus types). diff -urN linux-2.5.65-bk2/Documentation/kernel-parameters.txt linux-2.5.65-bk3/Documentation/kernel-parameters.txt --- linux-2.5.65-bk2/Documentation/kernel-parameters.txt Mon Mar 17 13:44:51 2003 +++ linux-2.5.65-bk3/Documentation/kernel-parameters.txt Mon Mar 31 12:41:39 2003 @@ -713,7 +713,6 @@ numbers ourselves, overriding whatever the firmware may have done. - usepirqmask [IA-32] Honor the possible IRQ mask stored in the BIOS $PIR table. This is needed on some systems with broken @@ -721,6 +720,7 @@ and Omnibook XE3 notebooks. This will have no effect if ACPI IRQ routing is enabled. + noacpi [IA-32] Do not use ACPI for IRQ routing. pcmv= [HW,PCMCIA] BadgePAD 4 diff -urN linux-2.5.65-bk2/MAINTAINERS linux-2.5.65-bk3/MAINTAINERS --- linux-2.5.65-bk2/MAINTAINERS Mon Mar 31 12:41:36 2003 +++ linux-2.5.65-bk3/MAINTAINERS Mon Mar 31 12:41:39 2003 @@ -728,7 +728,7 @@ GDT SCSI DISK ARRAY CONTROLLER DRIVER P: Achim Leubner -M: achim@vortex.de +M: achim.leubner@intel.com L: linux-scsi@vger.kernel.org W: http://www.icp-vortex.com/ S: Supported diff -urN linux-2.5.65-bk2/Makefile linux-2.5.65-bk3/Makefile --- linux-2.5.65-bk2/Makefile Mon Mar 31 12:41:36 2003 +++ linux-2.5.65-bk3/Makefile Mon Mar 31 12:41:39 2003 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 SUBLEVEL = 65 -EXTRAVERSION = -bk2 +EXTRAVERSION = -bk3 # *DOCUMENTATION* # To see a list of typical targets execute "make help" @@ -164,6 +164,8 @@ OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdump AWK = awk +RPM := $(shell if [ -x "/usr/bin/rpmbuild" ]; then echo rpmbuild; \ + else echo rpm; fi) GENKSYMS = scripts/genksyms/genksyms DEPMOD = /sbin/depmod KALLSYMS = scripts/kallsyms @@ -768,9 +770,7 @@ rm $(KERNELPATH) ; \ cd $(TOPDIR) ; \ $(CONFIG_SHELL) $(srctree)/scripts/mkversion > .version ; \ - RPM=`which rpmbuild`; \ - if [ -z "$$RPM" ]; then RPM=rpm; fi; \ - $$RPM -ta $(TOPDIR)/../$(KERNELPATH).tar.gz ; \ + $(RPM) -ta $(TOPDIR)/../$(KERNELPATH).tar.gz ; \ rm $(TOPDIR)/../$(KERNELPATH).tar.gz # Brief documentation of the typical targets used diff -urN linux-2.5.65-bk2/arch/i386/boot98/Makefile linux-2.5.65-bk3/arch/i386/boot98/Makefile --- linux-2.5.65-bk2/arch/i386/boot98/Makefile Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/boot98/Makefile Mon Mar 31 12:41:39 2003 @@ -0,0 +1,76 @@ +# +# arch/i386/boot/Makefile +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1994 by Linus Torvalds +# + +# ROOT_DEV specifies the default root-device when making the image. +# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case +# the default of FLOPPY is used by 'build'. + +ROOT_DEV := CURRENT + +# If you want to preset the SVGA mode, uncomment the next line and +# set SVGA_MODE to whatever number you want. +# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode. +# The number is the same as you would ordinarily press at bootup. + +SVGA_MODE := -DSVGA_MODE=NORMAL_VGA + +# If you want the RAM disk device, define this to be the size in blocks. + +#RAMDISK := -DRAMDISK=512 + +EXTRA_TARGETS := vmlinux.bin bootsect bootsect.o \ + setup setup.o zImage bzImage + +subdir- := compressed + +host-progs := tools/build + +# --------------------------------------------------------------------------- + +$(obj)/zImage: IMAGE_OFFSET := 0x1000 +$(obj)/zImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) +$(obj)/bzImage: IMAGE_OFFSET := 0x100000 +$(obj)/bzImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ +$(obj)/bzImage: BUILDFLAGS := -b + +quiet_cmd_image = BUILD $@ +cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \ + $(obj)/vmlinux.bin $(ROOT_DEV) > $@ + +$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \ + $(obj)/vmlinux.bin $(obj)/tools/build FORCE + $(call if_changed,image) + @echo 'Kernel: $@ is ready' + +$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE + $(call if_changed,objcopy) + +LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary +LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext + +$(obj)/setup $(obj)/bootsect: %: %.o FORCE + $(call if_changed,ld) + +$(obj)/compressed/vmlinux: FORCE + $(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \ + IMAGE_OFFSET=$(IMAGE_OFFSET) $@ + +zdisk: $(BOOTIMAGE) + dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0 + +zlilo: $(BOOTIMAGE) + if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi + if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi + cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz + cp System.map $(INSTALL_PATH)/ + if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi + +install: $(BOOTIMAGE) + sh $(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)" diff -urN linux-2.5.65-bk2/arch/i386/boot98/bootsect.S linux-2.5.65-bk3/arch/i386/boot98/bootsect.S --- linux-2.5.65-bk2/arch/i386/boot98/bootsect.S Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/boot98/bootsect.S Mon Mar 31 12:41:39 2003 @@ -0,0 +1,397 @@ +/* + * bootsect.S - boot sector for NEC PC-9800 series + * + * Linux/98 project at Kyoto University Microcomputer Club (KMC) + * FUJITA Norimasa, TAKAI Kousuke 1997-1998 + * rewritten by TAKAI Kousuke (as86 -> gas), Nov 1999 + * + * Based on: + * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds + * modified by Drew Eckhardt + * modified by Bruce Evans (bde) + * + * bootsect.S is loaded at 0x1FC00 or 0x1FE00 by the bios-startup routines, + * and moves itself out of the way to address 0x90000, and jumps there. + * + * It then loads 'setup' directly after itself (0x90200), and the system + * at 0x10000, using BIOS interrupts. + * + * NOTE! currently system is at most (8*65536-4096) bytes long. This should + * be no problem, even in the future. I want to keep it simple. This 508 kB + * kernel size should be enough, especially as this doesn't contain the + * buffer cache as in minix (and especially now that the kernel is + * compressed :-) + * + * The loader has been made as simple as possible, and continuous + * read errors will result in a unbreakable loop. Reboot by hand. It + * loads pretty fast by getting whole tracks at a time whenever possible. + */ + +#include /* for CONFIG_ROOT_RDONLY */ +#include + +SETUPSECTS = 4 /* default nr of setup-sectors */ +BOOTSEG = 0x1FC0 /* original address of boot-sector */ +INITSEG = DEF_INITSEG /* we move boot here - out of the way */ +SETUPSEG = DEF_SETUPSEG /* setup starts here */ +SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ +SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ + /* to be loaded */ +ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ +SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ + +#ifndef SVGA_MODE +#define SVGA_MODE ASK_VGA +#endif + +#ifndef RAMDISK +#define RAMDISK 0 +#endif + +#ifndef ROOT_RDONLY +#define ROOT_RDONLY 1 +#endif + +/* normal/hireso text VRAM segments */ +#define NORMAL_TEXT 0xa000 +#define HIRESO_TEXT 0xe000 + +/* bios work area addresses */ +#define EXPMMSZ 0x0401 +#define BIOS_FLAG 0x0501 +#define DISK_BOOT 0x0584 + +.code16 +.text + +.global _start +_start: + +#if 0 /* hook for debugger, harmless unless BIOS is fussy (old HP) */ + int $0x3 +#endif + jmp real_start + .ascii "Linux 98" + .word 0 +real_start: + xorw %di, %di /* %di = 0 */ + movw %di, %ss /* %ss = 0 */ + movw $0x03F0, %sp + pushw %cx /* for hint */ + + movw $0x0A00, %ax /* normal mode defaults (80x25) */ + + testb $0x08, %ss:BIOS_FLAG /* check hi-reso bit */ + jnz set_crt_mode +/* + * Hi-Reso (high-resolution) machine. + * + * Some hi-reso machines have no RAMs on bank 8/A (0x080000 - 0x0BFFFF). + * On such machines we get two RAM banks from top of protect menory and + * map them on bank 8/A. + * These work-around must be done before moving myself on INITSEG (0x090000-). + */ + movw $(HIRESO_TEXT >> 8), %cs:(vram + 1) /* text VRAM segment */ + + /* set memory window */ + movb $0x08, %al + outb %al, $0x91 /* map native RAM (if any) */ + movb $0x0A, %al + outb %al, $0x93 + + /* check bank ram A */ + pushw $0xA500 + popw %ds + movw (%di), %cx /* %si == 0 from entry */ + notw %cx + movw %cx, (%di) + + movw $0x43F, %dx /* cache flush for 486 and up. */ + movb $0xA0, %al + outb %al, %dx + + cmpw %cx, (%di) + je hireso_done + + /* + * Write test failed; we have no native RAM on 080000h - 0BFFFFh. + * Take 256KB of RAM from top of protected memory. + */ + movb %ss:EXPMMSZ, %al + subb $2, %al /* reduce 2 x 128KB */ + movb %al, %ss:EXPMMSZ + addb %al, %al + addb $0x10, %al + outb %al, $0x91 + addb $2, %al + outb %al, $0x93 + +hireso_done: + movb $0x10, %al /* CRT mode 80x31, %ah still 0Ah */ + +set_crt_mode: + int $0x18 /* set CRT mode */ + + movb $0x0C, %ah /* turn on text displaying */ + int $0x18 + + xorw %dx, %dx /* position cursor to home */ + movb $0x13, %ah + int $0x18 + + movb $0x11, %ah /* turn cursor displaying on */ + int $0x18 + + /* move 1 kilobytes from [BOOTSEG:0000h] to [INITSEG:0000h] */ + cld + xorw %si, %si + pushw $INITSEG + popw %es + movw $512, %cx /* %di == 0 from entry */ + rep + cs + movsw + + ljmp $INITSEG, $go + +go: + pushw %cs + popw %ds /* %ds = %cs */ + + popw %dx /* %dh = saved %ch passed from BIOS */ + movb %ss:DISK_BOOT, %al + andb $0xf0, %al /* %al = Device Address */ + movb $18, %ch /* 18 secs/track, 512 b/sec (1440 KB) */ + cmpb $0x30, %al + je try512 + cmpb $0x90, %al /* 1 MB I/F, 1 MB floppy */ + je try1.2M + cmpb $0xf0, %al /* 640 KB I/F, 1 MB floppy */ + je try1.2M + movb $9, %ch /* 9 secs/track, 512 b/sec ( 720 KB) */ + cmpb $0x10, %al /* 1 MB I/F, 640 KB floppy */ + je try512 + cmpb $0x70, %al /* 640 KB I/F, 640 KB floppy */ + jne error /* unknown device? */ + + /* XXX: Does it make sense to support 8 secs/track, 512 b/sec + (640 KB) floppy? */ + +try512: movb $2, %cl /* 512 b/sec */ +lasttry:call tryload +/* + * Display error message and halt + */ +error: movw $error_msg, %si + call print +wait_reboot: + movb $0x0, %ah + int $0x18 /* wait keyboard input */ +1: movb $0, %al + outb %al, $0xF0 /* reset CPU */ + jmp 1b /* just in case... */ + +try1.2M:cmpb $2, %dh + je try2HC + movw $0x0803, %cx /* 8 secs/track, 1024 b/sec (1232 KB) */ + call tryload + movb $15, %ch /* 15 secs/track, 512 b/sec (1200 KB) */ + jmp try512 +try2HC: movw $0x0F02, %cx /* 15 secs/track, 512 b/sec (1200 KB) */ + call tryload + movw $0x0803, %cx /* 8 secs/track, 1024 b/sec (1232 KB) */ + jmp lasttry + +/* + * Try to load SETUP and SYSTEM provided geometry information in %cx. + * This routine *will not* return on successful load... + */ +tryload: + movw %cx, sectlen + movb %ss:DISK_BOOT, %al + movb $0x7, %ah /* recalibrate the drive */ + int $0x1b + jc error /* recalibration should succeed */ + + /* + * Load SETUP into memory. It is assumed that SETUP fits into + * first cylinder (2 tracks, 9KB on 2DD, 15-18KB on 2HD). + */ + movb $0, %bl + movb setup_sects, %bh + incb %bh + shlw %bx /* %bx = (setup_sects + 1) * 512 */ + movw $128, %bp + shlw %cl, %bp /* %bp = */ + subw %bp, %bx /* length to load */ + movw $0x0002, %dx /* head 0, sector 2 */ + movb %cl, %ch /* `N' for sector address */ + movb $0, %cl /* cylinder 0 */ + pushw %cs + popw %es /* %es = %cs (= INITSEG) */ + movb $0xd6, %ah /* read, multi-track, MFM */ + int $0x1b /* load it! */ + jc read_error + + movw $loading_msg, %si + call print + + movw $SYSSEG, %ax + movw %ax, %es /* %es = SYSSEG */ + +/* + * This routine loads the system at address 0x10000, making sure + * no 64kB boundaries are crossed. We try to load it as fast as + * possible, loading whole tracks whenever we can. + * + * in: es - starting address segment (normally 0x1000) + */ + movb %ch, %cl + addb $7, %cl /* %cl = log2 */ + shrw %cl, %bx /* %bx = # of phys. sectors in SETUP */ + addb %bl, %dl /* %dl = start sector # of SYSTEM */ + decb %dl /* %dl is 0-based in below loop */ + +rp_read_newseg: + xorw %bp, %bp /* = starting address within segment */ +#ifdef __BIG_KERNEL__ + bootsect_kludge = 0x220 /* 0x200 (size of bootsector) + 0x20 (offset */ + lcall *bootsect_kludge /* of bootsect_kludge in setup.S */ +#else + movw %es, %ax + subw $SYSSEG, %ax +#endif + cmpw syssize, %ax + ja boot /* done! */ + +rp_read: + movb sectors, %al + addb %al, %al + movb %al, %ch /* # of sectors on both surface */ + subb %dl, %al /* # of sectors left on this track */ + movb $0, %ah + shlw %cl, %ax /* # of bytes left on this track */ + movw %ax, %bx /* transfer length */ + addw %bp, %ax /* cross 64K boundary? */ + jnc 1f /* ok. */ + jz 1f /* also ok. */ + /* + * Oops, we are crossing 64K boundary... + * Adjust transfer length to make transfer fit in the boundary. + * + * Note: sector size is assumed to be a measure of 65536. + */ + xorw %bx, %bx + subw %bp, %bx +1: pushw %dx + movw $dot_msg, %si /* give progress message */ + call print + xchgw %ax, %dx + movb $0, %ah + divb sectors + xchgb %al, %ah + xchgw %ax, %dx /* %dh = head # / %dl = sector # */ + incb %dl /* fix %dl to 1-based */ + pushw %cx + movw cylinder, %cx + movb $0xd6, %ah /* read, multi-track, seek, MFM */ + movb %ss:DISK_BOOT, %al + int $0x1b + popw %cx + popw %dx + jc read_error + movw %bx, %ax /* # of bytes just read */ + shrw %cl, %ax /* %ax = # of sectors just read */ + addb %al, %dl /* advance sector # */ + cmpb %ch, %dl /* %ch = # of sectors/cylinder */ + jb 2f + incb cylinder /* next cylinder */ + xorb %dl, %dl /* sector 0 */ +2: addw %bx, %bp /* advance offset pointer */ + jnc rp_read + /* offset pointer wrapped; advance segment pointer. */ + movw %es, %ax + addw $0x1000, %ax + movw %ax, %es + jmp rp_read_newseg + +read_error: + ret + +boot: movw %cs, %ax /* = INITSEG */ + /* movw %ax, %ds */ + movw %ax, %ss + movw $0x4000, %sp /* 0x4000 is arbitrary value >= + * length of bootsect + length of + * setup + room for stack; + * PC-9800 never have BIOS workareas + * on high memory. + */ +/* + * After that we check which root-device to use. If the device is + * not defined, /dev/fd0 (2, 0) will be used. + */ + cmpw $0, root_dev + jne 3f + movb $2, root_dev+1 +3: + +/* + * After that (everything loaded), we jump to the setup-routine + * loaded directly after the bootblock: + */ + ljmp $SETUPSEG, $0 + +/* + * Subroutine for print string on console. + * %cs:%si - pointer to message + */ +print: + pushaw + pushw %ds + pushw %es + pushw %cs + popw %ds + lesw curpos, %di /* %es:%di = current text VRAM addr. */ +1: xorw %ax, %ax + lodsb + testb %al, %al + jz 2f /* end of string */ + stosw /* character code */ + movb $0xE1, %es:0x2000-2(%di) /* character attribute */ + jmp 1b +2: movw %di, %dx + movb $0x13, %ah + int $0x18 /* move cursor to current point */ + popw %es + popw %ds + popaw + ret + +loading_msg: + .string "Loading" +dot_msg: + .string "." +error_msg: + .string "Read Error!" + + .org 490 + +curpos: .word 160 /* current cursor position */ +vram: .word NORMAL_TEXT /* text VRAM segment */ + +cylinder: .byte 0 /* current cylinder (lower byte) */ +sectlen: .byte 0 /* (log2 of ) - 7 */ +sectors: .byte 0x0F /* default is 2HD (15 sector/track) */ + +# XXX: This is a fairly snug fit. + +.org 497 +setup_sects: .byte SETUPSECTS +root_flags: .word ROOT_RDONLY +syssize: .word SYSSIZE +swap_dev: .word SWAP_DEV +ram_size: .word RAMDISK +vid_mode: .word SVGA_MODE +root_dev: .word ROOT_DEV +boot_flag: .word 0xAA55 diff -urN linux-2.5.65-bk2/arch/i386/boot98/compressed/Makefile linux-2.5.65-bk3/arch/i386/boot98/compressed/Makefile --- linux-2.5.65-bk2/arch/i386/boot98/compressed/Makefile Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/boot98/compressed/Makefile Mon Mar 31 12:41:39 2003 @@ -0,0 +1,25 @@ +# +# linux/arch/i386/boot/compressed/Makefile +# +# create a compressed vmlinux image from the original vmlinux +# + +EXTRA_TARGETS := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o +EXTRA_AFLAGS := -traditional + +LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32 + +$(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE + $(call if_changed,ld) + @: + +$(obj)/vmlinux.bin: vmlinux FORCE + $(call if_changed,objcopy) + +$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE + $(call if_changed,gzip) + +LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T + +$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE + $(call if_changed,ld) diff -urN linux-2.5.65-bk2/arch/i386/boot98/compressed/head.S linux-2.5.65-bk3/arch/i386/boot98/compressed/head.S --- linux-2.5.65-bk2/arch/i386/boot98/compressed/head.S Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/boot98/compressed/head.S Mon Mar 31 12:41:39 2003 @@ -0,0 +1,128 @@ +/* + * linux/boot/head.S + * + * Copyright (C) 1991, 1992, 1993 Linus Torvalds + */ + +/* + * head.S contains the 32-bit startup code. + * + * NOTE!!! Startup happens at absolute address 0x00001000, which is also where + * the page directory will exist. The startup code will be overwritten by + * the page directory. [According to comments etc elsewhere on a compressed + * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC] + * + * Page 0 is deliberately kept safe, since System Management Mode code in + * laptops may need to access the BIOS data stored there. This is also + * useful for future device drivers that either access the BIOS via VM86 + * mode. + */ + +/* + * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 + */ +.text + +#include +#include + + .globl startup_32 + +startup_32: + cld + cli + movl $(__BOOT_DS),%eax + movl %eax,%ds + movl %eax,%es + movl %eax,%fs + movl %eax,%gs + + lss stack_start,%esp + xorl %eax,%eax +1: incl %eax # check that A20 really IS enabled + movl %eax,0x000000 # loop forever if it isn't + cmpl %eax,0x100000 + je 1b + +/* + * Initialize eflags. Some BIOS's leave bits like NT set. This would + * confuse the debugger if this code is traced. + * XXX - best to initialize before switching to protected mode. + */ + pushl $0 + popfl +/* + * Clear BSS + */ + xorl %eax,%eax + movl $_edata,%edi + movl $_end,%ecx + subl %edi,%ecx + cld + rep + stosb +/* + * Do the decompression, and jump to the new kernel.. + */ + subl $16,%esp # place for structure on the stack + movl %esp,%eax + pushl %esi # real mode pointer as second arg + pushl %eax # address of structure as first arg + call decompress_kernel + orl %eax,%eax + jnz 3f + popl %esi # discard address + popl %esi # real mode pointer + xorl %ebx,%ebx + ljmp $(__BOOT_CS), $0x100000 + +/* + * We come here, if we were loaded high. + * We need to move the move-in-place routine down to 0x1000 + * and then start it with the buffer addresses in registers, + * which we got from the stack. + */ +3: + movl $move_routine_start,%esi + movl $0x1000,%edi + movl $move_routine_end,%ecx + subl %esi,%ecx + addl $3,%ecx + shrl $2,%ecx + cld + rep + movsl + + popl %esi # discard the address + popl %ebx # real mode pointer + popl %esi # low_buffer_start + popl %ecx # lcount + popl %edx # high_buffer_start + popl %eax # hcount + movl $0x100000,%edi + cli # make sure we don't get interrupted + ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine + +/* + * Routine (template) for moving the decompressed kernel in place, + * if we were high loaded. This _must_ PIC-code ! + */ +move_routine_start: + movl %ecx,%ebp + shrl $2,%ecx + rep + movsl + movl %ebp,%ecx + andl $3,%ecx + rep + movsb + movl %edx,%esi + movl %eax,%ecx # NOTE: rep movsb won't move if %ecx == 0 + addl $3,%ecx + shrl $2,%ecx + rep + movsl + movl %ebx,%esi # Restore setup pointer + xorl %ebx,%ebx + ljmp $(__BOOT_CS), $0x100000 +move_routine_end: diff -urN linux-2.5.65-bk2/arch/i386/boot98/compressed/misc.c linux-2.5.65-bk3/arch/i386/boot98/compressed/misc.c --- linux-2.5.65-bk2/arch/i386/boot98/compressed/misc.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/boot98/compressed/misc.c Mon Mar 31 12:41:39 2003 @@ -0,0 +1,379 @@ +/* + * misc.c + * + * This is a collection of several routines from gzip-1.0.3 + * adapted for Linux. + * + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + * puts by Nick Holloway 1993, better puts by Martin Mares 1995 + * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 + */ + +#include +#include +#include +#include +#ifdef STANDARD_MEMORY_BIOS_CALL +#undef STANDARD_MEMORY_BIOS_CALL +#endif + +/* + * gzip declarations + */ + +#define OF(args) args +#define STATIC static + +#undef memset +#undef memcpy + +/* + * Why do we do this? Don't ask me.. + * + * Incomprehensible are the ways of bootloaders. + */ +static void* memset(void *, int, size_t); +static void* memcpy(void *, __const void *, size_t); +#define memzero(s, n) memset ((s), 0, (n)) + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +#define WSIZE 0x8000 /* Window size must be at least 32k, */ + /* and a power of two */ + +static uch *inbuf; /* input buffer */ +static uch window[WSIZE]; /* Sliding window buffer */ + +static unsigned insize = 0; /* valid bytes in inbuf */ +static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ +static unsigned outcnt = 0; /* bytes in output buffer */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) + +/* Diagnostic functions */ +#ifdef DEBUG +# define Assert(cond,msg) {if(!(cond)) error(msg);} +# define Trace(x) fprintf x +# define Tracev(x) {if (verbose) fprintf x ;} +# define Tracevv(x) {if (verbose>1) fprintf x ;} +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +static int fill_inbuf(void); +static void flush_window(void); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +/* + * This is set up by the setup-routine at boot-time + */ +static unsigned char *real_mode; /* Pointer to real-mode data */ + +#define EXT_MEM_K (*(unsigned short *)(real_mode + 0x2)) +#ifndef STANDARD_MEMORY_BIOS_CALL +#define ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0)) +#endif +#define SCREEN_INFO (*(struct screen_info *)(real_mode+0)) + +extern char input_data[]; +extern int input_len; + +static long bytes_out = 0; +static uch *output_data; +static unsigned long output_ptr = 0; + +static void *malloc(int size); +static void free(void *where); + +static void puts(const char *); + +extern int end; +static long free_mem_ptr = (long)&end; +static long free_mem_end_ptr; + +#define INPLACE_MOVE_ROUTINE 0x1000 +#define LOW_BUFFER_START 0x2000 +#define LOW_BUFFER_MAX 0x90000 +#define HEAP_SIZE 0x3000 +static unsigned int low_buffer_end, low_buffer_size; +static int high_loaded =0; +static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/; + +static char *vidmem = (char *)0xa0000; +static int lines, cols; + +#ifdef CONFIG_X86_NUMAQ +static void * xquad_portio = NULL; +#endif + +#include "../../../../lib/inflate.c" + +static void *malloc(int size) +{ + void *p; + + if (size <0) error("Malloc error\n"); + if (free_mem_ptr <= 0) error("Memory error\n"); + + free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ + + p = (void *)free_mem_ptr; + free_mem_ptr += size; + + if (free_mem_ptr >= free_mem_end_ptr) + error("\nOut of memory\n"); + + return p; +} + +static void free(void *where) +{ /* Don't care */ +} + +static void gzip_mark(void **ptr) +{ + *ptr = (void *) free_mem_ptr; +} + +static void gzip_release(void **ptr) +{ + free_mem_ptr = (long) *ptr; +} + +static void scroll(void) +{ + int i; + + memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 ); + for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 ) + vidmem[i] = ' '; +} + +static void puts(const char *s) +{ + int x,y,pos; + char c; + + x = SCREEN_INFO.orig_x; + y = SCREEN_INFO.orig_y; + + while ( ( c = *s++ ) != '\0' ) { + if ( c == '\n' ) { + x = 0; + if ( ++y >= lines ) { + scroll(); + y--; + } + } else { + vidmem [ ( x + cols * y ) * 2 ] = c; + if ( ++x >= cols ) { + x = 0; + if ( ++y >= lines ) { + scroll(); + y--; + } + } + } + } + + SCREEN_INFO.orig_x = x; + SCREEN_INFO.orig_y = y; + + pos = x + cols * y; /* Update cursor position */ + while (!(inb_p(0x60) & 4)); + outb_p(0x49, 0x62); + outb_p(pos & 0xff, 0x60); + outb_p((pos >> 8) & 0xff, 0x60); +} + +static void* memset(void* s, int c, size_t n) +{ + int i; + char *ss = (char*)s; + + for (i=0;i> 8); + } + crc = c; + bytes_out += (ulg)outcnt; + output_ptr += (ulg)outcnt; + outcnt = 0; +} + +static void flush_window_high(void) +{ + ulg c = crc; /* temporary variable */ + unsigned n; + uch *in, ch; + in = window; + for (n = 0; n < outcnt; n++) { + ch = *output_data++ = *in++; + if ((ulg)output_data == low_buffer_end) output_data=high_buffer_start; + c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); + } + crc = c; + bytes_out += (ulg)outcnt; + outcnt = 0; +} + +static void flush_window(void) +{ + if (high_loaded) flush_window_high(); + else flush_window_low(); +} + +static void error(char *x) +{ + puts("\n\n"); + puts(x); + puts("\n\n -- System halted"); + + while(1); /* Halt */ +} + +#define STACK_SIZE (4096) + +long user_stack [STACK_SIZE]; + +struct { + long * a; + short b; + } stack_start = { & user_stack [STACK_SIZE] , __BOOT_DS }; + +static void setup_normal_output_buffer(void) +{ +#ifdef STANDARD_MEMORY_BIOS_CALL + if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n"); +#else + if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.\n"); +#endif + output_data = (char *)0x100000; /* Points to 1M */ + free_mem_end_ptr = (long)real_mode; +} + +struct moveparams { + uch *low_buffer_start; int lcount; + uch *high_buffer_start; int hcount; +}; + +static void setup_output_buffer_if_we_run_high(struct moveparams *mv) +{ + high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE); +#ifdef STANDARD_MEMORY_BIOS_CALL + if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory.\n"); +#else + if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory.\n"); +#endif + mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START; + low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX + ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff; + low_buffer_size = low_buffer_end - LOW_BUFFER_START; + high_loaded = 1; + free_mem_end_ptr = (long)high_buffer_start; + if ( (0x100000 + low_buffer_size) > ((ulg)high_buffer_start)) { + high_buffer_start = (uch *)(0x100000 + low_buffer_size); + mv->hcount = 0; /* say: we need not to move high_buffer */ + } + else mv->hcount = -1; + mv->high_buffer_start = high_buffer_start; +} + +static void close_output_buffer_if_we_run_high(struct moveparams *mv) +{ + if (bytes_out > low_buffer_size) { + mv->lcount = low_buffer_size; + if (mv->hcount) + mv->hcount = bytes_out - low_buffer_size; + } else { + mv->lcount = bytes_out; + mv->hcount = 0; + } +} + + +asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode) +{ + real_mode = rmode; + + vidmem = (char *)(((unsigned int)SCREEN_INFO.orig_video_page) << 4); + + lines = SCREEN_INFO.orig_video_lines; + cols = SCREEN_INFO.orig_video_cols; + + if (free_mem_ptr < 0x100000) setup_normal_output_buffer(); + else setup_output_buffer_if_we_run_high(mv); + + makecrc(); + puts("Uncompressing Linux... "); + gunzip(); + puts("Ok, booting the kernel.\n"); + if (high_loaded) close_output_buffer_if_we_run_high(mv); + return high_loaded; +} + +/* We don't actually check for stack overflows this early. */ +__asm__(".globl mcount ; mcount: ret\n"); + diff -urN linux-2.5.65-bk2/arch/i386/boot98/compressed/vmlinux.scr linux-2.5.65-bk3/arch/i386/boot98/compressed/vmlinux.scr --- linux-2.5.65-bk2/arch/i386/boot98/compressed/vmlinux.scr Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/boot98/compressed/vmlinux.scr Mon Mar 31 12:41:39 2003 @@ -0,0 +1,9 @@ +SECTIONS +{ + .data : { + input_len = .; + LONG(input_data_end - input_data) input_data = .; + *(.data) + input_data_end = .; + } +} diff -urN linux-2.5.65-bk2/arch/i386/boot98/install.sh linux-2.5.65-bk3/arch/i386/boot98/install.sh --- linux-2.5.65-bk2/arch/i386/boot98/install.sh Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/boot98/install.sh Mon Mar 31 12:41:39 2003 @@ -0,0 +1,40 @@ +#!/bin/sh +# +# arch/i386/boot/install.sh +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1995 by Linus Torvalds +# +# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin +# +# "make install" script for i386 architecture +# +# Arguments: +# $1 - kernel version +# $2 - kernel image file +# $3 - kernel map file +# $4 - default install path (blank if root directory) +# + +# User may have a custom install script + +if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi +if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi + +# Default install - same as make zlilo + +if [ -f $4/vmlinuz ]; then + mv $4/vmlinuz $4/vmlinuz.old +fi + +if [ -f $4/System.map ]; then + mv $4/System.map $4/System.old +fi + +cat $2 > $4/vmlinuz +cp $3 $4/System.map + +if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi diff -urN linux-2.5.65-bk2/arch/i386/boot98/setup.S linux-2.5.65-bk3/arch/i386/boot98/setup.S --- linux-2.5.65-bk2/arch/i386/boot98/setup.S Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/boot98/setup.S Mon Mar 31 12:41:39 2003 @@ -0,0 +1,961 @@ +/* + * setup.S Copyright (C) 1991, 1992 Linus Torvalds + * + * setup.s is responsible for getting the system data from the BIOS, + * and putting them into the appropriate places in system memory. + * both setup.s and system has been loaded by the bootblock. + * + * This code asks the bios for memory/disk/other parameters, and + * puts them in a "safe" place: 0x90000-0x901FF, ie where the + * boot-block used to be. It is then up to the protected mode + * system to read them from there before the area is overwritten + * for buffer-blocks. + * + * Move PS/2 aux init code to psaux.c + * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 + * + * some changes and additional features by Christoph Niemann, + * March 1993/June 1994 (Christoph.Niemann@linux.org) + * + * add APM BIOS checking by Stephen Rothwell, May 1994 + * (sfr@canb.auug.org.au) + * + * High load stuff, initrd support and position independency + * by Hans Lermen & Werner Almesberger, February 1996 + * , + * + * Video handling moved to video.S by Martin Mares, March 1996 + * + * + * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david + * parsons) to avoid loadlin confusion, July 1997 + * + * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. + * + * + * Fix to work around buggy BIOSes which dont use carry bit correctly + * and/or report extended memory in CX/DX for e801h memory size detection + * call. As a result the kernel got wrong figures. The int15/e801h docs + * from Ralf Brown interrupt list seem to indicate AX/BX should be used + * anyway. So to avoid breaking many machines (presumably there was a reason + * to orginally use CX/DX instead of AX/BX), we do a kludge to see + * if CX/DX have been changed in the e801 call and if so use AX/BX . + * Michael Miller, April 2001 + * + * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes + * by Robert Schwebel, December 2001 + * + * Heavily modified for NEC PC-9800 series by Kyoto University Microcomputer + * Club (KMC) Linux/98 project , 1997-1999 + */ + +#include +#include +#include +#include +#include +#include +#include + +/* Signature words to ensure LILO loaded us right */ +#define SIG1 0xAA55 +#define SIG2 0x5A5A + +#define HIRESO_TEXT 0xe000 +#define NORMAL_TEXT 0xa000 + +#define BIOS_FLAG2 0x0400 +#define BIOS_FLAG5 0x0458 +#define RDISK_EQUIP 0x0488 +#define BIOS_FLAG 0x0501 +#define KB_SHFT_STS 0x053a +#define DISK_EQUIP 0x055c + +INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way +SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536). +SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment + # ... and the former contents of CS + +DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020 + +.code16 +.globl begtext, begdata, begbss, endtext, enddata, endbss + +.text +begtext: +.data +begdata: +.bss +begbss: +.text + +start: + jmp trampoline + +# This is the setup header, and it must start at %cs:2 (old 0x9020:2) + + .ascii "HdrS" # header signature + .word 0x0203 # header version number (>= 0x0105) + # or else old loadlin-1.5 will fail) +realmode_swtch: .word 0, 0 # default_switch, SETUPSEG +start_sys_seg: .word SYSSEG + .word kernel_version # pointing to kernel version string + # above section of header is compatible + # with loadlin-1.5 (header v1.5). Don't + # change it. + +type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, + # Bootlin, SYSLX, bootsect...) + # See Documentation/i386/boot.txt for + # assigned ids + +# flags, unused bits must be zero (RFU) bit within loadflags +loadflags: +LOADED_HIGH = 1 # If set, the kernel is loaded high +CAN_USE_HEAP = 0x80 # If set, the loader also has set + # heap_end_ptr to tell how much + # space behind setup.S can be used for + # heap purposes. + # Only the loader knows what is free +#ifndef __BIG_KERNEL__ + .byte 0 +#else + .byte LOADED_HIGH +#endif + +setup_move_size: .word 0x8000 # size to move, when setup is not + # loaded at 0x90000. We will move setup + # to 0x90000 then just before jumping + # into the kernel. However, only the + # loader knows how much data behind + # us also needs to be loaded. + +code32_start: # here loaders can put a different + # start address for 32-bit code. +#ifndef __BIG_KERNEL__ + .long 0x1000 # 0x1000 = default for zImage +#else + .long 0x100000 # 0x100000 = default for big kernel +#endif + +ramdisk_image: .long 0 # address of loaded ramdisk image + # Here the loader puts the 32-bit + # address where it loaded the image. + # This only will be read by the kernel. + +ramdisk_size: .long 0 # its size in bytes + +bootsect_kludge: + .word bootsect_helper, SETUPSEG + +heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) + # space from here (exclusive) down to + # end of setup code can be used by setup + # for local heap purposes. + +pad1: .word 0 +cmd_line_ptr: .long 0 # (Header version 0x0202 or later) + # If nonzero, a 32-bit pointer + # to the kernel command line. + # The command line should be + # located between the start of + # setup and the end of low + # memory (0xa0000), or it may + # get overwritten before it + # gets read. If this field is + # used, there is no longer + # anything magical about the + # 0x90000 segment; the setup + # can be located anywhere in + # low memory 0x10000 or higher. + +ramdisk_max: .long __MAXMEM-1 # (Header version 0x0203 or later) + # The highest safe address for + # the contents of an initrd + +trampoline: call start_of_setup + .space 1024 +# End of setup header ##################################################### + +start_of_setup: +# Set %ds = %cs, we know that SETUPSEG = %cs at this point + movw %cs, %ax # aka SETUPSEG + movw %ax, %ds +# Check signature at end of setup + cmpw $SIG1, setup_sig1 + jne bad_sig + + cmpw $SIG2, setup_sig2 + jne bad_sig + + jmp good_sig1 + +# Routine to print asciiz string at ds:si +prtstr: + lodsb + andb %al, %al + jz fin + + call prtchr + jmp prtstr + +fin: ret + +no_sig_mess: .string "No setup signature found ..." + +good_sig1: + jmp good_sig + +# We now have to find the rest of the setup code/data +bad_sig: + movw %cs, %ax # SETUPSEG + subw $DELTA_INITSEG, %ax # INITSEG + movw %ax, %ds + xorb %bh, %bh + movb (497), %bl # get setup sect from bootsect + subw $4, %bx # LILO loads 4 sectors of setup + shlw $8, %bx # convert to words (1sect=2^8 words) + movw %bx, %cx + shrw $3, %bx # convert to segment + addw $SYSSEG, %bx + movw %bx, %cs:start_sys_seg +# Move rest of setup code/data to here + movw $2048, %di # four sectors loaded by LILO + subw %si, %si + pushw %cs + popw %es + movw $SYSSEG, %ax + movw %ax, %ds + rep + movsw + movw %cs, %ax # aka SETUPSEG + movw %ax, %ds + cmpw $SIG1, setup_sig1 + jne no_sig + + cmpw $SIG2, setup_sig2 + jne no_sig + + jmp good_sig + +no_sig: + lea no_sig_mess, %si + call prtstr + +no_sig_loop: + hlt + jmp no_sig_loop + +good_sig: + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %ds +# Check if an old loader tries to load a big-kernel + testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel? + jz loader_ok # No, no danger for old loaders. + + cmpb $0, %cs:type_of_loader # Do we have a loader that + # can deal with us? + jnz loader_ok # Yes, continue. + + pushw %cs # No, we have an old loader, + popw %ds # die. + lea loader_panic_mess, %si + call prtstr + + jmp no_sig_loop + +loader_panic_mess: .string "Wrong loader, giving up..." + +loader_ok: +# Get memory size (extended mem, kB) + +# On PC-9800, memory size detection is done completely in 32-bit +# kernel initialize code (kernel/setup.c). + pushw %es + xorl %eax, %eax + movw %ax, %es + movb %al, (E820NR) # PC-9800 has no E820 + movb %es:(0x401), %al + shll $7, %eax + addw $1024, %ax + movw %ax, (2) + movl %eax, (0x1e0) + movw %es:(0x594), %ax + shll $10, %eax + addl %eax, (0x1e0) + popw %es + +# Check for video adapter and its parameters and allow the +# user to browse video modes. + call video # NOTE: we need %ds pointing + # to bootsector + +# Get text video mode + movb $0x0B, %ah + int $0x18 # CRT mode sense + movw $(20 << 8) + 40, %cx + testb $0x10, %al + jnz 3f + movb $20, %ch + testb $0x01, %al + jnz 1f + movb $25, %ch + jmp 1f +3: # If bit 4 was 1, it means either 1) 31 lines for hi-reso mode, + # or 2) 30 lines for PC-9821. + movb $31, %ch # hireso mode value + pushw $0 + popw %es + testb $0x08, %es:BIOS_FLAG + jnz 1f + movb $30, %ch +1: # Now we got # of rows in %ch + movb %ch, (14) + + testb $0x02, %al + jnz 2f + movb $80, %cl +2: # Now we got # of columns in %cl + movb %cl, (7) + + # Next, get horizontal frequency if supported + movw $0x3100, %ax + int $0x18 # Call CRT bios + movb %al, (6) # If 31h is unsupported, %al remains 0 + +# Get hd0-3 data... + pushw %ds # aka INITSEG + popw %es + xorw %ax, %ax + movw %ax, %ds + cld + movw $0x0080, %di + movb DISK_EQUIP+1, %ah + movb $0x80, %al + +get_hd_info: + shrb %ah + pushw %ax + jnc 1f + movb $0x84, %ah + int $0x1b + jnc 2f # Success +1: xorw %cx, %cx # `0 cylinders' means no drive +2: # Attention! Work area (drive_info) is arranged for PC-9800. + movw %cx, %ax # # of cylinders + stosw + movw %dx, %ax # # of sectors / # of heads + stosw + movw %bx, %ax # sector size in bytes + stosw + popw %ax + incb %al + cmpb $0x84, %al + jb get_hd_info + +# Get fd data... + movw DISK_EQUIP, %ax + andw $0xf00f, %ax + orb %al, %ah + movb RDISK_EQUIP, %al + notb %al + andb %al, %ah # ignore all `RAM drive' + + movb $0x30, %al + +get_fd_info: + shrb %ah + pushw %ax + jnc 1f + movb $0xc4, %ah + int $0x1b + movb %ah, %al + andb $4, %al # 1.44MB support flag + shrb %al + addb $2, %al # %al = 2 (1.2MB) or 4 (1.44MB) + jmp 2f +1: movb $0, %al # no drive +2: stosb + popw %ax + incb %al + testb $0x04, %al + jz get_fd_info + + addb $(0xb0 - 0x34), %al + jnc get_fd_info # check FDs on 640KB I/F + + pushw %es + popw %ds # %ds got bootsector again +#if 0 + mov $0, (0x1ff) # default is no pointing device +#endif + +#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) +# Then check for an APM BIOS... + # %ds points to the bootsector + movw $0, 0x40 # version = 0 means no APM BIOS + movw $0x09a00, %ax # APM BIOS installation check + xorw %bx, %bx + int $0x1f + jc done_apm_bios # Nope, no APM BIOS + + cmpw $0x0504d, %bx # Check for "PM" signature + jne done_apm_bios # No signature, no APM BIOS + + testb $0x02, %cl # Is 32 bit supported? + je done_apm_bios # No 32-bit, no (good) APM BIOS + + movw $0x09a04, %ax # Disconnect first just in case + xorw %bx, %bx + int $0x1f # ignore return code + movw $0x09a03, %ax # 32 bit connect + xorl %ebx, %ebx + int $0x1f + jc no_32_apm_bios # Ack, error. + + movw %ax, (66) # BIOS code segment + movl %ebx, (68) # BIOS entry point offset + movw %cx, (72) # BIOS 16 bit code segment + movw %dx, (74) # BIOS data segment + movl %esi, (78) # BIOS code segment length + movw %di, (82) # BIOS data segment length +# Redo the installation check as the 32 bit connect +# modifies the flags returned on some BIOSs + movw $0x09a00, %ax # APM BIOS installation check + xorw %bx, %bx + int $0x1f + jc apm_disconnect # error -> shouldn't happen + + cmpw $0x0504d, %bx # check for "PM" signature + jne apm_disconnect # no sig -> shouldn't happen + + movw %ax, (64) # record the APM BIOS version + movw %cx, (76) # and flags + jmp done_apm_bios + +apm_disconnect: # Tidy up + movw $0x09a04, %ax # Disconnect + xorw %bx, %bx + int $0x1f # ignore return code + + jmp done_apm_bios + +no_32_apm_bios: + andw $0xfffd, (76) # remove 32 bit support bit +done_apm_bios: +#endif + +# Pass cursor position to kernel... + movw %cs:cursor_address, %ax + shrw %ax # cursor_address is 2 bytes unit + movb $80, %cl + divb %cl + xchgb %al, %ah # (0) = %al = X, (1) = %ah = Y + movw %ax, (0) + +#if 0 + movw $msg_cpos, %si + call prtstr_cs + call prthex + call prtstr_cs + movw %ds, %ax + call prthex + call prtstr_cs + movb $0x11, %ah + int $0x18 + movb $0, %ah + int $0x18 + .section .rodata, "a" +msg_cpos: .string "Cursor position: 0x" + .string ", %ds:0x" + .string "\r\n" + .previous +#endif + +# Now we want to move to protected mode ... + cmpw $0, %cs:realmode_swtch + jz rmodeswtch_normal + + lcall *%cs:realmode_swtch + + jmp rmodeswtch_end + +rmodeswtch_normal: + pushw %cs + call default_switch + +rmodeswtch_end: +# we get the code32 start address and modify the below 'jmpi' +# (loader may have changed it) + movl %cs:code32_start, %eax + movl %eax, %cs:code32 + +# Now we move the system to its rightful place ... but we check if we have a +# big-kernel. In that case we *must* not move it ... + testb $LOADED_HIGH, %cs:loadflags + jz do_move0 # .. then we have a normal low + # loaded zImage + # .. or else we have a high + # loaded bzImage + jmp end_move # ... and we skip moving + +do_move0: + movw $0x100, %ax # start of destination segment + movw %cs, %bp # aka SETUPSEG + subw $DELTA_INITSEG, %bp # aka INITSEG + movw %cs:start_sys_seg, %bx # start of source segment + cld +do_move: + movw %ax, %es # destination segment + incb %ah # instead of add ax,#0x100 + movw %bx, %ds # source segment + addw $0x100, %bx + subw %di, %di + subw %si, %si + movw $0x800, %cx + rep + movsw + cmpw %bp, %bx # assume start_sys_seg > 0x200, + # so we will perhaps read one + # page more than needed, but + # never overwrite INITSEG + # because destination is a + # minimum one page below source + jb do_move + +end_move: +# then we load the segment descriptors + movw %cs, %ax # aka SETUPSEG + movw %ax, %ds + +# Check whether we need to be downward compatible with version <=201 + cmpl $0, cmd_line_ptr + jne end_move_self # loader uses version >=202 features + cmpb $0x20, type_of_loader + je end_move_self # bootsect loader, we know of it + +# Boot loader does not support boot protocol version 2.02. +# If we have our code not at 0x90000, we need to move it there now. +# We also then need to move the params behind it (commandline) +# Because we would overwrite the code on the current IP, we move +# it in two steps, jumping high after the first one. + movw %cs, %ax + cmpw $SETUPSEG, %ax + je end_move_self + + cli # make sure we really have + # interrupts disabled ! + # because after this the stack + # should not be used + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ss, %dx + cmpw %ax, %dx + jb move_self_1 + + addw $INITSEG, %dx + subw %ax, %dx # this will go into %ss after + # the move +move_self_1: + movw %ax, %ds + movw $INITSEG, %ax # real INITSEG + movw %ax, %es + movw %cs:setup_move_size, %cx + std # we have to move up, so we use + # direction down because the + # areas may overlap + movw %cx, %di + decw %di + movw %di, %si + subw $move_self_here+0x200, %cx + rep + movsb + ljmp $SETUPSEG, $move_self_here + +move_self_here: + movw $move_self_here+0x200, %cx + rep + movsb + movw $SETUPSEG, %ax + movw %ax, %ds + movw %dx, %ss + +end_move_self: # now we are at the right place + lidt idt_48 # load idt with 0,0 + xorl %eax, %eax # Compute gdt_base + movw %ds, %ax # (Convert %ds:gdt to a linear ptr) + shll $4, %eax + addl $gdt, %eax + movl %eax, (gdt_48+2) + lgdt gdt_48 # load gdt with whatever is + # appropriate + +# that was painless, now we enable A20 + + outb %al, $0xf2 # A20 on + movb $0x02, %al + outb %al, $0xf6 # also A20 on; making ITF's + # way our model + + # PC-9800 seems to enable A20 at the moment of `outb'; + # so we don't wait unlike IBM PCs (see ../setup.S). + +# enable DMA to access memory over 0x100000 (1MB). + + movw $0x439, %dx + inb %dx, %al + andb $(~4), %al + outb %al, %dx + +# Set DMA to increment its bank address automatically at 16MB boundary. +# Initial setting is 64KB boundary mode so that we can't run DMA crossing +# physical address 0xXXXXFFFF. + + movb $0x0c, %al + outb %al, $0x29 # ch. 0 + movb $0x0d, %al + outb %al, $0x29 # ch. 1 + movb $0x0e, %al + outb %al, $0x29 # ch. 2 + movb $0x0f, %al + outb %al, $0x29 # ch. 3 + movb $0x50, %al + outb %al, $0x11 # reinitialize DMAC + +# make sure any possible coprocessor is properly reset.. + movb $0, %al + outb %al, $0xf8 + outb %al, $0x5f # delay + +# well, that went ok, I hope. Now we mask all interrupts - the rest +# is done in init_IRQ(). + movb $0xFF, %al # mask all interrupts for now + outb %al, $0x0A + outb %al, $0x5f # delay + + movb $0x7F, %al # mask all irq's but irq7 which + outb %al, $0x02 # is cascaded + +# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't +# need no steenking BIOS anyway (except for the initial loading :-). +# The BIOS-routine wants lots of unnecessary data, and it's less +# "interesting" anyway. This is how REAL programmers do it. +# +# Well, now's the time to actually move into protected mode. To make +# things as simple as possible, we do no register set-up or anything, +# we let the gnu-compiled 32-bit programs do that. We just jump to +# absolute address 0x1000 (or the loader supplied one), +# in 32-bit protected mode. +# +# Note that the short jump isn't strictly needed, although there are +# reasons why it might be a good idea. It won't hurt in any case. + movw $1, %ax # protected mode (PE) bit + lmsw %ax # This is it! + jmp flush_instr + +flush_instr: + xorw %bx, %bx # Flag to indicate a boot + xorl %esi, %esi # Pointer to real-mode code + movw %cs, %si + subw $DELTA_INITSEG, %si + shll $4, %esi # Convert to 32-bit pointer +# NOTE: For high loaded big kernels we need a +# jmpi 0x100000,__BOOT_CS +# +# but we yet haven't reloaded the CS register, so the default size +# of the target offset still is 16 bit. +# However, using an operand prefix (0x66), the CPU will properly +# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference +# Manual, Mixing 16-bit and 32-bit code, page 16-6) + + .byte 0x66, 0xea # prefix + jmpi-opcode +code32: .long 0x1000 # will be set to 0x100000 + # for big kernels + .word __BOOT_CS + +# Here's a bunch of information about your current kernel.. +kernel_version: .ascii UTS_RELEASE + .ascii " (" + .ascii LINUX_COMPILE_BY + .ascii "@" + .ascii LINUX_COMPILE_HOST + .ascii ") " + .ascii UTS_VERSION + .byte 0 + +# This is the default real mode switch routine. +# to be called just before protected mode transition +default_switch: + cli # no interrupts allowed ! + outb %al, $0x50 # disable NMI for bootup + # sequence + lret + +# This routine only gets called, if we get loaded by the simple +# bootsect loader _and_ have a bzImage to load. +# Because there is no place left in the 512 bytes of the boot sector, +# we must emigrate to code space here. +bootsect_helper: + cmpw $0, %cs:bootsect_es + jnz bootsect_second + + movb $0x20, %cs:type_of_loader + movw %es, %ax + shrw $4, %ax + movb %ah, %cs:bootsect_src_base+2 + movw %es, %ax + movw %ax, %cs:bootsect_es + subw $SYSSEG, %ax + lret # nothing else to do for now + +bootsect_second: + pushw %bx + pushw %cx + pushw %si + pushw %di + testw %bp, %bp # 64K full ? + jne bootsect_ex + + xorw %cx, %cx # zero means full 64K + pushw %cs + popw %es + movw $bootsect_gdt, %bx + xorw %si, %si # source address + xorw %di, %di # destination address + movb $0x90, %ah + int $0x1f + jc bootsect_panic # this, if INT1F fails + + movw %cs:bootsect_es, %es # we reset %es to always point + incb %cs:bootsect_dst_base+2 # to 0x10000 +bootsect_ex: + movb %cs:bootsect_dst_base+2, %ah + shlb $4, %ah # we now have the number of + # moved frames in %ax + xorb %al, %al + popw %di + popw %si + popw %cx + popw %bx + lret + +bootsect_gdt: + .word 0, 0, 0, 0 + .word 0, 0, 0, 0 + +bootsect_src: + .word 0xffff + +bootsect_src_base: + .byte 0x00, 0x00, 0x01 # base = 0x010000 + .byte 0x93 # typbyte + .word 0 # limit16,base24 =0 + +bootsect_dst: + .word 0xffff + +bootsect_dst_base: + .byte 0x00, 0x00, 0x10 # base = 0x100000 + .byte 0x93 # typbyte + .word 0 # limit16,base24 =0 + .word 0, 0, 0, 0 # BIOS CS + .word 0, 0, 0, 0 # BIOS DS + +bootsect_es: + .word 0 + +bootsect_panic: + pushw %cs + popw %ds + cld + leaw bootsect_panic_mess, %si + call prtstr + +bootsect_panic_loop: + jmp bootsect_panic_loop + +bootsect_panic_mess: + .string "INT1F refuses to access high mem, giving up." + +# This routine prints one character (in %al) on console. +# PC-9800 doesn't have BIOS-function to do it like IBM PC's INT 10h - 0Eh, +# so we hardcode `prtchr' subroutine here. +prtchr: + pushaw + pushw %es + cmpb $0, %cs:prtchr_initialized + jnz prtchr_ok + xorw %cx, %cx + movw %cx, %es + testb $0x8, %es:BIOS_FLAG + jz 1f + movb $(HIRESO_TEXT >> 8), %cs:cursor_address+3 + movw $(80 * 31 * 2), %cs:max_cursor_offset +1: pushw %ax + call get_cursor_position + movw %ax, %cs:cursor_address + popw %ax + movb $1, %cs:prtchr_initialized +prtchr_ok: + lesw %cs:cursor_address, %di + movw $160, %bx + movb $0, %ah + cmpb $13, %al + je do_cr + cmpb $10, %al + je do_lf + + # normal (printable) character + stosw + movb $0xe1, %es:0x2000-2(%di) + jmp 1f + +do_cr: movw %di, %ax + divb %bl # %al = Y, %ah = X * 2 + mulb %bl + movw %ax, %dx + jmp 2f + +do_lf: addw %bx, %di +1: movw %cs:max_cursor_offset, %cx + cmpw %cx, %di + movw %di, %dx + jb 2f + # cursor reaches bottom of screen; scroll it + subw %bx, %dx + xorw %di, %di + movw %bx, %si + cld + subw %bx, %cx + shrw %cx + pushw %cx + rep; es; movsw + movb $32, %al # clear bottom line characters + movb $80, %cl + rep; stosw + movw $0x2000, %di + popw %cx + leaw (%bx,%di), %si + rep; es; movsw + movb $0xe1, %al # clear bottom line attributes + movb $80, %cl + rep; stosw +2: movw %dx, %cs:cursor_address + movb $0x13, %ah # move cursor to right position + int $0x18 + popw %es + popaw + ret + +cursor_address: + .word 0 + .word NORMAL_TEXT +max_cursor_offset: + .word 80 * 25 * 2 # for normal 80x25 mode + +# putstr may called without running through start_of_setup (via bootsect_panic) +# so we should initialize ourselves on demand. +prtchr_initialized: + .byte 0 + +# This routine queries GDC (graphic display controller) for current cursor +# position. Cursor position is returned in %ax (CPU offset address). +get_cursor_position: +1: inb $0x60, %al + outb %al, $0x5f # delay + outb %al, $0x5f # delay + testb $0x04, %al # Is FIFO empty? + jz 1b # no -> wait until empty + + movb $0xe0, %al # CSRR command + outb %al, $0x62 # command write + outb %al, $0x5f # delay + outb %al, $0x5f # delay + +2: inb $0x60, %al + outb %al, $0x5f # delay + outb %al, $0x5f # delay + testb $0x01, %al # Is DATA READY? + jz 2b # no -> wait until ready + + inb $0x62, %al # read xAD (L) + outb %al, $0x5f # delay + outb %al, $0x5f # delay + movb %al, %ah + inb $0x62, %al # read xAD (H) + outb %al, $0x5f # delay + outb %al, $0x5f # delay + xchgb %al, %ah # correct byte order + pushw %ax + inb $0x62, %al # read yAD (L) + outb %al, $0x5f # delay + outb %al, $0x5f # delay + inb $0x62, %al # read yAD (M) + outb %al, $0x5f # delay + outb %al, $0x5f # delay + inb $0x62, %al # read yAD (H) + # yAD is not our interest, + # so discard it. + popw %ax + addw %ax, %ax # convert to CPU address + ret + +# Descriptor tables +# +# NOTE: The intel manual says gdt should be sixteen bytes aligned for +# efficiency reasons. However, there are machines which are known not +# to boot with misaligned GDTs, so alter this at your peril! If you alter +# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two +# empty GDT entries (one for NULL and one reserved). +# +# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is +# true for the Voyager Quad CPU card which will not boot without +# This directive. 16 byte aligment is recommended by intel. +# + .align 16 +gdt: + .fill GDT_ENTRY_BOOT_CS,8,0 + + .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) + .word 0 # base address = 0 + .word 0x9A00 # code read/exec + .word 0x00CF # granularity = 4096, 386 + # (+5th nibble of limit) + + .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) + .word 0 # base address = 0 + .word 0x9200 # data read/write + .word 0x00CF # granularity = 4096, 386 + # (+5th nibble of limit) +gdt_end: + .align 4 + + .word 0 # alignment byte +idt_48: + .word 0 # idt limit = 0 + .word 0, 0 # idt base = 0L + + .word 0 # alignment byte +gdt_48: + .word gdt_end - gdt - 1 # gdt limit + .word 0, 0 # gdt base (filled in later) + +# Include video setup & detection code + +#include "video.S" + +# Setup signature -- must be last +setup_sig1: .word SIG1 +setup_sig2: .word SIG2 + +# After this point, there is some free space which is used by the video mode +# handling code to store the temporary mode table (not used by the kernel). + +modelist: + +.text +endtext: +.data +enddata: +.bss +endbss: diff -urN linux-2.5.65-bk2/arch/i386/boot98/tools/build.c linux-2.5.65-bk3/arch/i386/boot98/tools/build.c --- linux-2.5.65-bk2/arch/i386/boot98/tools/build.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/boot98/tools/build.c Mon Mar 31 12:41:39 2003 @@ -0,0 +1,188 @@ +/* + * $Id: build.c,v 1.5 1997/05/19 12:29:58 mj Exp $ + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1997 Martin Mares + */ + +/* + * This file builds a disk-image from three different files: + * + * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest + * - setup: 8086 machine code, sets up system parm + * - system: 80386 code for actual system + * + * It does some checking that all files are of the correct type, and + * just writes the result to stdout, removing headers and padding to + * the right amount. It also writes some system data to stderr. + */ + +/* + * Changes by tytso to allow root device specification + * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 + * Cross compiling fixes by Gertjan van Wingerde, July 1996 + * Rewritten by Martin Mares, April 1997 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned long u32; + +#define DEFAULT_MAJOR_ROOT 0 +#define DEFAULT_MINOR_ROOT 0 + +/* Minimal number of setup sectors (see also bootsect.S) */ +#define SETUP_SECTS 4 + +byte buf[1024]; +int fd; +int is_big_kernel; + +void die(const char * str, ...) +{ + va_list args; + va_start(args, str); + vfprintf(stderr, str, args); + fputc('\n', stderr); + exit(1); +} + +void file_open(const char *name) +{ + if ((fd = open(name, O_RDONLY, 0)) < 0) + die("Unable to open `%s': %m", name); +} + +void usage(void) +{ + die("Usage: build [-b] bootsect setup system [rootdev] [> image]"); +} + +int main(int argc, char ** argv) +{ + unsigned int i, c, sz, setup_sectors; + u32 sys_size; + byte major_root, minor_root; + struct stat sb; + + if (argc > 2 && !strcmp(argv[1], "-b")) + { + is_big_kernel = 1; + argc--, argv++; + } + if ((argc < 4) || (argc > 5)) + usage(); + if (argc > 4) { + if (!strcmp(argv[4], "CURRENT")) { + if (stat("/", &sb)) { + perror("/"); + die("Couldn't stat /"); + } + major_root = major(sb.st_dev); + minor_root = minor(sb.st_dev); + } else if (strcmp(argv[4], "FLOPPY")) { + if (stat(argv[4], &sb)) { + perror(argv[4]); + die("Couldn't stat root device."); + } + major_root = major(sb.st_rdev); + minor_root = minor(sb.st_rdev); + } else { + major_root = 0; + minor_root = 0; + } + } else { + major_root = DEFAULT_MAJOR_ROOT; + minor_root = DEFAULT_MINOR_ROOT; + } + fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); + + file_open(argv[1]); + i = read(fd, buf, sizeof(buf)); + fprintf(stderr,"Boot sector %d bytes.\n",i); + if (i != 512) + die("Boot block must be exactly 512 bytes"); + if (buf[510] != 0x55 || buf[511] != 0xaa) + die("Boot block hasn't got boot flag (0xAA55)"); + buf[508] = minor_root; + buf[509] = major_root; + if (write(1, buf, 512) != 512) + die("Write call failed"); + close (fd); + + file_open(argv[2]); /* Copy the setup code */ + for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c ) + if (write(1, buf, c) != c) + die("Write call failed"); + if (c != 0) + die("read-error on `setup'"); + close (fd); + + setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */ + if (!(setup_sectors & 1)) + setup_sectors++; /* setup_sectors must be odd on NEC PC-9800 */ + fprintf(stderr, "Setup is %d bytes.\n", i); + memset(buf, 0, sizeof(buf)); + while (i < setup_sectors * 512) { + c = setup_sectors * 512 - i; + if (c > sizeof(buf)) + c = sizeof(buf); + if (write(1, buf, c) != c) + die("Write call failed"); + i += c; + } + + file_open(argv[3]); + if (fstat (fd, &sb)) + die("Unable to stat `%s': %m", argv[3]); + sz = sb.st_size; + fprintf (stderr, "System is %d kB\n", sz/1024); + sys_size = (sz + 15) / 16; + /* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */ + if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE)) + die("System is too big. Try using %smodules.", + is_big_kernel ? "" : "bzImage or "); + if (sys_size > 0xefff) + fprintf(stderr,"warning: kernel is too big for standalone boot " + "from floppy\n"); + while (sz > 0) { + int l, n; + + l = (sz > sizeof(buf)) ? sizeof(buf) : sz; + if ((n=read(fd, buf, l)) != l) { + if (n < 0) + die("Error reading %s: %m", argv[3]); + else + die("%s: Unexpected EOF", argv[3]); + } + if (write(1, buf, l) != l) + die("Write failed"); + sz -= l; + } + close(fd); + + if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */ + die("Output: seek failed"); + buf[0] = setup_sectors; + if (write(1, buf, 1) != 1) + die("Write of setup sector count failed"); + if (lseek(1, 500, SEEK_SET) != 500) + die("Output: seek failed"); + buf[0] = (sys_size & 0xff); + buf[1] = ((sys_size >> 8) & 0xff); + if (write(1, buf, 2) != 2) + die("Write of image length failed"); + + return 0; /* Everything is OK */ +} diff -urN linux-2.5.65-bk2/arch/i386/boot98/video.S linux-2.5.65-bk3/arch/i386/boot98/video.S --- linux-2.5.65-bk2/arch/i386/boot98/video.S Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/boot98/video.S Mon Mar 31 12:41:39 2003 @@ -0,0 +1,262 @@ +/* video.S + * + * Video mode setup, etc. for NEC PC-9800 series. + * + * Copyright (C) 1997,98,99 Linux/98 project + * + * Based on the video.S for IBM PC: + * copyright (C) Martin Mares + */ + +/* Positions of various video parameters passed to the kernel */ +/* (see also include/linux/tty.h) */ +#define PARAM_CURSOR_POS 0x00 +#define PARAM_VIDEO_PAGE 0x04 +#define PARAM_VIDEO_MODE 0x06 +#define PARAM_VIDEO_COLS 0x07 +#define PARAM_VIDEO_EGA_BX 0x0a +#define PARAM_VIDEO_LINES 0x0e +#define PARAM_HAVE_VGA 0x0f +#define PARAM_FONT_POINTS 0x10 + +#define PARAM_VIDEO98_COMPAT 0x0a +#define PARAM_VIDEO98_HIRESO 0x0b +#define PARAM_VIDEO98_MACHTYPE 0x0c +#define PARAM_VIDEO98_LINES 0x0e +#define PARAM_VIDEO98_COLS 0x0f + +# PARAM_LFB_* and PARAM_VESAPM_* are unused on PC-9800. + +# This is the main entry point called by setup.S +# %ds *must* be pointing to the bootsector +video: xorw %ax, %ax + movw %ax, %es # %es = 0 + + movb %es:BIOS_FLAG, %al + movb %al, PARAM_VIDEO_MODE + + movb $0, PARAM_VIDEO98_HIRESO # 0 = normal + movw $NORMAL_TEXT, PARAM_VIDEO_PAGE + testb $0x8, %al + movw $(80 * 256 + 25), %ax + jz 1f + # hireso machine. + movb $1, PARAM_VIDEO98_HIRESO # !0 = hi-reso + movb $(HIRESO_TEXT >> 8), PARAM_VIDEO_PAGE + 1 + movw $(80 * 256 + 31), %ax +1: movw %ax, PARAM_VIDEO98_LINES # also sets VIDEO98_COLS + + movb $0xc0, %ch # 400-line graphic mode + movb $0x42, %ah + int $0x18 + + movw $80, PARAM_VIDEO_COLS + + movw $msg_probing, %si + call prtstr_cs + +# Check vendor from font pattern of `A'... + +1: inb $0x60, %al # wait V-sync + testb $0x20, %al + jnz 1b +2: inb $0x60, %al + testb $0x20, %al + jz 2b + + movb $0x00, %al # select font of `A' + outb %al, $0xa1 + movb $0x41, %al + outb %al, $0xa3 + + movw $8, %cx + movw PARAM_VIDEO_PAGE, %ax + cmpw $NORMAL_TEXT, %ax + je 3f + movb $24, %cl # for hi-reso machine +3: addw $0x400, %ax # %ax = CG window segment + pushw %ds + movw %ax, %ds + xorw %dx, %dx # get sum of `A' pattern... + xorw %si, %si +4: lodsw + addw %ax, %dx + loop 4b + popw %ds + + movw %dx, %ax + movw $msg_nec, %si + xorw %bx, %bx # vendor info will go into %bx + testb $8, %es:BIOS_FLAG + jnz check_hireso_vendor + cmpw $0xc7f8, %ax + je 5f + jmp 6f +check_hireso_vendor: + cmpw $0x9639, %ax # XXX: NOT VERIFIED!!! + je 5f +6: incw %bx # compatible machine + movw $msg_compat, %si +5: movb %bl, PARAM_VIDEO98_COMPAT + call prtstr_cs + + movw $msg_fontdata, %si + call prtstr_cs # " (CG sum of A = 0x" + movw %dx, %ax + call prthex + call prtstr_cs # ") PC-98" + + movb $'0', %al + pushw %ds + pushw $0xf8e8 + popw %ds + cmpw $0x2198, (0) + popw %ds + jne 7f + movb $'2', %al +7: call prtchr + call prtstr_cs # "1 " + + movb $0, PARAM_VIDEO98_MACHTYPE +#if 0 /* XXX - This check is bogus? [0000:BIOS_FLAG2]-bit7 does NOT + indicate whether it is a note machine, but merely indicates + whether it has ``RAM drive''. */ +# check note machine + testb $0x80, %es:BIOS_FLAG2 + jnz is_note + pushw %ds + pushw $0xfd80 + popw %ds + movb (4), %al + popw %ds + cmpb $0x20, %al # EPSON note A + je epson_note + cmpb $0x22, %al # EPSON note W + je epson_note + cmpb $0x27, %al # EPSON note AE + je epson_note + cmpb $0x2a, %al # EPSON note WR + jne note_done +epson_note: + movb $1, PARAM_VIDEO98_MACHTYPE + movw $msg_note, %si + call prtstr_cs +note_done: +#endif + +# print h98 ? (only NEC) + cmpb $0, PARAM_VIDEO98_COMPAT + jnz 8f # not NEC -> not H98 + + testb $0x80, %es:BIOS_FLAG5 + jz 8f # have NESA bus -> H98 + movw $msg_h98, %si + call prtstr_cs + orb $2, PARAM_VIDEO98_MACHTYPE +8: testb $0x40, %es:BIOS_FLAG5 + jz 9f + movw $msg_gs, %si + call prtstr_cs # only prints it :-) +9: + movw $msg_normal, %si # "normal" + testb $0x8, %es:BIOS_FLAG + jz 1f + movw $msg_hireso, %si +1: call prtstr_cs + + movw $msg_sysclk, %si + call prtstr_cs + movb $'5', %al + testb $0x80, %es:BIOS_FLAG + jz 2f + movb $'8', %al +2: call prtchr + call prtstr_cs + +#if 0 + testb $0x40, %es:(0x45c) + jz no_30line # no 30-line support + + movb %es:KB_SHFT_STS, %al + testb $0x01, %al # is SHIFT key pressed? + jz no_30line + + testb $0x10, %al # is CTRL key pressed? + jnz line40 + + # switch to 30-line mode + movb $30, PARAM_VIDEO98_LINES + movw $msg_30line, %si + jmp 3f + +line40: + movb $37, PARAM_VIDEO98_LINES + movw $40, PARAM_VIDEO_LINES + movw $msg_40line, %si +3: call prtstr_cs + + movb $0x32, %bh + movw $0x300c, %ax + int $0x18 # switch video mode + movb $0x0c, %ah + int $0x18 # turn on text plane + movw %cs:cursor_address, %dx + movb $0x13, %ah + int $0x18 # move cursor to correct place + mov $0x11, %ah + int $0x18 # turn on text plane + + call prtstr_cs # "Ok.\r\n" +no_30line: +#endif + ret + +prtstr_cs: + pushw %ds + pushw %cs + popw %ds + call prtstr + popw %ds + ret + +# prthex is for debugging purposes, and prints %ax in hexadecimal. +prthex: pushw %cx + movw $4, %cx +1: rolw $4, %ax + pushw %ax + andb $0xf, %al + cmpb $10, %al + sbbb $0x69, %al + das + call prtchr + popw %ax + loop 1b + popw %cx + ret + +msg_probing: .string "Probing machine: " + +msg_nec: .string "NEC" +msg_compat: .string "compatible" + +msg_fontdata: .string " (CG sum of A = 0x" + .string ") PC-98" + .string "1 " + +msg_gs: .string "(GS) " +msg_h98: .string "(H98) " + +msg_normal: .string "normal" +msg_hireso: .string "Hi-reso" + +msg_sysclk: .string " mode, system clock " + .string "MHz\r\n" + +#if 0 +msg_40line: # cpp will concat following lines, so the assembler can deal. + .ascii "\ +Video mode will be adjusted to 37-line (so-called ``40-line'') mode later.\r\n\ +THIS MODE MAY DAMAGE YOUR MONITOR PHYSICALLY. USE AT YOUR OWN RISK.\r\n" +msg_30line: .string "Switching video mode to 30-line (640x480) mode... " + .string "Ok.\r\n" +#endif diff -urN linux-2.5.65-bk2/arch/i386/kernel/dmi_scan.c linux-2.5.65-bk3/arch/i386/kernel/dmi_scan.c --- linux-2.5.65-bk2/arch/i386/kernel/dmi_scan.c Mon Mar 17 13:44:03 2003 +++ linux-2.5.65-bk3/arch/i386/kernel/dmi_scan.c Mon Mar 31 12:41:39 2003 @@ -499,6 +499,19 @@ return 0; } +/* + * Exploding PnPBIOS. Don't yet know if its the BIOS or us for + * some entries + */ + +static __init int exploding_pnp_bios(struct dmi_blacklist *d) +{ + printk(KERN_WARNING "%s detected. Disabling PnPBIOS\n", d->ident); + dmi_broken |= BROKEN_PNP_BIOS; + return 0; +} + + /* * Simple "print if true" callback @@ -687,6 +700,13 @@ MATCH(DMI_BIOS_VERSION, "WXPO1Z3"), MATCH(DMI_BIOS_DATE, "10/26/01"), NO_MATCH } }, + + { exploding_pnp_bios, "Higraded P14H", { /* BIOSPnP problem */ + MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), + MATCH(DMI_BIOS_VERSION, "07.00T"), + MATCH(DMI_SYS_VENDOR, "Higraded"), + MATCH(DMI_PRODUCT_NAME, "P14H") + } }, /* Machines which have problems handling enabled local APICs */ diff -urN linux-2.5.65-bk2/arch/i386/mach-pc9800/Makefile linux-2.5.65-bk3/arch/i386/mach-pc9800/Makefile --- linux-2.5.65-bk2/arch/i386/mach-pc9800/Makefile Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/mach-pc9800/Makefile Mon Mar 31 12:41:39 2003 @@ -0,0 +1,7 @@ +# +# Makefile for the linux kernel. +# + +EXTRA_CFLAGS += -I../kernel + +obj-y := setup.o topology.o diff -urN linux-2.5.65-bk2/arch/i386/mach-pc9800/setup.c linux-2.5.65-bk3/arch/i386/mach-pc9800/setup.c --- linux-2.5.65-bk2/arch/i386/mach-pc9800/setup.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/mach-pc9800/setup.c Mon Mar 31 12:41:39 2003 @@ -0,0 +1,117 @@ +/* + * Machine specific setup for pc9800 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct sys_desc_table_struct { + unsigned short length; + unsigned char table[0]; +}; + +/** + * pre_intr_init_hook - initialisation prior to setting up interrupt vectors + * + * Description: + * Perform any necessary interrupt initialisation prior to setting up + * the "ordinary" interrupt call gates. For legacy reasons, the ISA + * interrupts should be initialised here if the machine emulates a PC + * in any way. + **/ +void __init pre_intr_init_hook(void) +{ + init_ISA_irqs(); +} + +/* + * IRQ7 is cascade interrupt to second interrupt controller + */ +static struct irqaction irq7 = { no_action, 0, 0, "cascade", NULL, NULL}; + +/** + * intr_init_hook - post gate setup interrupt initialisation + * + * Description: + * Fill in any interrupts that may have been left out by the general + * init_IRQ() routine. interrupts having to do with the machine rather + * than the devices on the I/O bus (like APIC interrupts in intel MP + * systems) are started here. + **/ +void __init intr_init_hook(void) +{ +#ifdef CONFIG_X86_LOCAL_APIC + apic_intr_init(); +#endif + + setup_irq(7, &irq7); +} + +/** + * pre_setup_arch_hook - hook called prior to any setup_arch() execution + * + * Description: + * generally used to activate any machine specific identification + * routines that may be needed before setup_arch() runs. On VISWS + * this is used to get the board revision and type. + **/ +void __init pre_setup_arch_hook(void) +{ + SYS_DESC_TABLE.length = 0; + MCA_bus = 0; + /* In PC-9800, APM BIOS version is written in BCD...?? */ + APM_BIOS_INFO.version = (APM_BIOS_INFO.version & 0xff00) + | ((APM_BIOS_INFO.version & 0x00f0) >> 4); +} + +/** + * trap_init_hook - initialise system specific traps + * + * Description: + * Called as the final act of trap_init(). Used in VISWS to initialise + * the various board specific APIC traps. + **/ +void __init trap_init_hook(void) +{ +} + +static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL}; + +/** + * time_init_hook - do any specific initialisations for the system timer. + * + * Description: + * Must plug the system timer interrupt source at HZ into the IRQ listed + * in irq_vectors.h:TIMER_IRQ + **/ +void __init time_init_hook(void) +{ + setup_irq(0, &irq0); +} + +#ifdef CONFIG_MCA +/** + * mca_nmi_hook - hook into MCA specific NMI chain + * + * Description: + * The MCA (Microchannel Architecture) has an NMI chain for NMI sources + * along the MCA bus. Use this to hook into that chain if you will need + * it. + **/ +void __init mca_nmi_hook(void) +{ + /* If I recall correctly, there's a whole bunch of other things that + * we can do to check for NMI problems, but that's all I know about + * at the moment. + */ + + printk("NMI generated from unknown source!\n"); +} +#endif diff -urN linux-2.5.65-bk2/arch/i386/mach-pc9800/topology.c linux-2.5.65-bk3/arch/i386/mach-pc9800/topology.c --- linux-2.5.65-bk2/arch/i386/mach-pc9800/topology.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/arch/i386/mach-pc9800/topology.c Mon Mar 31 12:41:39 2003 @@ -0,0 +1,44 @@ +/* + * arch/i386/mach-pc9800/topology.c - Populate driverfs with topology information + * + * Written by: Matthew Dobson, IBM Corporation + * Original Code: Paul Dorwin, IBM Corporation, Patrick Mochel, OSDL + * + * Copyright (C) 2002, IBM Corp. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Modify for PC-9800 by Osamu Tomita + * + */ +#include +#include +#include + +struct i386_cpu cpu_devices[NR_CPUS]; + +static int __init topology_init(void) +{ + int i; + + for (i = 0; i < NR_CPUS; i++) + if (cpu_possible(i)) arch_register_cpu(i); + return 0; +} + +subsys_initcall(topology_init); diff -urN linux-2.5.65-bk2/arch/i386/pci/pcbios.c linux-2.5.65-bk3/arch/i386/pci/pcbios.c --- linux-2.5.65-bk2/arch/i386/pci/pcbios.c Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/arch/i386/pci/pcbios.c Mon Mar 31 12:41:39 2003 @@ -5,22 +5,9 @@ #include #include #include "pci.h" +#include "pci-functions.h" -#define PCIBIOS_PCI_FUNCTION_ID 0xb1XX -#define PCIBIOS_PCI_BIOS_PRESENT 0xb101 -#define PCIBIOS_FIND_PCI_DEVICE 0xb102 -#define PCIBIOS_FIND_PCI_CLASS_CODE 0xb103 -#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106 -#define PCIBIOS_READ_CONFIG_BYTE 0xb108 -#define PCIBIOS_READ_CONFIG_WORD 0xb109 -#define PCIBIOS_READ_CONFIG_DWORD 0xb10a -#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b -#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c -#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d -#define PCIBIOS_GET_ROUTING_OPTIONS 0xb10e -#define PCIBIOS_SET_PCI_HW_INT 0xb10f - /* BIOS32 signature: "_32_" */ #define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) diff -urN linux-2.5.65-bk2/arch/s390x/kernel/exec32.c linux-2.5.65-bk3/arch/s390x/kernel/exec32.c --- linux-2.5.65-bk2/arch/s390x/kernel/exec32.c Mon Mar 17 13:43:37 2003 +++ linux-2.5.65-bk3/arch/s390x/kernel/exec32.c Mon Mar 31 12:41:39 2003 @@ -21,7 +21,6 @@ #include #include #include -#define __NO_VERSION__ #include #include diff -urN linux-2.5.65-bk2/arch/um/drivers/ubd_kern.c linux-2.5.65-bk3/arch/um/drivers/ubd_kern.c --- linux-2.5.65-bk2/arch/um/drivers/ubd_kern.c Mon Mar 17 13:44:05 2003 +++ linux-2.5.65-bk3/arch/um/drivers/ubd_kern.c Mon Mar 31 12:41:39 2003 @@ -507,7 +507,7 @@ /* /dev/ubd/N style names */ sprintf(devfs_name, "%d", unit); *handle_out = devfs_register(dir_handle, devfs_name, - DEVFS_FL_REMOVABLE, major, minor, + 0, major, minor, S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, &ubd_blops, NULL); disk->private_data = &ubd_dev[unit]; diff -urN linux-2.5.65-bk2/drivers/char/Makefile linux-2.5.65-bk3/drivers/char/Makefile --- linux-2.5.65-bk2/drivers/char/Makefile Mon Mar 17 13:44:45 2003 +++ linux-2.5.65-bk3/drivers/char/Makefile Mon Mar 31 12:41:40 2003 @@ -44,6 +44,7 @@ obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_TIPAR) += tipar.o +obj-$(CONFIG_PC9800_OLDLP) += lp_old98.o obj-$(CONFIG_BUSMOUSE) += busmouse.o obj-$(CONFIG_DTLK) += dtlk.o diff -urN linux-2.5.65-bk2/drivers/char/drm/ati_pcigart.h linux-2.5.65-bk3/drivers/char/drm/ati_pcigart.h --- linux-2.5.65-bk2/drivers/char/drm/ati_pcigart.h Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/drivers/char/drm/ati_pcigart.h Mon Mar 31 12:41:40 2003 @@ -27,7 +27,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include "drmP.h" #if PAGE_SIZE == 65536 diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_agpsupport.h linux-2.5.65-bk3/drivers/char/drm/drm_agpsupport.h --- linux-2.5.65-bk2/drivers/char/drm/drm_agpsupport.h Mon Mar 17 13:43:37 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_agpsupport.h Mon Mar 31 12:41:40 2003 @@ -29,7 +29,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include "drmP.h" #include diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_auth.h linux-2.5.65-bk3/drivers/char/drm/drm_auth.h --- linux-2.5.65-bk2/drivers/char/drm/drm_auth.h Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_auth.h Mon Mar 31 12:41:40 2003 @@ -29,7 +29,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include "drmP.h" static int DRM(hash_magic)(drm_magic_t magic) diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_bufs.h linux-2.5.65-bk3/drivers/char/drm/drm_bufs.h --- linux-2.5.65-bk2/drivers/char/drm/drm_bufs.h Mon Mar 17 13:43:47 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_bufs.h Mon Mar 31 12:41:40 2003 @@ -29,7 +29,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include #include "drmP.h" diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_context.h linux-2.5.65-bk3/drivers/char/drm/drm_context.h --- linux-2.5.65-bk2/drivers/char/drm/drm_context.h Mon Mar 17 13:43:37 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_context.h Mon Mar 31 12:41:40 2003 @@ -33,7 +33,6 @@ * needed by SiS driver's memory management. */ -#define __NO_VERSION__ #include "drmP.h" #if __HAVE_CTX_BITMAP diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_dma.h linux-2.5.65-bk3/drivers/char/drm/drm_dma.h --- linux-2.5.65-bk2/drivers/char/drm/drm_dma.h Mon Mar 17 13:44:15 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_dma.h Mon Mar 31 12:41:40 2003 @@ -29,7 +29,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include "drmP.h" #include /* For task queue support */ diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_drawable.h linux-2.5.65-bk3/drivers/char/drm/drm_drawable.h --- linux-2.5.65-bk2/drivers/char/drm/drm_drawable.h Mon Mar 17 13:44:39 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_drawable.h Mon Mar 31 12:41:40 2003 @@ -29,7 +29,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include "drmP.h" int DRM(adddraw)(struct inode *inode, struct file *filp, diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_fops.h linux-2.5.65-bk3/drivers/char/drm/drm_fops.h --- linux-2.5.65-bk2/drivers/char/drm/drm_fops.h Mon Mar 17 13:44:07 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_fops.h Mon Mar 31 12:41:40 2003 @@ -30,7 +30,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include "drmP.h" #include diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_init.h linux-2.5.65-bk3/drivers/char/drm/drm_init.h --- linux-2.5.65-bk2/drivers/char/drm/drm_init.h Mon Mar 17 13:44:42 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_init.h Mon Mar 31 12:41:40 2003 @@ -29,7 +29,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include "drmP.h" #if 0 diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_ioctl.h linux-2.5.65-bk3/drivers/char/drm/drm_ioctl.h --- linux-2.5.65-bk2/drivers/char/drm/drm_ioctl.h Mon Mar 17 13:43:48 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_ioctl.h Mon Mar 31 12:41:40 2003 @@ -29,7 +29,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include "drmP.h" diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_lists.h linux-2.5.65-bk3/drivers/char/drm/drm_lists.h --- linux-2.5.65-bk2/drivers/char/drm/drm_lists.h Mon Mar 17 13:44:41 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_lists.h Mon Mar 31 12:41:40 2003 @@ -29,7 +29,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include "drmP.h" #if __HAVE_DMA_WAITLIST diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_lock.h linux-2.5.65-bk3/drivers/char/drm/drm_lock.h --- linux-2.5.65-bk2/drivers/char/drm/drm_lock.h Mon Mar 17 13:44:18 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_lock.h Mon Mar 31 12:41:40 2003 @@ -29,7 +29,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include "drmP.h" int DRM(block)(struct inode *inode, struct file *filp, unsigned int cmd, diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_memory.h linux-2.5.65-bk3/drivers/char/drm/drm_memory.h --- linux-2.5.65-bk2/drivers/char/drm/drm_memory.h Mon Mar 17 13:43:44 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_memory.h Mon Mar 31 12:41:40 2003 @@ -29,7 +29,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include #include "drmP.h" #include diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_os_linux.h linux-2.5.65-bk3/drivers/char/drm/drm_os_linux.h --- linux-2.5.65-bk2/drivers/char/drm/drm_os_linux.h Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_os_linux.h Mon Mar 31 12:41:40 2003 @@ -1,4 +1,3 @@ -#define __NO_VERSION__ #include /* For task queue support */ #include diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_proc.h linux-2.5.65-bk3/drivers/char/drm/drm_proc.h --- linux-2.5.65-bk2/drivers/char/drm/drm_proc.h Mon Mar 17 13:43:40 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_proc.h Mon Mar 31 12:41:40 2003 @@ -33,7 +33,6 @@ * the problem with the proc files not outputting all their information. */ -#define __NO_VERSION__ #include "drmP.h" static int DRM(name_info)(char *buf, char **start, off_t offset, diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_scatter.h linux-2.5.65-bk3/drivers/char/drm/drm_scatter.h --- linux-2.5.65-bk2/drivers/char/drm/drm_scatter.h Mon Mar 17 13:44:11 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_scatter.h Mon Mar 31 12:41:40 2003 @@ -27,7 +27,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include #include #include "drmP.h" diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_stub.h linux-2.5.65-bk3/drivers/char/drm/drm_stub.h --- linux-2.5.65-bk2/drivers/char/drm/drm_stub.h Mon Mar 17 13:44:41 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_stub.h Mon Mar 31 12:41:40 2003 @@ -28,7 +28,6 @@ * */ -#define __NO_VERSION__ #include "drmP.h" #define DRM_STUB_MAXCARDS 16 /* Enough for one machine */ diff -urN linux-2.5.65-bk2/drivers/char/drm/drm_vm.h linux-2.5.65-bk3/drivers/char/drm/drm_vm.h --- linux-2.5.65-bk2/drivers/char/drm/drm_vm.h Mon Mar 17 13:44:51 2003 +++ linux-2.5.65-bk3/drivers/char/drm/drm_vm.h Mon Mar 31 12:41:40 2003 @@ -29,7 +29,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include "drmP.h" struct vm_operations_struct DRM(vm_ops) = { diff -urN linux-2.5.65-bk2/drivers/char/drm/gamma_dma.c linux-2.5.65-bk3/drivers/char/drm/gamma_dma.c --- linux-2.5.65-bk2/drivers/char/drm/gamma_dma.c Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/drivers/char/drm/gamma_dma.c Mon Mar 31 12:41:40 2003 @@ -29,7 +29,6 @@ * */ -#define __NO_VERSION__ #include "gamma.h" #include "drmP.h" #include "drm.h" diff -urN linux-2.5.65-bk2/drivers/char/drm/i810_dma.c linux-2.5.65-bk3/drivers/char/drm/i810_dma.c --- linux-2.5.65-bk2/drivers/char/drm/i810_dma.c Mon Mar 17 13:44:02 2003 +++ linux-2.5.65-bk3/drivers/char/drm/i810_dma.c Mon Mar 31 12:41:40 2003 @@ -30,7 +30,6 @@ * */ -#define __NO_VERSION__ #include "i810.h" #include "drmP.h" #include "drm.h" diff -urN linux-2.5.65-bk2/drivers/char/drm/i830_dma.c linux-2.5.65-bk3/drivers/char/drm/i830_dma.c --- linux-2.5.65-bk2/drivers/char/drm/i830_dma.c Mon Mar 31 12:41:36 2003 +++ linux-2.5.65-bk3/drivers/char/drm/i830_dma.c Mon Mar 31 12:41:40 2003 @@ -31,7 +31,6 @@ * */ -#define __NO_VERSION__ #include "i830.h" #include "drmP.h" #include "drm.h" diff -urN linux-2.5.65-bk2/drivers/char/drm/mga_warp.c linux-2.5.65-bk3/drivers/char/drm/mga_warp.c --- linux-2.5.65-bk2/drivers/char/drm/mga_warp.c Mon Mar 17 13:44:04 2003 +++ linux-2.5.65-bk3/drivers/char/drm/mga_warp.c Mon Mar 31 12:41:40 2003 @@ -27,7 +27,6 @@ * Gareth Hughes */ -#define __NO_VERSION__ #include "mga.h" #include "drmP.h" #include "drm.h" diff -urN linux-2.5.65-bk2/drivers/char/drm/sis_ds.c linux-2.5.65-bk3/drivers/char/drm/sis_ds.c --- linux-2.5.65-bk2/drivers/char/drm/sis_ds.c Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/drivers/char/drm/sis_ds.c Mon Mar 31 12:41:40 2003 @@ -28,7 +28,6 @@ * */ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/drivers/char/drm/sis_mm.c linux-2.5.65-bk3/drivers/char/drm/sis_mm.c --- linux-2.5.65-bk2/drivers/char/drm/sis_mm.c Mon Mar 17 13:44:19 2003 +++ linux-2.5.65-bk3/drivers/char/drm/sis_mm.c Mon Mar 31 12:41:40 2003 @@ -28,7 +28,6 @@ * */ -#define __NO_VERSION__ #include "sis.h" #include #include "drmP.h" diff -urN linux-2.5.65-bk2/drivers/char/ftape/lowlevel/ftape_syms.c linux-2.5.65-bk3/drivers/char/ftape/lowlevel/ftape_syms.c --- linux-2.5.65-bk2/drivers/char/ftape/lowlevel/ftape_syms.c Mon Mar 17 13:44:02 2003 +++ linux-2.5.65-bk3/drivers/char/ftape/lowlevel/ftape_syms.c Mon Mar 31 12:41:40 2003 @@ -26,7 +26,6 @@ */ #include -#define __NO_VERSION__ #include #include diff -urN linux-2.5.65-bk2/drivers/char/ftape/zftape/zftape-ctl.c linux-2.5.65-bk3/drivers/char/ftape/zftape/zftape-ctl.c --- linux-2.5.65-bk2/drivers/char/ftape/zftape/zftape-ctl.c Mon Mar 17 13:44:03 2003 +++ linux-2.5.65-bk3/drivers/char/ftape/zftape/zftape-ctl.c Mon Mar 31 12:41:40 2003 @@ -27,7 +27,6 @@ #include #include #include -#define __NO_VERSION__ #include #include diff -urN linux-2.5.65-bk2/drivers/char/ftape/zftape/zftape_syms.c linux-2.5.65-bk3/drivers/char/ftape/zftape/zftape_syms.c --- linux-2.5.65-bk2/drivers/char/ftape/zftape/zftape_syms.c Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/drivers/char/ftape/zftape/zftape_syms.c Mon Mar 31 12:41:40 2003 @@ -24,7 +24,6 @@ * the ftape floppy tape driver exports */ -#define __NO_VERSION__ #include #include diff -urN linux-2.5.65-bk2/drivers/char/ipmi/ipmi_devintf.c linux-2.5.65-bk3/drivers/char/ipmi/ipmi_devintf.c --- linux-2.5.65-bk2/drivers/char/ipmi/ipmi_devintf.c Mon Mar 17 13:44:42 2003 +++ linux-2.5.65-bk3/drivers/char/ipmi/ipmi_devintf.c Mon Mar 31 12:41:40 2003 @@ -105,7 +105,7 @@ static struct ipmi_user_hndl ipmi_hndlrs = { - ipmi_recv_hndl : file_receive_handler + .ipmi_recv_hndl = file_receive_handler, }; static int ipmi_open(struct inode *inode, struct file *file) @@ -424,12 +424,12 @@ static struct file_operations ipmi_fops = { - owner: THIS_MODULE, - ioctl: ipmi_ioctl, - open: ipmi_open, - release: ipmi_release, - fasync: ipmi_fasync, - poll: ipmi_poll + .owner = THIS_MODULE, + .ioctl = ipmi_ioctl, + .open = ipmi_open, + .release = ipmi_release, + .fasync = ipmi_fasync, + .poll = ipmi_poll, }; #define DEVICE_NAME "ipmidev" @@ -468,8 +468,8 @@ static struct ipmi_smi_watcher smi_watcher = { - new_smi : ipmi_new_smi, - smi_gone : ipmi_smi_gone + .new_smi = ipmi_new_smi, + .smi_gone = ipmi_smi_gone, }; static __init int init_ipmi_devintf(void) diff -urN linux-2.5.65-bk2/drivers/char/ite_gpio.c linux-2.5.65-bk3/drivers/char/ite_gpio.c --- linux-2.5.65-bk2/drivers/char/ite_gpio.c Mon Mar 17 13:44:20 2003 +++ linux-2.5.65-bk3/drivers/char/ite_gpio.c Mon Mar 31 12:41:40 2003 @@ -140,7 +140,7 @@ { int ret=-1; - if (MAX_GPIO_LINE > *data >= 0) + if ((MAX_GPIO_LINE > *data) && (*data >= 0)) ret=ite_gpio_irq_pending[*data]; DEB(printk("ite_gpio_in_status %d ret=%d\n",*data, ret)); diff -urN linux-2.5.65-bk2/drivers/char/lp_old98.c linux-2.5.65-bk3/drivers/char/lp_old98.c --- linux-2.5.65-bk2/drivers/char/lp_old98.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/drivers/char/lp_old98.c Mon Mar 31 12:41:40 2003 @@ -0,0 +1,544 @@ +/* + * linux/drivers/char/lp_old98.c + * + * printer port driver for ancient PC-9800s with no bidirectional port support + * + * Copyright (C) 1998,99 Kousuke Takai , + * Kyoto University Microcomputer Club + * + * This driver is based on and has compatibility with `lp.c', + * generic PC printer port driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/* + * I/O port numbers + */ +#define LP_PORT_DATA 0x40 +#define LP_PORT_STATUS (LP_PORT_DATA + 2) +#define LP_PORT_STROBE (LP_PORT_DATA + 4) +#define LP_PORT_CONTROL (LP_PORT_DATA + 6) + +#define LP_PORT_H98MODE 0x0448 +#define LP_PORT_EXTMODE 0x0149 + +/* + * bit mask for I/O + */ +#define LP_MASK_nBUSY (1 << 2) +#define LP_MASK_nSTROBE (1 << 7) + +#define LP_CONTROL_ASSERT_STROBE (0x0e) +#define LP_CONTROL_NEGATE_STROBE (0x0f) + +/* + * Acceptable maximum value for non-privileged user for LPCHARS ioctl. + */ +#define LP_CHARS_NOPRIV_MAX 65535 + +#define DC1 '\x11' +#define DC3 '\x13' + +/* PC-9800s have at least and at most one old-style printer port. */ +static struct lp_struct lp = { + .flags = LP_EXIST | LP_ABORTOPEN, + .chars = LP_INIT_CHAR, + .time = LP_INIT_TIME, + .wait = LP_INIT_WAIT, +}; + +static int dc1_check; +static spinlock_t lp_old98_lock = SPIN_LOCK_UNLOCKED; + + +#undef LP_OLD98_DEBUG + +#ifdef CONFIG_PC9800_OLDLP_CONSOLE +static struct console lp_old98_console; /* defined later */ +static short saved_console_flags; +#endif + +static DECLARE_WAIT_QUEUE_HEAD (lp_old98_waitq); + +static void lp_old98_timer_function(unsigned long data) +{ + if (inb(LP_PORT_STATUS) & LP_MASK_nBUSY) + wake_up_interruptible(&lp_old98_waitq); + else { + struct timer_list *t = (struct timer_list *) data; + + t->expires = jiffies + 1; + add_timer(t); + } +} + +static inline int lp_old98_wait_ready(void) +{ + struct timer_list timer; + + init_timer(&timer); + timer.function = lp_old98_timer_function; + timer.expires = jiffies + 1; + timer.data = (unsigned long)&timer; + add_timer(&timer); + interruptible_sleep_on(&lp_old98_waitq); + del_timer(&timer); + return signal_pending(current); +} + +static inline int lp_old98_char(char lpchar) +{ + unsigned long count = 0; +#ifdef LP_STATS + int tmp; +#endif + + while (!(inb(LP_PORT_STATUS) & LP_MASK_nBUSY)) { + count++; + if (count >= lp.chars) + return 0; + } + + outb(lpchar, LP_PORT_DATA); + +#ifdef LP_STATS + /* + * Update lp statsistics here (and between next two outb()'s). + * Time to compute it is part of storobe delay. + */ + if (count > lp.stats.maxwait) { +#ifdef LP_OLD98_DEBUG + printk(KERN_DEBUG "lp_old98: success after %d counts.\n", + count); +#endif + lp.stats.maxwait = count; + } + count *= 256; + tmp = count - lp.stats.meanwait; + if (tmp < 0) + tmp = -tmp; +#endif + ndelay(lp.wait); + + /* negate PSTB# (activate strobe) */ + outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL); + +#ifdef LP_STATS + lp.stats.meanwait = (255 * lp.stats.meanwait + count + 128) / 256; + lp.stats.mdev = (127 * lp.stats.mdev + tmp + 64) / 128; + lp.stats.chars ++; +#endif + + ndelay(lp.wait); + + /* assert PSTB# (deactivate strobe) */ + outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL); + + return 1; +} + +static ssize_t lp_old98_write(struct file * file, + const char * buf, size_t count, + loff_t *dummy) +{ + unsigned long total_bytes_written = 0; + + if (!access_ok(VERIFY_READ, buf, count)) + return -EFAULT; + +#ifdef LP_STATS + if (jiffies - lp.lastcall > lp.time) + lp.runchars = 0; + lp.lastcall = jiffies; +#endif + + do { + unsigned long bytes_written = 0; + unsigned long copy_size + = (count < LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE); + + if (__copy_from_user(lp.lp_buffer, buf, copy_size)) + return -EFAULT; + + while (bytes_written < copy_size) { + if (lp_old98_char(lp.lp_buffer[bytes_written])) + bytes_written ++; + else { +#ifdef LP_STATS + int rc = lp.runchars + bytes_written; + + if (rc > lp.stats.maxrun) + lp.stats.maxrun = rc; + + lp.stats.sleeps ++; +#endif +#ifdef LP_OLD98_DEBUG + printk(KERN_DEBUG + "lp_old98: sleeping at %d characters" + " for %d jiffies\n", + lp.runchars, lp.time); + lp.runchars = 0; +#endif + if (lp_old98_wait_ready()) + return ((total_bytes_written + + bytes_written) + ? : -EINTR); + } + } + total_bytes_written += bytes_written; + buf += bytes_written; +#ifdef LP_STATS + lp.runchars += bytes_written; +#endif + count -= bytes_written; + } while (count > 0); + + return total_bytes_written; +} + +static int lp_old98_open(struct inode * inode, struct file * file) +{ + if (minor(inode->i_rdev) != 0) + return -ENXIO; + + if (lp.flags & LP_BUSY) + return -EBUSY; + + if (dc1_check && (lp.flags & LP_ABORTOPEN) + && !(file->f_flags & O_NONBLOCK)) { + /* + * Check whether printer is on-line. + * PC-9800's old style port have only BUSY# as status input, + * so that it is impossible to distinguish that the printer is + * ready and that the printer is off-line or not connected + * (in both case BUSY# is in the same state). So: + * + * (1) output DC1 (0x11) to printer port and do strobe. + * (2) watch BUSY# line for a while. If BUSY# is pulled + * down, the printer will be ready. Otherwise, + * it will be off-line (or not connected, or power-off, + * ...). + * + * The source of this procedure: + * Terumasa KODAKA, Kazufumi SHIMIZU, Yu HAYAMI: + * `PC-9801 Super Technique', Ascii, 1992. + */ + int count; + unsigned long flags; + + /* interrupts while check is fairly bad */ + spin_lock_irqsave(&lp_old98_lock, flags); + + if (!lp_old98_char(DC1)) { + spin_unlock_irqrestore(&lp_old98_lock, flags); + return -EBUSY; + } + count = (unsigned int)dc1_check > 10000 ? 10000 : dc1_check; + while (inb(LP_PORT_STATUS) & LP_MASK_nBUSY) { + if (--count == 0) { + spin_unlock_irqrestore(&lp_old98_lock, flags); + return -ENODEV; + } + } + spin_unlock_irqrestore(&lp_old98_lock, flags); + } + + if ((lp.lp_buffer = kmalloc(LP_BUFFER_SIZE, GFP_KERNEL)) == NULL) + return -ENOMEM; + + lp.flags |= LP_BUSY; + +#ifdef CONFIG_PC9800_OLDLP_CONSOLE + saved_console_flags = lp_old98_console.flags; + lp_old98_console.flags &= ~CON_ENABLED; +#endif + return 0; +} + +static int lp_old98_release(struct inode * inode, struct file * file) +{ + kfree(lp.lp_buffer); + lp.lp_buffer = NULL; + lp.flags &= ~LP_BUSY; +#ifdef CONFIG_PC9800_OLDLP_CONSOLE + lp_old98_console.flags = saved_console_flags; +#endif + return 0; +} + +static int lp_old98_init_device(void) +{ + unsigned char data; + + if ((data = inb(LP_PORT_EXTMODE)) != 0xFF && (data & 0x10)) { + printk(KERN_INFO + "lp_old98: shutting down extended parallel port mode...\n"); + outb(data & ~0x10, LP_PORT_EXTMODE); + } +#ifdef PC98_HW_H98 + if ((pc98_hw_flags & PC98_HW_H98) + && ((data = inb(LP_PORT_H98MODE)) & 0x01)) { + printk(KERN_INFO + "lp_old98: shutting down H98 full centronics mode...\n"); + outb(data & ~0x01, LP_PORT_H98MODE); + } +#endif + return 0; +} + +static int lp_old98_ioctl(struct inode *inode, struct file *file, + unsigned int command, unsigned long arg) +{ + int retval = 0; + + switch (command) { + case LPTIME: + lp.time = arg * HZ/100; + break; + case LPCHAR: + lp.chars = arg; + break; + case LPABORT: + if (arg) + lp.flags |= LP_ABORT; + else + lp.flags &= ~LP_ABORT; + break; + case LPABORTOPEN: + if (arg) + lp.flags |= LP_ABORTOPEN; + else + lp.flags &= ~LP_ABORTOPEN; + break; + case LPCAREFUL: + /* do nothing */ + break; + case LPWAIT: + lp.wait = arg; + break; + case LPGETIRQ: + retval = put_user(0, (int *)arg); + break; + case LPGETSTATUS: + /* + * convert PC-9800's status to IBM PC's one, so that tunelp(8) + * works in the same way on this driver. + */ + retval = put_user((inb(LP_PORT_STATUS) & LP_MASK_nBUSY) + ? (LP_PBUSY | LP_PERRORP) : LP_PERRORP, + (int *)arg); + break; + case LPRESET: + retval = lp_old98_init_device(); + break; +#ifdef LP_STATS + case LPGETSTATS: + if (copy_to_user((struct lp_stats *)arg, &lp.stats, + sizeof(struct lp_stats))) + retval = -EFAULT; + else if (suser()) + memset(&lp.stats, 0, sizeof(struct lp_stats)); + break; +#endif + case LPGETFLAGS: + retval = put_user(lp.flags, (int *)arg); + break; + case LPSETIRQ: + default: + retval = -EINVAL; + } + return retval; +} + +static struct file_operations lp_old98_fops = { + .owner = THIS_MODULE, + .write = lp_old98_write, + .ioctl = lp_old98_ioctl, + .open = lp_old98_open, + .release = lp_old98_release, +}; + +/* + * Support for console on lp_old98 + */ +#ifdef CONFIG_PC9800_OLDLP_CONSOLE + +static inline void io_delay(void) +{ + unsigned char dummy; /* actually not output */ + + asm volatile ("out%B0 %0,%1" : "=a"(dummy) : "N"(0x5f)); +} + +static void lp_old98_console_write(struct console *console, + const char *s, unsigned int count) +{ + int i; + static unsigned int timeout_run = 0; + + while (count) { + /* wait approx 1.2 seconds */ + for (i = 2000000; !(inb(LP_PORT_STATUS) & LP_MASK_nBUSY); + io_delay()) + if (!--i) { + if (++timeout_run >= 10) + /* disable forever... */ + console->flags &= ~CON_ENABLED; + return; + } + + timeout_run = 0; + + if (*s == '\n') { + outb('\r', LP_PORT_DATA); + io_delay(); + io_delay(); + outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL); + io_delay(); + io_delay(); + outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL); + io_delay(); + io_delay(); + for (i = 1000000; + !(inb(LP_PORT_STATUS) & LP_MASK_nBUSY); + io_delay()) + if (!--i) + return; + } + + outb(*s++, LP_PORT_DATA); + io_delay(); + io_delay(); + outb(LP_CONTROL_ASSERT_STROBE, LP_PORT_CONTROL); + io_delay(); + io_delay(); + outb(LP_CONTROL_NEGATE_STROBE, LP_PORT_CONTROL); + io_delay(); + io_delay(); + + --count; + } +} + +static kdev_t lp_old98_console_device(struct console *console) +{ + return mk_kdev(LP_MAJOR, 0); +} + +static struct console lp_old98_console = { + .name = "lp_old98", + .write = lp_old98_console_write, + .device = lp_old98_console_device, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +#endif /* console on lp_old98 */ + +static int __init lp_old98_init(void) +{ + char *errmsg = "I/O ports already occupied, giving up."; + +#ifdef PC98_HW_H98 + if (pc98_hw_flags & PC98_HW_H98) + if (!request_region(LP_PORT_H98MODE, 1, "lp_old98") + goto err1; +#endif + if (!request_region(LP_PORT_DATA, 1, "lp_old98")) + goto err2; + if (!request_region(LP_PORT_STATUS, 1, "lp_old98")) + goto err3; + if (!request_region(LP_PORT_STROBE, 1, "lp_old98")) + goto err4; + if (!request_region(LP_PORT_EXTMODE, 1, "lp_old98")) + goto err5; + if (!register_chrdev(LP_MAJOR, "lp", &lp_old98_fops)) { +#ifdef CONFIG_PC9800_OLDLP_CONSOLE + register_console(&lp_old98_console); + printk(KERN_INFO "lp_old98: console ready\n"); +#endif + /* + * rest are not needed by this driver, + * but for locking out other printer drivers... + */ + lp_old98_init_device(); + return 0; + } else + errmsg = "unable to register device"; + + release_region(LP_PORT_EXTMODE, 1); +err5: + release_region(LP_PORT_STROBE, 1); +err4: + release_region(LP_PORT_STATUS, 1); +err3: + release_region(LP_PORT_DATA, 1); +err2: +#ifdef PC98_HW_H98 + if (pc98_hw_flags & PC98_HW_H98) + release_region(LP_PORT_H98MODE, 1); + +err1: +#endif + printk(KERN_ERR "lp_old98: %s\n", errmsg); + return -EBUSY; +} + +static void __exit lp_old98_exit(void) +{ +#ifdef CONFIG_PC9800_OLDLP_CONSOLE + unregister_console(&lp_old98_console); +#endif + unregister_chrdev(LP_MAJOR, "lp"); + + release_region(LP_PORT_DATA, 1); + release_region(LP_PORT_STATUS, 1); + release_region(LP_PORT_STROBE, 1); +#ifdef PC98_HW_H98 + if (pc98_hw_flags & PC98_HW_H98) + release_region(LP_PORT_H98MODE, 1); +#endif + release_region(LP_PORT_EXTMODE, 1); +} + +#ifndef MODULE +static int __init lp_old98_setup(char *str) +{ + int ints[4]; + + str = get_options(str, ARRAY_SIZE(ints), ints); + if (ints[0] > 0) + dc1_check = ints[1]; + return 1; +} +__setup("lp_old98_dc1_check=", lp_old98_setup); +#endif + +MODULE_PARM(dc1_check, "i"); +MODULE_AUTHOR("Kousuke Takai "); +MODULE_DESCRIPTION("PC-9800 old printer port driver"); +MODULE_LICENSE("GPL"); + +module_init(lp_old98_init); +module_exit(lp_old98_exit); diff -urN linux-2.5.65-bk2/drivers/char/mwave/mwavedd.c linux-2.5.65-bk3/drivers/char/mwave/mwavedd.c --- linux-2.5.65-bk2/drivers/char/mwave/mwavedd.c Mon Mar 17 13:43:50 2003 +++ linux-2.5.65-bk3/drivers/char/mwave/mwavedd.c Mon Mar 31 12:41:40 2003 @@ -53,46 +53,20 @@ #include #include #include -#include +#include #include #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #include -#else -#include -#endif #include #include "smapi.h" #include "mwavedd.h" #include "3780i.h" #include "tp3780i.h" -#ifndef __exit -#define __exit -#endif - MODULE_DESCRIPTION("3780i Advanced Communications Processor (Mwave) driver"); MODULE_AUTHOR("Mike Sullivan and Paul Schroeder"); MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static int mwave_get_info(char *buf, char **start, off_t offset, int len); -#else -static int mwave_read_proc(char *buf, char **start, off_t offset, int xlen, int unused); -static struct proc_dir_entry mwave_proc = { - 0, /* unsigned short low_ino */ - 5, /* unsigned short namelen */ - "mwave", /* const char *name */ - S_IFREG | S_IRUGO, /* mode_t mode */ - 1, /* nlink_t nlink */ - 0, /* uid_t uid */ - 0, /* gid_t gid */ - 0, /* unsigned long size */ - NULL, /* struct inode_operations *ops */ - &mwave_read_proc /* int (*get_info) (...) */ -}; -#endif - /* * These parameters support the setting of MWave resources. Note that no * checks are made against other devices (ie. superio) for conflicts. @@ -157,19 +131,23 @@ case IOCTL_MW_RESET: PRINTK_1(TRACE_MWAVE, - "mwavedd::mwave_ioctl, IOCTL_MW_RESET calling tp3780I_ResetDSP\n"); + "mwavedd::mwave_ioctl, IOCTL_MW_RESET" + " calling tp3780I_ResetDSP\n"); retval = tp3780I_ResetDSP(&pDrvData->rBDData); PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_ioctl, IOCTL_MW_RESET retval %x from tp3780I_ResetDSP\n", + "mwavedd::mwave_ioctl, IOCTL_MW_RESET" + " retval %x from tp3780I_ResetDSP\n", retval); break; case IOCTL_MW_RUN: PRINTK_1(TRACE_MWAVE, - "mwavedd::mwave_ioctl, IOCTL_MW_RUN calling tp3780I_StartDSP\n"); + "mwavedd::mwave_ioctl, IOCTL_MW_RUN" + " calling tp3780I_StartDSP\n"); retval = tp3780I_StartDSP(&pDrvData->rBDData); PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_ioctl, IOCTL_MW_RUN retval %x from tp3780I_StartDSP\n", + "mwavedd::mwave_ioctl, IOCTL_MW_RUN" + " retval %x from tp3780I_StartDSP\n", retval); break; @@ -177,17 +155,24 @@ MW_ABILITIES rAbilities; PRINTK_1(TRACE_MWAVE, - "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES calling tp3780I_QueryAbilities\n"); - retval = tp3780I_QueryAbilities(&pDrvData->rBDData, &rAbilities); + "mwavedd::mwave_ioctl," + " IOCTL_MW_DSP_ABILITIES calling" + " tp3780I_QueryAbilities\n"); + retval = tp3780I_QueryAbilities(&pDrvData->rBDData, + &rAbilities); PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES retval %x from tp3780I_QueryAbilities\n", + "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES" + " retval %x from tp3780I_QueryAbilities\n", retval); if (retval == 0) { - if( copy_to_user((char *) ioarg, (char *) &rAbilities, sizeof(MW_ABILITIES)) ) + if( copy_to_user((char *) ioarg, + (char *) &rAbilities, + sizeof(MW_ABILITIES)) ) return -EFAULT; } PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES exit retval %x\n", + "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES" + " exit retval %x\n", retval); } break; @@ -197,15 +182,21 @@ MW_READWRITE rReadData; unsigned short *pusBuffer = 0; - if( copy_from_user((char *) &rReadData, (char *) ioarg, sizeof(MW_READWRITE)) ) + if( copy_from_user((char *) &rReadData, + (char *) ioarg, + sizeof(MW_READWRITE)) ) return -EFAULT; pusBuffer = (unsigned short *) (rReadData.pBuf); PRINTK_4(TRACE_MWAVE, - "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA, size %lx, ioarg %lx pusBuffer %p\n", + "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA," + " size %lx, ioarg %lx pusBuffer %p\n", rReadData.ulDataLength, ioarg, pusBuffer); - retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd, - (void *) pusBuffer, rReadData.ulDataLength, rReadData.usDspAddress); + retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, + iocmd, + (void *) pusBuffer, + rReadData.ulDataLength, + rReadData.usDspAddress); } break; @@ -213,12 +204,14 @@ MW_READWRITE rReadData; unsigned short *pusBuffer = 0; - if( copy_from_user((char *) &rReadData, (char *) ioarg, sizeof(MW_READWRITE)) ) + if( copy_from_user((char *) &rReadData, (char *) ioarg, + sizeof(MW_READWRITE)) ) return -EFAULT; pusBuffer = (unsigned short *) (rReadData.pBuf); PRINTK_4(TRACE_MWAVE, - "mwavedd::mwave_ioctl IOCTL_MW_READ_INST, size %lx, ioarg %lx pusBuffer %p\n", + "mwavedd::mwave_ioctl IOCTL_MW_READ_INST," + " size %lx, ioarg %lx pusBuffer %p\n", rReadData.ulDataLength / 2, ioarg, pusBuffer); retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, @@ -232,16 +225,21 @@ MW_READWRITE rWriteData; unsigned short *pusBuffer = 0; - if( copy_from_user((char *) &rWriteData, (char *) ioarg, sizeof(MW_READWRITE)) ) + if( copy_from_user((char *) &rWriteData, + (char *) ioarg, + sizeof(MW_READWRITE)) ) return -EFAULT; pusBuffer = (unsigned short *) (rWriteData.pBuf); PRINTK_4(TRACE_MWAVE, - "mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA, size %lx, ioarg %lx pusBuffer %p\n", + "mwavedd::mwave_ioctl IOCTL_MW_WRITE_DATA," + " size %lx, ioarg %lx pusBuffer %p\n", rWriteData.ulDataLength, ioarg, pusBuffer); - retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd, - pusBuffer, rWriteData.ulDataLength, rWriteData.usDspAddress); + retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, + iocmd, pusBuffer, + rWriteData.ulDataLength, + rWriteData.usDspAddress); } break; @@ -249,16 +247,21 @@ MW_READWRITE rWriteData; unsigned short *pusBuffer = 0; - if( copy_from_user((char *) &rWriteData, (char *) ioarg, sizeof(MW_READWRITE)) ) + if( copy_from_user((char *) &rWriteData, + (char *) ioarg, + sizeof(MW_READWRITE)) ) return -EFAULT; pusBuffer = (unsigned short *) (rWriteData.pBuf); PRINTK_4(TRACE_MWAVE, - "mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST, size %lx, ioarg %lx pusBuffer %p\n", + "mwavedd::mwave_ioctl IOCTL_MW_WRITE_INST," + " size %lx, ioarg %lx pusBuffer %p\n", rWriteData.ulDataLength, ioarg, pusBuffer); - retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, iocmd, - pusBuffer, rWriteData.ulDataLength, rWriteData.usDspAddress); + retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, + iocmd, pusBuffer, + rWriteData.ulDataLength, + rWriteData.usDspAddress); } break; @@ -266,23 +269,25 @@ unsigned int ipcnum = (unsigned int) ioarg; PRINTK_3(TRACE_MWAVE, - "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC ipcnum %x entry usIntCount %x\n", + "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" + " ipcnum %x entry usIntCount %x\n", ipcnum, pDrvData->IPCs[ipcnum].usIntCount); - if (ipcnum > 16) { - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: IOCTL_MW_REGISTER_IPC: Error: Invalid ipcnum %x\n", ipcnum); + if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) { + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd::mwave_ioctl:" + " IOCTL_MW_REGISTER_IPC:" + " Error: Invalid ipcnum %x\n", + ipcnum); return -EINVAL; } pDrvData->IPCs[ipcnum].bIsHere = FALSE; pDrvData->IPCs[ipcnum].bIsEnabled = TRUE; - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - #else - current->priority = 0x28; /* boost to provide priority timing */ - #endif PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC ipcnum %x exit\n", + "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" + " ipcnum %x exit\n", ipcnum); } break; @@ -293,17 +298,22 @@ unsigned long flags; PRINTK_3(TRACE_MWAVE, - "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC ipcnum %x, usIntCount %x\n", + "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC" + " ipcnum %x, usIntCount %x\n", ipcnum, pDrvData->IPCs[ipcnum].usIntCount); - if (ipcnum > 16) { - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: IOCTL_MW_GET_IPC: Error: Invalid ipcnum %x\n", ipcnum); + if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) { + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd::mwave_ioctl:" + " IOCTL_MW_GET_IPC: Error:" + " Invalid ipcnum %x\n", ipcnum); return -EINVAL; } if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_ioctl, thread for ipc %x going to sleep\n", + "mwavedd::mwave_ioctl, thread for" + " ipc %x going to sleep\n", ipcnum); spin_lock_irqsave(&ipc_lock, flags); @@ -313,10 +323,13 @@ pDrvData->IPCs[ipcnum].usIntCount = 2; /* first int has been handled */ spin_unlock_irqrestore(&ipc_lock, flags); PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC ipcnum %x handling first int\n", + "mwavedd::mwave_ioctl" + " IOCTL_MW_GET_IPC ipcnum %x" + " handling first int\n", ipcnum); } else { /* either 1st int has not yet occurred, or we have already handled the first int */ pDrvData->IPCs[ipcnum].bIsHere = TRUE; +#warning "Sleeping on spinlock" interruptible_sleep_on(&pDrvData->IPCs[ipcnum].ipc_wait_queue); pDrvData->IPCs[ipcnum].bIsHere = FALSE; if (pDrvData->IPCs[ipcnum].usIntCount == 1) { @@ -325,11 +338,16 @@ } spin_unlock_irqrestore(&ipc_lock, flags); PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC ipcnum %x woke up and returning to application\n", + "mwavedd::mwave_ioctl" + " IOCTL_MW_GET_IPC ipcnum %x" + " woke up and returning to" + " application\n", ipcnum); } PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC, returning thread for ipc %x processing\n", + "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC," + " returning thread for ipc %x" + " processing\n", ipcnum); } } @@ -339,10 +357,15 @@ unsigned int ipcnum = (unsigned int) ioarg; PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC ipcnum %x\n", + "mwavedd::mwave_ioctl IOCTL_MW_UNREGISTER_IPC" + " ipcnum %x\n", ipcnum); - if (ipcnum > 16) { - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: IOCTL_MW_UNREGISTER_IPC: Error: Invalid ipcnum %x\n", ipcnum); + if (ipcnum > ARRAY_SIZE(pDrvData->IPCs)) { + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd::mwave_ioctl:" + " IOCTL_MW_UNREGISTER_IPC:" + " Error: Invalid ipcnum %x\n", + ipcnum); return -EINVAL; } if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { @@ -355,7 +378,9 @@ break; default: - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl: Error: Unrecognized iocmd %x\n", iocmd); + PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl:" + " Error: Unrecognized iocmd %x\n", + iocmd); return -ENOTTY; break; } /* switch */ @@ -381,7 +406,8 @@ size_t count, loff_t * ppos) { PRINTK_5(TRACE_MWAVE, - "mwavedd::mwave_write entry file %p, buf %p, count %x ppos %p\n", + "mwavedd::mwave_write entry file %p, buf %p," + " count %x ppos %p\n", file, buf, count, ppos); return -EINVAL; @@ -400,7 +426,9 @@ /* OK */ break; default: - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::register_serial_portandirq: Error: Illegal port %x\n", port ); + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd::register_serial_portandirq:" + " Error: Illegal port %x\n", port ); return -1; } /* switch */ /* port is okay */ @@ -413,7 +441,9 @@ /* OK */ break; default: - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::register_serial_portandirq: Error: Illegal irq %x\n", irq ); + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd::register_serial_portandirq:" + " Error: Illegal irq %x\n", irq ); return -1; } /* switch */ /* irq is okay */ @@ -427,7 +457,6 @@ } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) static struct file_operations mwave_fops = { .owner = THIS_MODULE, .read = mwave_read, @@ -436,24 +465,46 @@ .open = mwave_open, .release = mwave_close }; -#else -static struct file_operations mwave_fops = { - NULL, /* lseek */ - mwave_read, /* read */ - mwave_write, /* write */ - NULL, /* readdir */ - NULL, /* poll */ - mwave_ioctl, /* ioctl */ - NULL, /* mmap */ - mwave_open, /* open */ - NULL, /* flush */ - mwave_close /* release */ -}; -#endif + static struct miscdevice mwave_misc_dev = { MWAVE_MINOR, "mwave", &mwave_fops }; /* + * sysfs support + */ + +struct device mwave_device; + +/* Prevent code redundancy, create a macro for mwave_show_* functions. */ +#define mwave_show_function(attr_name, format_string, field) \ +static ssize_t mwave_show_##attr_name(struct device *dev, char *buf) \ +{ \ + DSP_3780I_CONFIG_SETTINGS *pSettings = \ + &mwave_s_mdd.rBDData.rDspSettings; \ + return sprintf(buf, format_string, pSettings->field); \ +} + +/* All of our attributes are read attributes. */ +#define mwave_dev_rd_attr(attr_name, format_string, field) \ + mwave_show_function(attr_name, format_string, field) \ +static DEVICE_ATTR(attr_name, S_IRUGO, mwave_show_##attr_name, NULL) + +mwave_dev_rd_attr (3780i_dma, "%i\n", usDspDma); +mwave_dev_rd_attr (3780i_irq, "%i\n", usDspIrq); +mwave_dev_rd_attr (3780i_io, "%#.4x\n", usDspBaseIO); +mwave_dev_rd_attr (uart_irq, "%i\n", usUartIrq); +mwave_dev_rd_attr (uart_io, "%#.4x\n", usUartBaseIO); + +static struct device_attribute * const mwave_dev_attrs[] = { + &dev_attr_3780i_dma, + &dev_attr_3780i_irq, + &dev_attr_3780i_io, + &dev_attr_uart_irq, + &dev_attr_uart_io, +}; + + +/* * mwave_init is called on module load * * mwave_exit is called on module unload @@ -461,17 +512,16 @@ */ static void mwave_exit(void) { + int i; pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd; PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_exit entry\n"); - if (pDrvData->bProcEntryCreated) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - remove_proc_entry("mwave", NULL); -#else - proc_unregister(&proc_root, mwave_proc.low_ino); -#endif + for (i = 0; i < ARRAY_SIZE(mwave_dev_attrs); i++) { + device_remove_file(&mwave_device, mwave_dev_attrs[i]); } + device_unregister(&mwave_device); + if ( pDrvData->sLine >= 0 ) { unregister_serial(pDrvData->sLine); } @@ -497,72 +547,81 @@ { int i; int retval = 0; - unsigned int resultMiscRegister; pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd; - memset(&mwave_s_mdd, 0, sizeof(MWAVE_DEVICE_DATA)); - PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_init entry\n"); + memset(&mwave_s_mdd, 0, sizeof(MWAVE_DEVICE_DATA)); + pDrvData->bBDInitialized = FALSE; pDrvData->bResourcesClaimed = FALSE; pDrvData->bDSPEnabled = FALSE; pDrvData->bDSPReset = FALSE; pDrvData->bMwaveDevRegistered = FALSE; pDrvData->sLine = -1; - pDrvData->bProcEntryCreated = FALSE; - for (i = 0; i < 16; i++) { + for (i = 0; i < ARRAY_SIZE(pDrvData->IPCs); i++) { pDrvData->IPCs[i].bIsEnabled = FALSE; pDrvData->IPCs[i].bIsHere = FALSE; pDrvData->IPCs[i].usIntCount = 0; /* no ints received yet */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) init_waitqueue_head(&pDrvData->IPCs[i].ipc_wait_queue); -#endif } retval = tp3780I_InitializeBoardData(&pDrvData->rBDData); PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_init, return from tp3780I_InitializeBoardData retval %x\n", + "mwavedd::mwave_init, return from tp3780I_InitializeBoardData" + " retval %x\n", retval); if (retval) { - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_init: Error: Failed to initialize board data\n"); + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd::mwave_init: Error:" + " Failed to initialize board data\n"); goto cleanup_error; } pDrvData->bBDInitialized = TRUE; retval = tp3780I_CalcResources(&pDrvData->rBDData); PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_init, return from tp3780I_CalcResources retval %x\n", + "mwavedd::mwave_init, return from tp3780I_CalcResources" + " retval %x\n", retval); if (retval) { - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to calculate resources\n"); + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd:mwave_init: Error:" + " Failed to calculate resources\n"); goto cleanup_error; } retval = tp3780I_ClaimResources(&pDrvData->rBDData); PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_init, return from tp3780I_ClaimResources retval %x\n", + "mwavedd::mwave_init, return from tp3780I_ClaimResources" + " retval %x\n", retval); if (retval) { - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to claim resources\n"); + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd:mwave_init: Error:" + " Failed to claim resources\n"); goto cleanup_error; } pDrvData->bResourcesClaimed = TRUE; retval = tp3780I_EnableDSP(&pDrvData->rBDData); PRINTK_2(TRACE_MWAVE, - "mwavedd::mwave_init, return from tp3780I_EnableDSP retval %x\n", + "mwavedd::mwave_init, return from tp3780I_EnableDSP" + " retval %x\n", retval); if (retval) { - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to enable DSP\n"); + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd:mwave_init: Error:" + " Failed to enable DSP\n"); goto cleanup_error; } pDrvData->bDSPEnabled = TRUE; - resultMiscRegister = misc_register(&mwave_misc_dev); - if (resultMiscRegister < 0) { - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to register misc device\n"); + if (misc_register(&mwave_misc_dev) < 0) { + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd:mwave_init: Error:" + " Failed to register misc device\n"); goto cleanup_error; } pDrvData->bMwaveDevRegistered = TRUE; @@ -572,28 +631,36 @@ pDrvData->rBDData.rDspSettings.usUartIrq ); if (pDrvData->sLine < 0) { - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd:mwave_init: Error: Failed to register serial driver\n"); + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd:mwave_init: Error:" + " Failed to register serial driver\n"); goto cleanup_error; } /* uart is registered */ - if ( -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) - !create_proc_info_entry("mwave", 0, NULL, mwave_get_info) -#else - proc_register(&proc_root, &mwave_proc) -#endif - ) { - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_init: Error: Failed to register /proc/mwave\n"); - goto cleanup_error; + /* sysfs */ + memset(&mwave_device, 0, sizeof (struct device)); + snprintf(mwave_device.name, DEVICE_NAME_SIZE, "mwave"); + snprintf(mwave_device.bus_id, BUS_ID_SIZE, "mwave"); + + device_register(&mwave_device); + for (i = 0; i < ARRAY_SIZE(mwave_dev_attrs); i++) { + if(device_create_file(&mwave_device, mwave_dev_attrs[i])) { + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd:mwave_init: Error:" + " Failed to create sysfs file %s\n", + mwave_dev_attrs[i]->attr.name); + goto cleanup_error; + } } - pDrvData->bProcEntryCreated = TRUE; /* SUCCESS! */ return 0; cleanup_error: - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_init: Error: Failed to initialize\n"); + PRINTK_ERROR(KERN_ERR_MWAVE + "mwavedd::mwave_init: Error:" + " Failed to initialize\n"); mwave_exit(); /* clean up */ return -EIO; @@ -601,39 +668,3 @@ module_init(mwave_init); - -/* -* proc entry stuff added by Ian Pilcher -*/ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static int mwave_get_info(char *buf, char **start, off_t offset, int len) -{ - DSP_3780I_CONFIG_SETTINGS *pSettings = &mwave_s_mdd.rBDData.rDspSettings; - - char *out = buf; - - out += sprintf(out, "3780i_IRQ %i\n", pSettings->usDspIrq); - out += sprintf(out, "3780i_DMA %i\n", pSettings->usDspDma); - out += sprintf(out, "3780i_IO %#.4x\n", pSettings->usDspBaseIO); - out += sprintf(out, "UART_IRQ %i\n", pSettings->usUartIrq); - out += sprintf(out, "UART_IO %#.4x\n", pSettings->usUartBaseIO); - - return out - buf; -} -#else /* kernel version < 2.4.0 */ -static int mwave_read_proc(char *buf, char **start, off_t offset, - int xlen, int unused) -{ - DSP_3780I_CONFIG_SETTINGS *pSettings = &mwave_s_mdd.rBDData.rDspSettings; - int len; - - len = sprintf(buf, "3780i_IRQ %i\n", pSettings->usDspIrq); - len += sprintf(&buf[len], "3780i_DMA %i\n", pSettings->usDspDma); - len += sprintf(&buf[len], "3780i_IO %#.4x\n", pSettings->usDspBaseIO); - len += sprintf(&buf[len], "UART_IRQ %i\n", pSettings->usUartIrq); - len += sprintf(&buf[len], "UART_IO %#.4x\n", pSettings->usUartBaseIO); - - return len; -} -#endif diff -urN linux-2.5.65-bk2/drivers/char/mwave/mwavedd.h linux-2.5.65-bk3/drivers/char/mwave/mwavedd.h --- linux-2.5.65-bk2/drivers/char/mwave/mwavedd.h Mon Mar 17 13:44:08 2003 +++ linux-2.5.65-bk3/drivers/char/mwave/mwavedd.h Mon Mar 31 12:41:40 2003 @@ -126,11 +126,7 @@ BOOLEAN bIsEnabled; BOOLEAN bIsHere; /* entry spin lock */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) wait_queue_head_t ipc_wait_queue; -#else - struct wait_queue *ipc_wait_queue; -#endif } MWAVE_IPC; typedef struct _MWAVE_DEVICE_DATA { @@ -143,7 +139,6 @@ BOOLEAN bDSPReset; MWAVE_IPC IPCs[16]; BOOLEAN bMwaveDevRegistered; - BOOLEAN bProcEntryCreated; short sLine; } MWAVE_DEVICE_DATA, *pMWAVE_DEVICE_DATA; diff -urN linux-2.5.65-bk2/drivers/char/mwave/mwavepub.h linux-2.5.65-bk3/drivers/char/mwave/mwavepub.h --- linux-2.5.65-bk2/drivers/char/mwave/mwavepub.h Mon Mar 17 13:44:51 2003 +++ linux-2.5.65-bk3/drivers/char/mwave/mwavepub.h Mon Mar 31 12:41:40 2003 @@ -50,13 +50,8 @@ #ifndef _LINUX_MWAVEPUB_H #define _LINUX_MWAVEPUB_H -#ifndef MWAVEM_APP_DIST #include -#endif -#ifdef MWAVEM_APP_DIST -#define MWAVE_MINOR 219 -#endif typedef struct _MW_ABILITIES { unsigned long instr_per_sec; diff -urN linux-2.5.65-bk2/drivers/char/mwave/smapi.c linux-2.5.65-bk3/drivers/char/mwave/smapi.c --- linux-2.5.65-bk2/drivers/char/mwave/smapi.c Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/drivers/char/mwave/smapi.c Mon Mar 31 12:41:40 2003 @@ -280,10 +280,11 @@ if ((usSI & 0xFF) == mwave_uart_irq) { #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES PRINTK_ERROR(KERN_ERR_MWAVE + "smapi::smapi_set_DSP_cfg: Serial port A irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq); #else PRINTK_3(TRACE_SMAPI, + "smapi::smapi_set_DSP_cfg: Serial port A irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq); #endif - "smapi::smapi_set_DSP_cfg: Serial port A irq %x conflicts with mwave_uart_irq %x\n", usSI, mwave_uart_irq); #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES PRINTK_1(TRACE_SMAPI, "smapi::smapi_set_DSP_cfg Disabling conflicting serial port\n"); @@ -300,13 +301,14 @@ if ((usSI >> 8) == uartio_index) { #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES PRINTK_ERROR(KERN_ERR_MWAVE + "smapi::smapi_set_DSP_cfg: Serial port A base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]); #else PRINTK_3(TRACE_SMAPI, + "smapi::smapi_set_DSP_cfg: Serial port A base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]); #endif - "smapi::smapi_set_DSP_cfg: Serial port A base I/O address index %x conflicts with uartio_index %x\n", usSI >> 8, uartio_index); #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES PRINTK_1(TRACE_SMAPI, - "smapi::smapi_set_DSP_cfg Disabling conflicting serial port\n"); + "smapi::smapi_set_DSP_cfg Disabling conflicting serial port A\n"); bRC = smapi_request (0x1403, 0x0100, 0, usSI, &usAX, &usBX, &usCX, &usDX, &usDI, &usSI); if (bRC) goto exit_smapi_request_error; @@ -331,13 +333,14 @@ if ((usSI & 0xFF) == mwave_uart_irq) { #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES PRINTK_ERROR(KERN_ERR_MWAVE + "smapi::smapi_set_DSP_cfg: Serial port B irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq); #else PRINTK_3(TRACE_SMAPI, + "smapi::smapi_set_DSP_cfg: Serial port B irq %x conflicts with mwave_uart_irq %x\n", usSI & 0xFF, mwave_uart_irq); #endif - "smapi::smapi_set_DSP_cfg: Serial port B irq %x conflicts with mwave_uart_irq %x\n", usSI, mwave_uart_irq); #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES PRINTK_1(TRACE_SMAPI, - "smapi::smapi_set_DSP_cfg Disabling conflicting serial port\n"); + "smapi::smapi_set_DSP_cfg Disabling conflicting serial port B\n"); bRC = smapi_request(0x1405, 0x0100, 0, usSI, &usAX, &usBX, &usCX, &usDX, &usDI, &usSI); if (bRC) goto exit_smapi_request_error; @@ -351,13 +354,14 @@ if ((usSI >> 8) == uartio_index) { #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES PRINTK_ERROR(KERN_ERR_MWAVE + "smapi::smapi_set_DSP_cfg: Serial port B base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]); #else PRINTK_3(TRACE_SMAPI, + "smapi::smapi_set_DSP_cfg: Serial port B base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI >> 8], ausUartBases[uartio_index]); #endif - "smapi::smapi_set_DSP_cfg: Serial port B base I/O address index %x conflicts with uartio_index %x\n", usSI >> 8, uartio_index); #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES PRINTK_1 (TRACE_SMAPI, - "smapi::smapi_set_DSP_cfg Disabling conflicting serial port\n"); + "smapi::smapi_set_DSP_cfg Disabling conflicting serial port B\n"); bRC = smapi_request (0x1405, 0x0100, 0, usSI, &usAX, &usBX, &usCX, &usDX, &usDI, &usSI); if (bRC) goto exit_smapi_request_error; @@ -380,39 +384,15 @@ &usAX, &usBX, &usCX, &usDX, &usDI, &usSI); if (bRC) goto exit_smapi_request_error; /* bRC == 0 */ - if ((usCX & 0xff) == mwave_uart_irq) { /* serial port is enabled */ -#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES - PRINTK_ERROR(KERN_ERR_MWAVE -#else - PRINTK_3(TRACE_SMAPI, -#endif - "smapi::smapi_set_DSP_cfg: IR port irq %x conflicts with mwave_uart_irq %x\n", usSI, mwave_uart_irq); -#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES - PRINTK_1(TRACE_SMAPI, - "smapi::smapi_set_DSP_cfg Disabling conflicting IR port\n"); - bRC = smapi_request(0x1701, 0x0100, 0, 0, - &usAX, &usBX, &usCX, &usDX, &usDI, &usSI); - if (bRC) goto exit_smapi_request_error; - bRC = smapi_request(0x1700, 0, 0, 0, - &usAX, &usBX, &usCX, &usDX, &usDI, &usSI); - if (bRC) goto exit_smapi_request_error; - bRC = smapi_request(0x1705, 0x01ff, 0, usSI, - &usAX, &usBX, &usCX, &usDX, &usDI, &usSI); - if (bRC) goto exit_smapi_request_error; - bRC = smapi_request(0x1704, 0x0000, 0, 0, - &usAX, &usBX, &usCX, &usDX, &usDI, &usSI); - if (bRC) goto exit_smapi_request_error; -#else - goto exit_conflict; -#endif - } else { - if ((usSI & 0xff) == uartio_index) { + if ((usCX & 0xff) != 0xff) { /* IR port not disabled */ + if ((usCX & 0xff) == mwave_uart_irq) { #ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES PRINTK_ERROR(KERN_ERR_MWAVE + "smapi::smapi_set_DSP_cfg: IR port irq %x conflicts with mwave_uart_irq %x\n", usCX & 0xff, mwave_uart_irq); #else PRINTK_3(TRACE_SMAPI, + "smapi::smapi_set_DSP_cfg: IR port irq %x conflicts with mwave_uart_irq %x\n", usCX & 0xff, mwave_uart_irq); #endif - "smapi::smapi_set_DSP_cfg: IR port base I/O address index %x conflicts with uartio_index %x\n", usSI & 0xff, uartio_index); #ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES PRINTK_1(TRACE_SMAPI, "smapi::smapi_set_DSP_cfg Disabling conflicting IR port\n"); @@ -431,6 +411,34 @@ #else goto exit_conflict; #endif + } else { + if ((usSI & 0xff) == uartio_index) { +#ifndef MWAVE_FUTZ_WITH_OTHER_DEVICES + PRINTK_ERROR(KERN_ERR_MWAVE + "smapi::smapi_set_DSP_cfg: IR port base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI & 0xff], ausUartBases[uartio_index]); +#else + PRINTK_3(TRACE_SMAPI, + "smapi::smapi_set_DSP_cfg: IR port base I/O address %x conflicts with mwave uart I/O %x\n", ausUartBases[usSI & 0xff], ausUartBases[uartio_index]); +#endif +#ifdef MWAVE_FUTZ_WITH_OTHER_DEVICES + PRINTK_1(TRACE_SMAPI, + "smapi::smapi_set_DSP_cfg Disabling conflicting IR port\n"); + bRC = smapi_request(0x1701, 0x0100, 0, 0, + &usAX, &usBX, &usCX, &usDX, &usDI, &usSI); + if (bRC) goto exit_smapi_request_error; + bRC = smapi_request(0x1700, 0, 0, 0, + &usAX, &usBX, &usCX, &usDX, &usDI, &usSI); + if (bRC) goto exit_smapi_request_error; + bRC = smapi_request(0x1705, 0x01ff, 0, usSI, + &usAX, &usBX, &usCX, &usDX, &usDI, &usSI); + if (bRC) goto exit_smapi_request_error; + bRC = smapi_request(0x1704, 0x0000, 0, 0, + &usAX, &usBX, &usCX, &usDX, &usDI, &usSI); + if (bRC) goto exit_smapi_request_error; +#else + goto exit_conflict; +#endif + } } } } diff -urN linux-2.5.65-bk2/drivers/char/rio/rioboot.c linux-2.5.65-bk3/drivers/char/rio/rioboot.c --- linux-2.5.65-bk2/drivers/char/rio/rioboot.c Mon Mar 17 13:43:49 2003 +++ linux-2.5.65-bk3/drivers/char/rio/rioboot.c Mon Mar 31 12:41:40 2003 @@ -34,7 +34,6 @@ static char *_rioboot_c_sccs_ = "@(#)rioboot.c 1.3"; #endif -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/drivers/char/rio/riocmd.c linux-2.5.65-bk3/drivers/char/rio/riocmd.c --- linux-2.5.65-bk2/drivers/char/rio/riocmd.c Mon Mar 17 13:43:50 2003 +++ linux-2.5.65-bk3/drivers/char/rio/riocmd.c Mon Mar 31 12:41:40 2003 @@ -34,7 +34,6 @@ static char *_riocmd_c_sccs_ = "@(#)riocmd.c 1.2"; #endif -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/drivers/char/rio/rioctrl.c linux-2.5.65-bk3/drivers/char/rio/rioctrl.c --- linux-2.5.65-bk2/drivers/char/rio/rioctrl.c Mon Mar 17 13:44:04 2003 +++ linux-2.5.65-bk3/drivers/char/rio/rioctrl.c Mon Mar 31 12:41:40 2003 @@ -34,7 +34,6 @@ #endif -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/drivers/char/rio/rioinit.c linux-2.5.65-bk3/drivers/char/rio/rioinit.c --- linux-2.5.65-bk2/drivers/char/rio/rioinit.c Mon Mar 17 13:43:50 2003 +++ linux-2.5.65-bk3/drivers/char/rio/rioinit.c Mon Mar 31 12:41:40 2003 @@ -33,7 +33,6 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3"; #endif -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/drivers/char/rio/riointr.c linux-2.5.65-bk3/drivers/char/rio/riointr.c --- linux-2.5.65-bk2/drivers/char/rio/riointr.c Mon Mar 17 13:43:37 2003 +++ linux-2.5.65-bk3/drivers/char/rio/riointr.c Mon Mar 31 12:41:40 2003 @@ -34,7 +34,6 @@ #endif -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/drivers/char/rio/rioparam.c linux-2.5.65-bk3/drivers/char/rio/rioparam.c --- linux-2.5.65-bk2/drivers/char/rio/rioparam.c Mon Mar 17 13:44:51 2003 +++ linux-2.5.65-bk3/drivers/char/rio/rioparam.c Mon Mar 31 12:41:40 2003 @@ -34,7 +34,6 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3"; #endif -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/drivers/char/rio/rioroute.c linux-2.5.65-bk3/drivers/char/rio/rioroute.c --- linux-2.5.65-bk2/drivers/char/rio/rioroute.c Mon Mar 17 13:44:07 2003 +++ linux-2.5.65-bk3/drivers/char/rio/rioroute.c Mon Mar 31 12:41:40 2003 @@ -33,7 +33,6 @@ static char *_rioroute_c_sccs_ = "@(#)rioroute.c 1.3"; #endif -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/drivers/char/rio/riotable.c linux-2.5.65-bk3/drivers/char/rio/riotable.c --- linux-2.5.65-bk2/drivers/char/rio/riotable.c Mon Mar 17 13:44:45 2003 +++ linux-2.5.65-bk3/drivers/char/rio/riotable.c Mon Mar 31 12:41:40 2003 @@ -33,7 +33,6 @@ static char *_riotable_c_sccs_ = "@(#)riotable.c 1.2"; #endif -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/drivers/char/rio/riotty.c linux-2.5.65-bk3/drivers/char/rio/riotty.c --- linux-2.5.65-bk2/drivers/char/rio/riotty.c Mon Mar 17 13:44:03 2003 +++ linux-2.5.65-bk3/drivers/char/rio/riotty.c Mon Mar 31 12:41:40 2003 @@ -36,7 +36,6 @@ #define __EXPLICIT_DEF_H__ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/drivers/char/rtc.c linux-2.5.65-bk3/drivers/char/rtc.c --- linux-2.5.65-bk2/drivers/char/rtc.c Mon Mar 17 13:44:04 2003 +++ linux-2.5.65-bk3/drivers/char/rtc.c Mon Mar 31 12:41:40 2003 @@ -47,7 +47,7 @@ #define RTC_VERSION "1.11" -#define RTC_IO_EXTENT 0x10 /* Only really two ports, but... */ +#define RTC_IO_EXTENT 0x8 /* * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with diff -urN linux-2.5.65-bk2/drivers/char/upd4990a.c linux-2.5.65-bk3/drivers/char/upd4990a.c --- linux-2.5.65-bk2/drivers/char/upd4990a.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/drivers/char/upd4990a.c Mon Mar 31 12:41:40 2003 @@ -0,0 +1,423 @@ +/* + * NEC PC-9800 Real Time Clock interface for Linux + * + * Copyright (C) 1997-2001 Linux/98 project, + * Kyoto University Microcomputer Club. + * + * Based on: + * drivers/char/rtc.c by Paul Gortmaker + * + * Changes: + * 2001-02-09 Call check_region on rtc_init and do not request I/O 0033h. + * Call del_timer and release_region on rtc_exit. -- tak + * 2001-07-14 Rewrite and split to + * and . + * Introduce a lot of spin_lock/unlock (&rtc_lock). + */ + +#define RTC98_VERSION "1.2" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * We sponge a minor off of the misc major. No need slurping + * up another valuable major dev number for this. If you add + * an ioctl, make sure you don't conflict with SPARC's RTC + * ioctls. + */ + +static struct fasync_struct *rtc_async_queue; + +static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); + +static struct timer_list rtc_uie_timer; +static u8 old_refclk; + +static int rtc_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); + +static int rtc_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data); + +/* + * Bits in rtc_status. (5 bits of room for future expansion) + */ + +#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ +#define RTC_TIMER_ON 0x02 /* not used */ +#define RTC_UIE_TIMER_ON 0x04 /* UIE emulation timer is active */ + +/* + * rtc_status is never changed by rtc_interrupt, and ioctl/open/close is + * protected by the big kernel lock. However, ioctl can still disable the timer + * in rtc_status and then with del_timer after the interrupt has read + * rtc_status but before mod_timer is called, which would then reenable the + * timer (but you would need to have an awful timing before you'd trip on it) + */ +static unsigned char rtc_status; /* bitmapped status byte. */ +static unsigned long rtc_irq_data; /* our output to the world */ + +static const unsigned char days_in_mo[] = +{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +extern spinlock_t rtc_lock; /* defined in arch/i386/kernel/time.c */ + +static void rtc_uie_intr(unsigned long data) +{ + u8 refclk, tmp; + + /* Kernel timer does del_timer internally before calling + each timer entry, so this is unnecessary. + del_timer(&rtc_uie_timer); */ + spin_lock(&rtc_lock); + + /* Detect rising edge of 1Hz reference clock. */ + refclk = UPD4990A_READ_DATA(); + tmp = old_refclk & refclk; + old_refclk = ~refclk; + if (!(tmp & 1)) + rtc_irq_data += 0x100; + + spin_unlock(&rtc_lock); + + if (!(tmp & 1)) { + /* Now do the rest of the actions */ + wake_up_interruptible(&rtc_wait); + kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); + } + + rtc_uie_timer.expires = jiffies + 1; + add_timer(&rtc_uie_timer); +} + +/* + * Now all the various file operations that we export. + */ + +static ssize_t rtc_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long data; + ssize_t retval = 0; + + if (count < sizeof(unsigned long)) + return -EINVAL; + + add_wait_queue(&rtc_wait, &wait); + + set_current_state(TASK_INTERRUPTIBLE); + + do { + /* First make it right. Then make it fast. Putting this whole + * block within the parentheses of a while would be too + * confusing. And no, xchg() is not the answer. */ + spin_lock_irq(&rtc_lock); + data = rtc_irq_data; + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + + if (data != 0) + break; + if (file->f_flags & O_NONBLOCK) { + retval = -EAGAIN; + goto out; + } + if (signal_pending(current)) { + retval = -ERESTARTSYS; + goto out; + } + schedule(); + } while (1); + + retval = put_user(data, (unsigned long *)buf); + if (!retval) + retval = sizeof(unsigned long); + out: + set_current_state(TASK_RUNNING); + remove_wait_queue(&rtc_wait, &wait); + + return retval; +} + +static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct rtc_time wtime; + struct upd4990a_raw_data raw; + + switch (cmd) { + case RTC_UIE_OFF: /* Mask ints from RTC updates. */ + spin_lock_irq(&rtc_lock); + if (rtc_status & RTC_UIE_TIMER_ON) { + rtc_status &= ~RTC_UIE_TIMER_ON; + del_timer(&rtc_uie_timer); + } + spin_unlock_irq(&rtc_lock); + return 0; + + case RTC_UIE_ON: /* Allow ints for RTC updates. */ + spin_lock_irq(&rtc_lock); + rtc_irq_data = 0; + if (!(rtc_status & RTC_UIE_TIMER_ON)) { + rtc_status |= RTC_UIE_TIMER_ON; + rtc_uie_timer.expires = jiffies + 1; + add_timer(&rtc_uie_timer); + } + /* Just in case... */ + upd4990a_serial_command(UPD4990A_REGISTER_HOLD); + old_refclk = ~UPD4990A_READ_DATA(); + spin_unlock_irq(&rtc_lock); + return 0; + + case RTC_RD_TIME: /* Read the time/date from RTC */ + spin_lock_irq(&rtc_lock); + upd4990a_get_time(&raw, 0); + spin_unlock_irq(&rtc_lock); + + wtime.tm_sec = BCD2BIN(raw.sec); + wtime.tm_min = BCD2BIN(raw.min); + wtime.tm_hour = BCD2BIN(raw.hour); + wtime.tm_mday = BCD2BIN(raw.mday); + wtime.tm_mon = raw.mon - 1; /* convert to 0-base */ + wtime.tm_wday = raw.wday; + + /* + * Account for differences between how the RTC uses the values + * and how they are defined in a struct rtc_time; + */ + if ((wtime.tm_year = BCD2BIN(raw.year)) < 95) + wtime.tm_year += 100; + + wtime.tm_isdst = 0; + break; + + case RTC_SET_TIME: /* Set the RTC */ + { + int leap_yr; + + if (!capable(CAP_SYS_TIME)) + return -EACCES; + + if (copy_from_user(&wtime, (struct rtc_time *) arg, + sizeof (struct rtc_time))) + return -EFAULT; + + /* Valid year is 1995 - 2094, inclusive. */ + if (wtime.tm_year < 95 || wtime.tm_year > 194) + return -EINVAL; + + if (wtime.tm_mon > 11 || wtime.tm_mday == 0) + return -EINVAL; + + /* For acceptable year domain (1995 - 2094), + this IS sufficient. */ + leap_yr = !(wtime.tm_year % 4); + + if (wtime.tm_mday > (days_in_mo[wtime.tm_mon] + + (wtime.tm_mon == 2 && leap_yr))) + return -EINVAL; + + if (wtime.tm_hour >= 24 + || wtime.tm_min >= 60 || wtime.tm_sec >= 60) + return -EINVAL; + + if (wtime.tm_wday > 6) + return -EINVAL; + + raw.sec = BIN2BCD(wtime.tm_sec); + raw.min = BIN2BCD(wtime.tm_min); + raw.hour = BIN2BCD(wtime.tm_hour); + raw.mday = BIN2BCD(wtime.tm_mday); + raw.mon = wtime.tm_mon + 1; + raw.wday = wtime.tm_wday; + raw.year = BIN2BCD(wtime.tm_year % 100); + + spin_lock_irq(&rtc_lock); + upd4990a_set_time(&raw, 0); + spin_unlock_irq(&rtc_lock); + + return 0; + } + default: + return -EINVAL; + } + return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; +} + +/* + * We enforce only one user at a time here with the open/close. + * Also clear the previous interrupt data on an open, and clean + * up things on a close. + */ + +static int rtc_open(struct inode *inode, struct file *file) +{ + spin_lock_irq(&rtc_lock); + + if(rtc_status & RTC_IS_OPEN) + goto out_busy; + + rtc_status |= RTC_IS_OPEN; + + rtc_irq_data = 0; + spin_unlock_irq(&rtc_lock); + return 0; + + out_busy: + spin_unlock_irq(&rtc_lock); + return -EBUSY; +} + +static int rtc_fasync(int fd, struct file *filp, int on) +{ + return fasync_helper(fd, filp, on, &rtc_async_queue); +} + +static int rtc_release(struct inode *inode, struct file *file) +{ + del_timer(&rtc_uie_timer); + + if (file->f_flags & FASYNC) + rtc_fasync(-1, file, 0); + + rtc_irq_data = 0; + + /* No need for locking -- nobody else can do anything until this rmw is + * committed, and no timer is running. */ + rtc_status &= ~(RTC_IS_OPEN | RTC_UIE_TIMER_ON); + return 0; +} + +static unsigned int rtc_poll(struct file *file, poll_table *wait) +{ + unsigned long l; + + poll_wait(file, &rtc_wait, wait); + + spin_lock_irq(&rtc_lock); + l = rtc_irq_data; + spin_unlock_irq(&rtc_lock); + + if (l != 0) + return POLLIN | POLLRDNORM; + return 0; +} + +/* + * The various file operations we support. + */ + +static struct file_operations rtc_fops = { + .owner = THIS_MODULE, + .read = rtc_read, + .poll = rtc_poll, + .ioctl = rtc_ioctl, + .open = rtc_open, + .release = rtc_release, + .fasync = rtc_fasync, +}; + +static struct miscdevice rtc_dev= +{ + .minor = RTC_MINOR, + .name = "rtc", + .fops = &rtc_fops, +}; + +static int __init rtc_init(void) +{ + if (!request_region(UPD4990A_IO, 1, "rtc")) { + printk(KERN_ERR "upd4990a: could not acquire I/O port %#x\n", + UPD4990A_IO); + return -EBUSY; + } + +#if 0 + printk(KERN_INFO "\xB6\xDA\xDD\xC0\xDE \xC4\xDE\xB9\xB2 Driver\n"); /* Calender Clock Driver */ +#else + printk(KERN_INFO + "Real Time Clock driver for NEC PC-9800 v" RTC98_VERSION "\n"); +#endif + misc_register(&rtc_dev); + create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL); + + init_timer(&rtc_uie_timer); + rtc_uie_timer.function = rtc_uie_intr; + + return 0; +} + +module_init (rtc_init); + +static void __exit rtc_exit(void) +{ + del_timer(&rtc_uie_timer); + release_region(UPD4990A_IO, 1); + remove_proc_entry("driver/rtc", NULL); + misc_deregister(&rtc_dev); +} + +module_exit (rtc_exit); + +/* + * Info exported via "/proc/driver/rtc". + */ + +static inline int rtc_get_status(char *buf) +{ + char *p; + unsigned int year; + struct upd4990a_raw_data data; + + p = buf; + + upd4990a_get_time(&data, 0); + + /* + * There is no way to tell if the luser has the RTC set for local + * time or for Universal Standard Time (GMT). Probably local though. + */ + if ((year = BCD2BIN(data.year) + 1900) < 1995) + year += 100; + p += sprintf(p, + "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n", + BCD2BIN(data.hour), BCD2BIN(data.min), + BCD2BIN(data.sec), + year, data.mon, BCD2BIN(data.mday)); + + return p - buf; +} + +static int rtc_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = rtc_get_status(page); + + if (len <= off + count) + *eof = 1; + *start = page + off; + len -= off; + if (len > count) + len = count; + if (len < 0) + len = 0; + return len; +} diff -urN linux-2.5.65-bk2/drivers/char/watchdog/acquirewdt.c linux-2.5.65-bk3/drivers/char/watchdog/acquirewdt.c --- linux-2.5.65-bk2/drivers/char/watchdog/acquirewdt.c Mon Mar 17 13:44:14 2003 +++ linux-2.5.65-bk3/drivers/char/watchdog/acquirewdt.c Mon Mar 31 12:41:40 2003 @@ -141,6 +141,8 @@ spin_unlock(&acq_lock); return -EBUSY; } + if (nowayout) + MOD_INC_USE_COUNT; /* Activate */ acq_is_open=1; diff -urN linux-2.5.65-bk2/drivers/char/watchdog/ib700wdt.c linux-2.5.65-bk3/drivers/char/watchdog/ib700wdt.c --- linux-2.5.65-bk2/drivers/char/watchdog/ib700wdt.c Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/drivers/char/watchdog/ib700wdt.c Mon Mar 31 12:41:40 2003 @@ -228,6 +228,8 @@ spin_unlock(&ibwdt_lock); return -EBUSY; } + if (nowayout) + MOD_INC_USE_COUNT; /* Activate */ ibwdt_is_open = 1; diff -urN linux-2.5.65-bk2/drivers/char/watchdog/indydog.c linux-2.5.65-bk3/drivers/char/watchdog/indydog.c --- linux-2.5.65-bk2/drivers/char/watchdog/indydog.c Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/drivers/char/watchdog/indydog.c Mon Mar 31 12:41:40 2003 @@ -53,6 +53,9 @@ if( test_and_set_bit(0,&indydog_alive) ) return -EBUSY; + if (nowayout) + MOD_INC_USE_COUNT; + /* * Activate timer */ diff -urN linux-2.5.65-bk2/drivers/char/watchdog/machzwd.c linux-2.5.65-bk3/drivers/char/watchdog/machzwd.c --- linux-2.5.65-bk2/drivers/char/watchdog/machzwd.c Mon Mar 17 13:43:44 2003 +++ linux-2.5.65-bk3/drivers/char/watchdog/machzwd.c Mon Mar 31 12:41:40 2003 @@ -390,6 +390,9 @@ return -EBUSY; } + if (nowayout) + MOD_INC_USE_COUNT; + zf_is_open = 1; spin_unlock(&zf_lock); diff -urN linux-2.5.65-bk2/drivers/char/watchdog/mixcomwd.c linux-2.5.65-bk3/drivers/char/watchdog/mixcomwd.c --- linux-2.5.65-bk2/drivers/char/watchdog/mixcomwd.c Mon Mar 17 13:43:49 2003 +++ linux-2.5.65-bk3/drivers/char/watchdog/mixcomwd.c Mon Mar 31 12:41:40 2003 @@ -93,7 +93,9 @@ } mixcomwd_ping(); - if (!nowayout) { + if (nowayout) { + MOD_INC_USE_COUNT; + } else { if(mixcomwd_timer_alive) { del_timer(&mixcomwd_timer); mixcomwd_timer_alive=0; diff -urN linux-2.5.65-bk2/drivers/char/watchdog/pcwd.c linux-2.5.65-bk3/drivers/char/watchdog/pcwd.c --- linux-2.5.65-bk2/drivers/char/watchdog/pcwd.c Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/drivers/char/watchdog/pcwd.c Mon Mar 31 12:41:40 2003 @@ -430,7 +430,7 @@ atomic_inc( &open_allowed ); return -EBUSY; } - + MOD_INC_USE_COUNT; /* Enable the port */ if (revision == PCWD_REVISION_C) { spin_lock(&io_lock); diff -urN linux-2.5.65-bk2/drivers/char/watchdog/sbc60xxwdt.c linux-2.5.65-bk3/drivers/char/watchdog/sbc60xxwdt.c --- linux-2.5.65-bk2/drivers/char/watchdog/sbc60xxwdt.c Mon Mar 17 13:44:20 2003 +++ linux-2.5.65-bk3/drivers/char/watchdog/sbc60xxwdt.c Mon Mar 31 12:41:40 2003 @@ -206,7 +206,9 @@ /* Just in case we're already talking to someone... */ if(wdt_is_open) return -EBUSY; - + if (nowayout) { + MOD_INC_USE_COUNT; + } /* Good, fire up the show */ wdt_is_open = 1; wdt_startup(); diff -urN linux-2.5.65-bk2/drivers/char/watchdog/sc520_wdt.c linux-2.5.65-bk3/drivers/char/watchdog/sc520_wdt.c --- linux-2.5.65-bk2/drivers/char/watchdog/sc520_wdt.c Mon Mar 17 13:44:05 2003 +++ linux-2.5.65-bk3/drivers/char/watchdog/sc520_wdt.c Mon Mar 31 12:41:40 2003 @@ -229,6 +229,8 @@ return -EBUSY; /* Good, fire up the show */ wdt_startup(); + if (nowayout) + MOD_INC_USE_COUNT; return 0; default: diff -urN linux-2.5.65-bk2/drivers/char/watchdog/shwdt.c linux-2.5.65-bk3/drivers/char/watchdog/shwdt.c --- linux-2.5.65-bk2/drivers/char/watchdog/shwdt.c Mon Mar 17 13:43:50 2003 +++ linux-2.5.65-bk3/drivers/char/watchdog/shwdt.c Mon Mar 31 12:41:40 2003 @@ -189,6 +189,10 @@ if (test_and_set_bit(0, &sh_is_open)) return -EBUSY; + if (nowayout) { + MOD_INC_USE_COUNT; + } + sh_wdt_start(); break; diff -urN linux-2.5.65-bk2/drivers/char/watchdog/softdog.c linux-2.5.65-bk3/drivers/char/watchdog/softdog.c --- linux-2.5.65-bk2/drivers/char/watchdog/softdog.c Mon Mar 17 13:44:04 2003 +++ linux-2.5.65-bk3/drivers/char/watchdog/softdog.c Mon Mar 31 12:41:40 2003 @@ -103,7 +103,9 @@ { if(test_and_set_bit(0, &timer_alive)) return -EBUSY; - + if (nowayout) { + MOD_INC_USE_COUNT; + } /* * Activate timer */ diff -urN linux-2.5.65-bk2/drivers/char/watchdog/wdt977.c linux-2.5.65-bk3/drivers/char/watchdog/wdt977.c --- linux-2.5.65-bk2/drivers/char/watchdog/wdt977.c Mon Mar 17 13:44:40 2003 +++ linux-2.5.65-bk3/drivers/char/watchdog/wdt977.c Mon Mar 31 12:41:40 2003 @@ -99,6 +99,8 @@ if (nowayout) { + MOD_INC_USE_COUNT; + /* do not permit disabling the watchdog by writing 0 to reg. 0xF2 */ if (!timeoutM) timeoutM = DEFAULT_TIMEOUT; } diff -urN linux-2.5.65-bk2/drivers/char/watchdog/wdt_pci.c linux-2.5.65-bk3/drivers/char/watchdog/wdt_pci.c --- linux-2.5.65-bk2/drivers/char/watchdog/wdt_pci.c Mon Mar 17 13:44:15 2003 +++ linux-2.5.65-bk3/drivers/char/watchdog/wdt_pci.c Mon Mar 31 12:41:40 2003 @@ -365,6 +365,9 @@ if (down_trylock(&open_sem)) return -EBUSY; + if (nowayout) { + MOD_INC_USE_COUNT; + } /* * Activate */ diff -urN linux-2.5.65-bk2/drivers/fc4/fc_syms.c linux-2.5.65-bk3/drivers/fc4/fc_syms.c --- linux-2.5.65-bk2/drivers/fc4/fc_syms.c Mon Mar 17 13:44:41 2003 +++ linux-2.5.65-bk3/drivers/fc4/fc_syms.c Mon Mar 31 12:41:40 2003 @@ -2,7 +2,6 @@ * We should not even be trying to compile this if we are not doing * a module. */ -#define __NO_VERSION__ #include #include diff -urN linux-2.5.65-bk2/drivers/ide/Makefile linux-2.5.65-bk3/drivers/ide/Makefile --- linux-2.5.65-bk2/drivers/ide/Makefile Mon Mar 17 13:44:06 2003 +++ linux-2.5.65-bk3/drivers/ide/Makefile Mon Mar 31 12:41:40 2003 @@ -12,7 +12,7 @@ # Core IDE code - must come before legacy -obj-$(CONFIG_BLK_DEV_IDE) += ide-io.o ide-probe.o ide-geometry.o ide-iops.o ide-taskfile.o ide.o ide-lib.o +obj-$(CONFIG_BLK_DEV_IDE) += ide-io.o ide-probe.o ide-geometry.o ide-iops.o ide-taskfile.o ide.o ide-lib.o ide-default.o obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd.o obj-$(CONFIG_BLK_DEV_IDETAPE) += ide-tape.o diff -urN linux-2.5.65-bk2/drivers/ide/ide-cd.c linux-2.5.65-bk3/drivers/ide/ide-cd.c --- linux-2.5.65-bk2/drivers/ide/ide-cd.c Mon Mar 17 13:44:05 2003 +++ linux-2.5.65-bk3/drivers/ide/ide-cd.c Mon Mar 31 12:41:40 2003 @@ -294,7 +294,7 @@ * *************************************************************************/ -#define IDECD_VERSION "4.59" +#define IDECD_VERSION "4.59-ac1" #include #include @@ -635,6 +635,23 @@ return ide_stopped; } +ide_startstop_t ide_cdrom_abort (ide_drive_t *drive, const char *msg) +{ + struct request *rq; + + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) + return ide_stopped; + /* retry only "normal" I/O: */ + if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) { + rq->errors = 1; + ide_end_drive_cmd(drive, BUSY_STAT, 0); + return ide_stopped; + } + rq->errors |= ERROR_RESET; + DRIVER(drive)->end_request(drive, 0, 0); + return ide_stopped; +} + static void cdrom_end_request (ide_drive_t *drive, int uptodate) { struct request *rq = HWGROUP(drive)->rq; @@ -899,9 +916,6 @@ return startstop; } - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - /* Arm the interrupt handler. */ ide_set_handler(drive, handler, rq->timeout, cdrom_timer_expiry); @@ -1133,9 +1147,6 @@ } } - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - /* Done moving data! Wait for another interrupt. */ ide_set_handler(drive, &cdrom_read_intr, WAIT_CMD, NULL); return ide_started; @@ -1470,9 +1481,6 @@ rq->flags |= REQ_FAILED; } - if (HWGROUP(drive)->handler != NULL) - BUG(); - /* Now we wait for another interrupt. */ ide_set_handler(drive, &cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry); return ide_started; @@ -1863,9 +1871,6 @@ cdrom_end_request(drive, 1); } - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); - /* re-arm handler */ ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL); return ide_started; @@ -2837,11 +2842,9 @@ * ACER50 (and others?) require the full spec length mode sense * page capabilities size, but older drives break. */ - if (drive->id) { - if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") || - !strcmp(drive->id->model, "WPI CDS-32X"))) - size -= sizeof(cap->pad); - } + if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") || + !strcmp(drive->id->model, "WPI CDS-32X"))) + size -= sizeof(cap->pad); /* we have to cheat a little here. the packet will eventually * be queued with ide_cdrom_packet(), which extracts the @@ -2924,7 +2927,7 @@ } /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */ - if (drive->id && !drive->id->model[0] && + if (!drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) { CDROM_STATE_FLAGS(drive)->current_speed = (((unsigned int)cap.curspeed) + (176/2)) / 176; @@ -3089,12 +3092,7 @@ CDROM_CONFIG_FLAGS(drive)->no_doorlock = 0; #endif - if (drive->id != NULL) - CDROM_CONFIG_FLAGS(drive)->drq_interrupt = - ((drive->id->config & 0x0060) == 0x20); - else - CDROM_CONFIG_FLAGS(drive)->drq_interrupt = 0; - + CDROM_CONFIG_FLAGS(drive)->drq_interrupt = ((drive->id->config & 0x0060) == 0x20); CDROM_CONFIG_FLAGS(drive)->is_changer = 0; CDROM_CONFIG_FLAGS(drive)->cd_r = 0; CDROM_CONFIG_FLAGS(drive)->cd_rw = 0; @@ -3109,16 +3107,14 @@ /* limit transfer size per interrupt. */ CDROM_CONFIG_FLAGS(drive)->limit_nframes = 0; - if (drive->id != NULL) { - /* a testament to the nice quality of Samsung drives... */ - if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430")) - CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1; - else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432")) - CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1; - /* the 3231 model does not support the SET_CD_SPEED command */ - else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231")) - cdi->mask |= CDC_SELECT_SPEED; - } + /* a testament to the nice quality of Samsung drives... */ + if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430")) + CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1; + else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432")) + CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1; + /* the 3231 model does not support the SET_CD_SPEED command */ + else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231")) + cdi->mask |= CDC_SELECT_SPEED; #if ! STANDARD_ATAPI /* by default Sanyo 3 CD changer support is turned off and @@ -3131,55 +3127,47 @@ CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 0; CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 0; - if (drive->id != NULL) { - if (strcmp (drive->id->model, "V003S0DS") == 0 && - drive->id->fw_rev[4] == '1' && - drive->id->fw_rev[6] <= '2') { - /* Vertos 300. - Some versions of this drive like to talk BCD. */ - CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1; - } - - else if (strcmp (drive->id->model, "V006E0DS") == 0 && - drive->id->fw_rev[4] == '1' && - drive->id->fw_rev[6] <= '2') { - /* Vertos 600 ESD. */ - CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1; - } - - else if (strcmp(drive->id->model, - "NEC CD-ROM DRIVE:260") == 0 && - strncmp(drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */ - /* Old NEC260 (not R). - This drive was released before the 1.2 version - of the spec. */ - CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->nec260 = 1; - } - - else if (strcmp(drive->id->model, "WEARNES CDD-120") == 0 && - strncmp(drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */ - /* Wearnes */ - CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1; - CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1; - } - - /* Sanyo 3 CD changer uses a non-standard command - for CD changing */ - else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) || - (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) || - (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) { - /* uses CD in slot 0 when value is set to 3 */ - cdi->sanyo_slot = 3; - } - - - } + if (strcmp (drive->id->model, "V003S0DS") == 0 && + drive->id->fw_rev[4] == '1' && + drive->id->fw_rev[6] <= '2') { + /* Vertos 300. + Some versions of this drive like to talk BCD. */ + CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1; + } + + else if (strcmp (drive->id->model, "V006E0DS") == 0 && + drive->id->fw_rev[4] == '1' && + drive->id->fw_rev[6] <= '2') { + /* Vertos 600 ESD. */ + CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1; + } + else if (strcmp(drive->id->model, "NEC CD-ROM DRIVE:260") == 0 && + strncmp(drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */ + /* Old NEC260 (not R). + This drive was released before the 1.2 version + of the spec. */ + CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->nec260 = 1; + } + else if (strcmp(drive->id->model, "WEARNES CDD-120") == 0 && + strncmp(drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */ + /* Wearnes */ + CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1; + CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1; + } + /* Sanyo 3 CD changer uses a non-standard command + for CD changing */ + else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) || + (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) || + (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) { + /* uses CD in slot 0 when value is set to 3 */ + cdi->sanyo_slot = 3; + } #endif /* not STANDARD_ATAPI */ info->toc = NULL; @@ -3246,6 +3234,7 @@ printk("%s: ide_cdrom_cleanup failed to unregister device from the cdrom driver.\n", drive->name); kfree(info); drive->driver_data = NULL; + blk_queue_prep_rq(&drive->queue, NULL); del_gendisk(g); g->fops = ide_fops; return 0; @@ -3265,6 +3254,7 @@ .do_request = ide_do_rw_cdrom, .sense = ide_cdrom_dump_status, .error = ide_cdrom_error, + .abort = ide_cdrom_abort, .capacity = ide_cdrom_capacity, .attach = ide_cdrom_attach, .drives = LIST_HEAD_INIT(ide_cdrom_driver.drives), diff -urN linux-2.5.65-bk2/drivers/ide/ide-default.c linux-2.5.65-bk3/drivers/ide/ide-default.c --- linux-2.5.65-bk2/drivers/ide/ide-default.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/drivers/ide/ide-default.c Mon Mar 31 12:41:40 2003 @@ -0,0 +1,71 @@ +/* + * ide-default - Driver for unbound ide devices + * + * This provides a clean way to bind a device to default operations + * by having an actual driver class that rather than special casing + * "no driver" all over the IDE code + * + * Copyright (C) 2003, Red Hat + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define IDEDEFAULT_VERSION "0.9.newide" +/* + * Driver initialization. + */ + +static int idedefault_attach(ide_drive_t *drive); + +/* + * IDE subdriver functions, registered with ide.c + * + * idedefault *must* support DMA because it will be + * attached before the other drivers are loaded and + * we don't want to lose the DMA status at probe + * time. + */ + +ide_driver_t idedefault_driver = { + .name = "ide-default", + .version = IDEDEFAULT_VERSION, + .attach = idedefault_attach, + .supports_dma = 1, + .drives = LIST_HEAD_INIT(idedefault_driver.drives) +}; + +static int idedefault_attach (ide_drive_t *drive) +{ + if (ide_register_subdriver(drive, + &idedefault_driver, IDE_SUBDRIVER_VERSION)) { + printk(KERN_ERR "ide-default: %s: Failed to register the " + "driver with ide.c\n", drive->name); + return 1; + } + return 0; +} + +MODULE_DESCRIPTION("IDE Default Driver"); + +MODULE_LICENSE("GPL"); diff -urN linux-2.5.65-bk2/drivers/ide/ide-disk.c linux-2.5.65-bk3/drivers/ide/ide-disk.c --- linux-2.5.65-bk2/drivers/ide/ide-disk.c Mon Mar 17 13:44:04 2003 +++ linux-2.5.65-bk3/drivers/ide/ide-disk.c Mon Mar 31 12:41:40 2003 @@ -1,11 +1,10 @@ /* - * linux/drivers/ide/ide-disk.c Version 1.16 April 7, 2002 + * linux/drivers/ide/ide-disk.c Version 1.18 Mar 05, 2003 * + * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) * Copyright (C) 1998-2002 Linux ATA Developemt * Andre Hedrick - * - * - * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) + * Copyright (C) 2003 Red Hat */ /* @@ -42,7 +41,7 @@ * fix wcache setup. */ -#define IDEDISK_VERSION "1.17" +#define IDEDISK_VERSION "1.18" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -154,8 +153,6 @@ return DRIVER(drive)->error(drive, "read_intr", stat); } /* no data yet, so wait for another interrupt */ - if (HWGROUP(drive)->handler != NULL) - BUG(); ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); return ide_started; } @@ -189,8 +186,6 @@ if (i > 0) { if (msect) goto read_next; - if (HWGROUP(drive)->handler != NULL) - BUG(); ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); return ide_started; } @@ -230,8 +225,6 @@ char *to = ide_map_buffer(rq, &flags); taskfile_output_data(drive, to, SECTOR_WORDS); ide_unmap_buffer(rq, to, &flags); - if (HWGROUP(drive)->handler != NULL) - BUG(); ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); return ide_started; } @@ -332,8 +325,6 @@ if (rq->nr_sectors) { if (ide_multwrite(drive, drive->mult_count)) return ide_stopped; - if (HWGROUP(drive)->handler != NULL) - BUG(); ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); return ide_started; } @@ -550,8 +541,6 @@ * MAJOR DATA INTEGRITY BUG !!! only if we error */ hwgroup->wrq = *rq; /* scratchpad */ - if (HWGROUP(drive)->handler != NULL) - BUG(); ide_set_handler(drive, &multwrite_intr, WAIT_CMD, NULL); if (ide_multwrite(drive, drive->mult_count)) { unsigned long flags; @@ -564,8 +553,6 @@ } else { unsigned long flags; char *to = ide_map_buffer(rq, &flags); - if (HWGROUP(drive)->handler != NULL) - BUG(); ide_set_handler(drive, &write_intr, WAIT_CMD, NULL); taskfile_output_data(drive, to, SECTOR_WORDS); ide_unmap_buffer(rq, to, &flags); @@ -941,6 +928,26 @@ return ide_stopped; } +ide_startstop_t idedisk_abort(ide_drive_t *drive, const char *msg) +{ + ide_hwif_t *hwif; + struct request *rq; + + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) + return ide_stopped; + + hwif = HWIF(drive); + + if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK | REQ_DRIVE_TASKFILE)) { + rq->errors = 1; + ide_end_drive_cmd(drive, BUSY_STAT, 0); + return ide_stopped; + } + + DRIVER(drive)->end_request(drive, 0, 0); + return ide_stopped; +} + /* * Queries for true maximum capacity of the drive. * Returns maximum LBA address (> 0) of the drive, 0 if failed. @@ -1073,7 +1080,7 @@ { int flag = (drive->id->cfs_enable_1 & 0x0400) ? 1 : 0; if (flag) - printk("%s: host protected area => %d\n", drive->name, flag); + printk(KERN_INFO "%s: host protected area => %d\n", drive->name, flag); return flag; } @@ -1201,7 +1208,7 @@ } } else if (s->b.set_multmode) { s->b.set_multmode = 0; - if (drive->id && drive->mult_req > drive->id->max_multsect) + if (drive->mult_req > drive->id->max_multsect) drive->mult_req = drive->id->max_multsect; if (!IS_PDC4030_DRIVE) { ide_task_t args; @@ -1286,7 +1293,7 @@ char *out = page; int len; - if (drive->id) + if (drive->id_read) len = sprintf(out,"%i\n", drive->id->buf_size / 2); else len = sprintf(out,"(none)\n"); @@ -1549,7 +1556,7 @@ idedisk_add_settings(drive); - if (id == NULL) + if (drive->id_read == 0) return; /* @@ -1666,6 +1673,7 @@ .do_request = do_rw_disk, .sense = idedisk_dump_status, .error = idedisk_error, + .abort = idedisk_abort, .pre_reset = idedisk_pre_reset, .capacity = idedisk_capacity, .special = idedisk_special, diff -urN linux-2.5.65-bk2/drivers/ide/ide-dma.c linux-2.5.65-bk3/drivers/ide/ide-dma.c --- linux-2.5.65-bk2/drivers/ide/ide-dma.c Mon Mar 17 13:44:06 2003 +++ linux-2.5.65-bk3/drivers/ide/ide-dma.c Mon Mar 31 12:41:40 2003 @@ -75,7 +75,6 @@ */ #include -#define __NO_VERSION__ #include #include #include @@ -419,7 +418,7 @@ struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); - if (id && (id->capability & 1) && hwif->autodma) { + if ((id->capability & 1) && hwif->autodma) { /* Consult the list of known "bad" drives */ if (hwif->ide_dma_bad_drive(drive)) return hwif->ide_dma_off(drive); @@ -977,14 +976,12 @@ { printk(KERN_INFO " %s: MMIO-DMA at 0x%08lx-0x%08lx", hwif->name, base, base + ports - 1); - if (check_mem_region(base, ports)) { - printk(" -- Error, MMIO ports already in use.\n"); - return 1; - } - request_mem_region(base, ports, hwif->name); + if (!request_mem_region(base, ports, hwif->name)) + goto fail; hwif->dma_base = base; if ((hwif->cds->extra) && (hwif->channel == 0)) { - request_region(base+16, hwif->cds->extra, hwif->cds->name); + if (!request_region(base+16, hwif->cds->extra, hwif->cds->name)) + goto release_mem; hwif->dma_extra = hwif->cds->extra; } @@ -993,10 +990,18 @@ else hwif->dma_master = base; if (hwif->dma_base2) { - if (!check_mem_region(hwif->dma_base2, ports)) - request_mem_region(hwif->dma_base2, ports, hwif->name); + if (!request_mem_region(hwif->dma_base2, ports, hwif->name)) + goto release_io; } return 0; + +release_mem: + release_mem_region(base, ports); +release_io: + release_region(base+16, hwif->cds->extra); +fail: + printk(" -- Error, MMIO ports already in use.\n"); + return 1; } int ide_iomio_dma (ide_hwif_t *hwif, unsigned long base, unsigned int ports) diff -urN linux-2.5.65-bk2/drivers/ide/ide-geometry.c linux-2.5.65-bk3/drivers/ide/ide-geometry.c --- linux-2.5.65-bk2/drivers/ide/ide-geometry.c Mon Mar 17 13:44:41 2003 +++ linux-2.5.65-bk3/drivers/ide/ide-geometry.c Mon Mar 31 12:41:40 2003 @@ -129,7 +129,7 @@ set_capacity(drive->disk, current_capacity(drive)); if (ret) - printk(KERN_INFO "%s%s [%d/%d/%d]", msg, msg1, + printk("%s%s [%d/%d/%d]", msg, msg1, drive->bios_cyl, drive->bios_head, drive->bios_sect); return ret; } diff -urN linux-2.5.65-bk2/drivers/ide/ide-io.c linux-2.5.65-bk3/drivers/ide/ide-io.c --- linux-2.5.65-bk2/drivers/ide/ide-io.c Mon Mar 17 13:44:41 2003 +++ linux-2.5.65-bk3/drivers/ide/ide-io.c Mon Mar 31 12:41:40 2003 @@ -330,10 +330,7 @@ hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); } if (rq->errors >= ERROR_MAX) { - if (drive->driver != NULL) - DRIVER(drive)->end_request(drive, 0, 0); - else - ide_end_request(drive, 0, 0); + DRIVER(drive)->end_request(drive, 0, 0); } else { if ((rq->errors & ERROR_RESET) == ERROR_RESET) { ++rq->errors; @@ -349,6 +346,49 @@ EXPORT_SYMBOL(ide_error); /** + * ide_abort - abort pending IDE operatins + * @drive: drive the error occurred on + * @msg: message to report + * + * ide_abort kills and cleans up when we are about to do a + * host initiated reset on active commands. Longer term we + * want handlers to have sensible abort handling themselves + * + * This differs fundamentally from ide_error because in + * this case the command is doing just fine when we + * blow it away. + */ + +ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg) +{ + ide_hwif_t *hwif; + struct request *rq; + + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) + return ide_stopped; + + hwif = HWIF(drive); + /* retry only "normal" I/O: */ + if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) { + rq->errors = 1; + ide_end_drive_cmd(drive, BUSY_STAT, 0); + return ide_stopped; + } + if (rq->flags & REQ_DRIVE_TASKFILE) { + rq->errors = 1; + ide_end_drive_cmd(drive, BUSY_STAT, 0); +// ide_end_taskfile(drive, BUSY_STAT, 0); + return ide_stopped; + } + + rq->errors |= ERROR_RESET; + DRIVER(drive)->end_request(drive, 0, 0); + return ide_stopped; +} + +EXPORT_SYMBOL(ide_abort); + +/** * ide_cmd - issue a simple drive command * @drive: drive the command is for * @cmd: command byte @@ -399,7 +439,7 @@ udelay(100); } - if (!OK_STAT(stat, READY_STAT, BAD_STAT)) + if (!OK_STAT(stat, READY_STAT, BAD_STAT) && DRIVER(drive) != NULL) return DRIVER(drive)->error(drive, "drive_cmd", stat); /* calls ide_end_drive_cmd */ ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG)); @@ -428,13 +468,10 @@ s->b.set_tune = 0; if (HWIF(drive)->tuneproc != NULL) HWIF(drive)->tuneproc(drive, drive->tune_req); - } else if (drive->driver != NULL) { - return DRIVER(drive)->special(drive); - } else if (s->all) { - printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, s->all); - s->all = 0; + return ide_stopped; } - return ide_stopped; + else + return DRIVER(drive)->special(drive); } EXPORT_SYMBOL(do_special); @@ -589,42 +626,17 @@ return execute_drive_cmd(drive, rq); else if (rq->flags & REQ_DRIVE_TASKFILE) return execute_drive_cmd(drive, rq); - - if (drive->driver != NULL) { - return (DRIVER(drive)->do_request(drive, rq, block)); - } - printk(KERN_ERR "%s: media type %d not supported\n", drive->name, drive->media); - goto kill_rq; + return (DRIVER(drive)->do_request(drive, rq, block)); } return do_special(drive); kill_rq: - if (drive->driver != NULL) - DRIVER(drive)->end_request(drive, 0, 0); - else - ide_end_request(drive, 0, 0); + DRIVER(drive)->end_request(drive, 0, 0); return ide_stopped; } EXPORT_SYMBOL(start_request); /** - * restart_request - reissue an IDE request - * @drive: drive for request - * @rq: request to reissue - * - * Reissue a request. See start_request for details and for - * FIXME - */ - -int restart_request (ide_drive_t *drive, struct request *rq) -{ - (void) start_request(drive, rq); - return 0; -} - -EXPORT_SYMBOL(restart_request); - -/** * ide_stall_queue - pause an IDE device * @drive: drive to stall * @timeout: time to stall for (jiffies) @@ -742,8 +754,8 @@ /* for atari only: POSSIBLY BROKEN HERE(?) */ ide_get_lock(ide_intr, hwgroup); - /* necessary paranoia: ensure IRQs are masked on local CPU */ - local_irq_disable(); + /* caller must own ide_lock */ + BUG_ON(!irqs_disabled()); while (!hwgroup->busy) { hwgroup->busy = 1; diff -urN linux-2.5.65-bk2/drivers/ide/ide-iops.c linux-2.5.65-bk3/drivers/ide/ide-iops.c --- linux-2.5.65-bk2/drivers/ide/ide-iops.c Mon Mar 17 13:44:02 2003 +++ linux-2.5.65-bk3/drivers/ide/ide-iops.c Mon Mar 31 12:41:40 2003 @@ -1,13 +1,12 @@ /* - * linux/drivers/ide/ide-iops.c Version 0.33 April 11, 2002 + * linux/drivers/ide/ide-iops.c Version 0.37 Mar 05, 2003 * * Copyright (C) 2000-2002 Andre Hedrick - * + * Copyright (C) 2003 Red Hat * */ #include -#define __NO_VERSION__ #include #include #include @@ -63,6 +62,10 @@ { } +static void ide_unplugged_outbsync (ide_drive_t *drive, u8 addr, unsigned long port) +{ +} + static void ide_unplugged_outw (u16 val, unsigned long port) { } @@ -82,7 +85,7 @@ void unplugged_hwif_iops (ide_hwif_t *hwif) { hwif->OUTB = ide_unplugged_outb; - hwif->OUTBSYNC = ide_unplugged_outb; + hwif->OUTBSYNC = ide_unplugged_outbsync; hwif->OUTW = ide_unplugged_outw; hwif->OUTL = ide_unplugged_outl; hwif->OUTSW = ide_unplugged_outsw; @@ -130,6 +133,11 @@ outb(val, port); } +static void ide_outbsync (ide_drive_t *drive, u8 addr, unsigned long port) +{ + outb(addr, port); +} + static void ide_outw (u16 val, unsigned long port) { outw(val, port); @@ -153,7 +161,7 @@ void default_hwif_iops (ide_hwif_t *hwif) { hwif->OUTB = ide_outb; - hwif->OUTBSYNC = ide_outb; + hwif->OUTBSYNC = ide_outbsync; hwif->OUTW = ide_outw; hwif->OUTL = ide_outl; hwif->OUTSW = ide_outsw; @@ -201,6 +209,11 @@ writeb(value, port); } +static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long port) +{ + writeb(value, port); +} + static void ide_mm_outw (u16 value, unsigned long port) { writew(value, port); @@ -226,7 +239,7 @@ hwif->OUTB = ide_mm_outb; /* Most systems will need to override OUTBSYNC, alas however this one is controller specific! */ - hwif->OUTBSYNC = ide_mm_outb; + hwif->OUTBSYNC = ide_mm_outbsync; hwif->OUTW = ide_mm_outw; hwif->OUTL = ide_mm_outl; hwif->OUTSW = ide_mm_outsw; @@ -986,13 +999,11 @@ * * See also ide_execute_command */ -void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, +void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry) { - unsigned long flags; ide_hwgroup_t *hwgroup = HWGROUP(drive); - spin_lock_irqsave(&ide_lock, flags); if (hwgroup->handler != NULL) { printk(KERN_CRIT "%s: ide_set_handler: handler not null; " "old=%p, new=%p\n", @@ -1002,11 +1013,21 @@ hwgroup->expiry = expiry; hwgroup->timer.expires = jiffies + timeout; add_timer(&hwgroup->timer); +} + +EXPORT_SYMBOL(__ide_set_handler); + +void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, + unsigned int timeout, ide_expiry_t *expiry) +{ + unsigned long flags; + spin_lock_irqsave(&ide_lock, flags); + __ide_set_handler(drive, handler, timeout, expiry); spin_unlock_irqrestore(&ide_lock, flags); } EXPORT_SYMBOL(ide_set_handler); - + /** * ide_execute_command - execute an IDE command * @drive: IDE drive to issue the command against @@ -1035,7 +1056,7 @@ hwgroup->expiry = expiry; hwgroup->timer.expires = jiffies + timeout; add_timer(&hwgroup->timer); - hwif->OUTBSYNC(cmd, IDE_COMMAND_REG); + hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG); /* Drive takes 400nS to respond, we must avoid the IRQ being serviced before that. @@ -1050,7 +1071,7 @@ /* needed below */ -ide_startstop_t do_reset1 (ide_drive_t *, int); +static ide_startstop_t do_reset1 (ide_drive_t *, int); /* * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms @@ -1167,8 +1188,7 @@ void pre_reset (ide_drive_t *drive) { - if (drive->driver != NULL) - DRIVER(drive)->pre_reset(drive); + DRIVER(drive)->pre_reset(drive); if (!drive->keep_settings) { if (drive->using_dma) { @@ -1202,14 +1222,20 @@ * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, * we set a timer to poll at 50ms intervals. */ -ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) +static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) { unsigned int unit; unsigned long flags; - ide_hwif_t *hwif = HWIF(drive); - ide_hwgroup_t *hwgroup = HWGROUP(drive); + ide_hwif_t *hwif; + ide_hwgroup_t *hwgroup; + + spin_lock_irqsave(&ide_lock, flags); + hwif = HWIF(drive); + hwgroup = HWGROUP(drive); - local_irq_save(flags); + /* We must not reset with running handlers */ + if(hwgroup->handler != NULL) + BUG(); /* For an ATAPI device, first try an ATAPI SRST. */ if (drive->media != ide_disk && !do_not_try_atapi) { @@ -1218,10 +1244,8 @@ udelay (20); hwif->OUTB(WIN_SRST, IDE_COMMAND_REG); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); - local_irq_restore(flags); + __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); + spin_unlock_irqrestore(&ide_lock, flags); return ide_started; } @@ -1234,20 +1258,10 @@ #if OK_TO_RESET_CONTROLLER if (!IDE_CONTROL_REG) { - local_irq_restore(flags); + spin_unlock_irqrestore(&ide_lock, flags); return ide_stopped; } -# if 0 - { - u8 control = hwif->INB(IDE_CONTROL_REG); - control |= 0x04; - hwif->OUTB(control,IDE_CONTROL_REG); - udelay(30); - control &= 0xFB; - hwif->OUTB(control, IDE_CONTROL_REG); - } -# else /* * Note that we also set nIEN while resetting the device, * to mask unwanted interrupts from the interface during the reset. @@ -1257,23 +1271,21 @@ * recover from reset very quickly, saving us the first 50ms wait time. */ /* set SRST and nIEN */ - hwif->OUTB(drive->ctl|6,IDE_CONTROL_REG); + hwif->OUTBSYNC(drive, drive->ctl|6,IDE_CONTROL_REG); /* more than enough time */ udelay(10); if (drive->quirk_list == 2) { /* clear SRST and nIEN */ - hwif->OUTB(drive->ctl, IDE_CONTROL_REG); + hwif->OUTBSYNC(drive, drive->ctl, IDE_CONTROL_REG); } else { /* clear SRST, leave nIEN */ - hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG); + hwif->OUTBSYNC(drive, drive->ctl|2, IDE_CONTROL_REG); } /* more than enough time */ udelay(10); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); -# endif + __ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); + /* * Some weird controller like resetting themselves to a strange * state when the disks are reset this way. At least, the Winbond @@ -1281,71 +1293,22 @@ */ if (hwif->resetproc != NULL) { hwif->resetproc(drive); - -# if 0 - if (drive->failures) { - local_irq_restore(flags); - return ide_stopped; - } -# endif } - + #endif /* OK_TO_RESET_CONTROLLER */ - local_irq_restore(flags); + spin_unlock_irqrestore(&ide_lock, flags); return ide_started; } -#if 0 /* * ide_do_reset() is the entry point to the drive/interface reset code. */ + ide_startstop_t ide_do_reset (ide_drive_t *drive) { return do_reset1(drive, 0); } -#else -/* - * ide_do_reset() is the entry point to the drive/interface reset code. - */ -ide_startstop_t ide_do_reset (ide_drive_t *drive) -{ - ide_startstop_t start_stop = ide_started; -# if 0 - u8 tmp_dma = drive->using_dma; - u8 cspeed = drive->current_speed; - u8 unmask = drive->unmask; -# endif - - if (HWGROUP(drive)->handler != NULL) { - unsigned long flags; - spin_lock_irqsave(&ide_lock, flags); - HWGROUP(drive)->handler = NULL; - del_timer(&HWGROUP(drive)->timer); - spin_unlock_irqrestore(&ide_lock, flags); - } - - start_stop = do_reset1(drive, 0); -# if 0 - /* - * check for suspend-spindown flag, - * to attempt a restart or spinup of device. - */ - if (drive->suspend_reset) { - /* - * APM WAKE UP todo !! - * int nogoodpower = 1; - * while(nogoodpower) { - * check_power1() or check_power2() - * nogoodpower = 0; - * } - * HWIF(drive)->multiproc(drive); - */ -# endif - - return start_stop; -} -#endif EXPORT_SYMBOL(ide_do_reset); diff -urN linux-2.5.65-bk2/drivers/ide/ide-lib.c linux-2.5.65-bk3/drivers/ide/ide-lib.c --- linux-2.5.65-bk2/drivers/ide/ide-lib.c Mon Mar 17 13:44:46 2003 +++ linux-2.5.65-bk3/drivers/ide/ide-lib.c Mon Mar 31 12:41:40 2003 @@ -1,5 +1,4 @@ #include -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/drivers/ide/ide-probe.c linux-2.5.65-bk3/drivers/ide/ide-probe.c --- linux-2.5.65-bk2/drivers/ide/ide-probe.c Mon Mar 17 13:44:08 2003 +++ linux-2.5.65-bk3/drivers/ide/ide-probe.c Mon Mar 31 12:41:40 2003 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/ide-probe.c Version 1.10 Feb 11, 2003 + * linux/drivers/ide/ide-probe.c Version 1.11 Mar 05, 2003 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -65,23 +65,14 @@ * and make drive properties unconditional outside of this file */ -static int generic_id(ide_drive_t *drive) +static void generic_id(ide_drive_t *drive) { - drive->id = kmalloc(SECTOR_WORDS *4, GFP_KERNEL); - if(drive->id == NULL) - { - printk(KERN_ERR "ide: out of memory for id data.\n"); - return -ENOMEM; - } - memset(drive->id, 0, SECTOR_WORDS * 4); drive->id->cyls = drive->cyl; drive->id->heads = drive->head; drive->id->sectors = drive->sect; drive->id->cur_cyls = drive->cyl; drive->id->cur_heads = drive->head; drive->id->cur_sectors = drive->sect; - strcpy(drive->id->model, "UNKNOWN"); - return 0; } /** @@ -107,7 +98,7 @@ { struct hd_driveid *id = drive->id; - if (drive->removable && id != NULL) { + if (drive->removable) { if (id->config == 0x848a) return 1; /* CompactFlash */ if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */ || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */ @@ -138,16 +129,11 @@ int bswap = 1; struct hd_driveid *id; - /* called with interrupts disabled! */ - id = drive->id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); - if (!id) { - printk(KERN_WARNING "(ide-probe::do_identify) " - "Out of memory.\n"); - goto err_kmalloc; - } + id = drive->id; /* read 512 bytes of id info */ hwif->ata_input_data(drive, id, SECTOR_WORDS); + drive->id_read = 1; local_irq_enable(); ide_fix_driveid(id); @@ -290,7 +276,6 @@ err_misc: kfree(id); -err_kmalloc: drive->present = 0; return; } @@ -592,6 +577,25 @@ static inline u8 probe_for_drive (ide_drive_t *drive) { + /* + * In order to keep things simple we have an id + * block for all drives at all times. If the device + * is pre ATA or refuses ATA/ATAPI identify we + * will add faked data to this. + * + * Also note that 0 everywhere means "can't do X" + */ + + drive->id = kmalloc(SECTOR_WORDS *4, GFP_KERNEL); + drive->id_read = 0; + if(drive->id == NULL) + { + printk(KERN_ERR "ide: out of memory for id data.\n"); + return 0; + } + memset(drive->id, 0, SECTOR_WORDS * 4); + strcpy(drive->id->model, "UNKNOWN"); + /* skip probing? */ if (!drive->noprobe) { @@ -600,14 +604,14 @@ /* look for ATAPI device */ (void) do_probe(drive, WIN_PIDENTIFY); } - if (drive->id && strstr(drive->id->model, "E X A B Y T E N E S T")) + if (strstr(drive->id->model, "E X A B Y T E N E S T")) enable_nest(drive); if (!drive->present) /* drive not found */ return 0; /* identification failed? */ - if (drive->id == NULL) { + if (!drive->id_read) { if (drive->media == ide_disk) { printk(KERN_INFO "%s: non-IDE drive, CHS=%d/%d/%d\n", drive->name, drive->cyl, @@ -616,6 +620,7 @@ printk(KERN_INFO "%s: ATAPI cdrom (?)\n", drive->name); } else { /* nuke it */ + printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name); drive->present = 0; } } @@ -623,9 +628,9 @@ } if(!drive->present) return 0; - if(drive->id == NULL) - if(generic_id(drive) < 0) - drive->present = 0; + /* The drive wasn't being helpful. Add generic info only */ + if(!drive->id_read) + generic_id(drive); return drive->present; } @@ -945,6 +950,9 @@ u16 unit = 0; for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; + /* For now don't attach absent drives, we may + want them on default or a new "empty" class + for hotplug reprobing ? */ if (drive->present) { ata_attach(drive); } @@ -990,18 +998,23 @@ static void ide_init_queue(ide_drive_t *drive) { request_queue_t *q = &drive->queue; - int max_sectors; + int max_sectors = 256; + /* + * Our default set up assumes the normal IDE case, + * that is 64K segmenting, standard PRD setup + * and LBA28. Some drivers then impose their own + * limits and LBA48 we could raise it but as yet + * do not. + */ + q->queuedata = HWGROUP(drive); blk_init_queue(q, do_ide_request, &ide_lock); drive->queue_setup = 1; blk_queue_segment_boundary(q, 0xffff); -#ifdef CONFIG_BLK_DEV_PDC4030 - max_sectors = 127; -#else - max_sectors = 255; -#endif + if (HWIF(drive)->rqsize) + max_sectors = HWIF(drive)->rqsize; blk_queue_max_sectors(q, max_sectors); /* IDE DMA can do PRD_ENTRIES number of segments. */ @@ -1009,7 +1022,13 @@ /* This is a driver limit and could be eliminated. */ blk_queue_max_phys_segments(q, PRD_ENTRIES); +} +/* + * Setup the drive for request handling. + */ +static void ide_init_drive(ide_drive_t *drive) +{ ide_toggle_bounce(drive, 1); #ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT @@ -1032,16 +1051,14 @@ */ static int init_irq (ide_hwif_t *hwif) { - unsigned long flags; unsigned int index; - ide_hwgroup_t *hwgroup, *new_hwgroup; + ide_hwgroup_t *hwgroup; ide_hwif_t *match = NULL; - /* Allocate the buffer and potentially sleep first */ - new_hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL); - - spin_lock_irqsave(&ide_lock, flags); + BUG_ON(in_interrupt()); + BUG_ON(irqs_disabled()); + down(&ide_cfg_sem); hwif->hwgroup = NULL; #if MAX_HWIFS > 1 /* @@ -1073,14 +1090,28 @@ */ if (match) { hwgroup = match->hwgroup; - if(new_hwgroup) - kfree(new_hwgroup); + hwif->hwgroup = hwgroup; + /* + * Link us into the hwgroup. + * This must be done early, do ensure that unexpected_intr + * can find the hwif and prevent irq storms. + * No drives are attached to the new hwif, choose_drive + * can't do anything stupid (yet). + * Add ourself as the 2nd entry to the hwgroup->hwif + * linked list, the first entry is the hwif that owns + * hwgroup->handler - do not change that. + */ + spin_lock_irq(&ide_lock); + hwif->next = hwgroup->hwif->next; + hwgroup->hwif->next = hwif; + spin_unlock_irq(&ide_lock); } else { - hwgroup = new_hwgroup; - if (!hwgroup) { - spin_unlock_irqrestore(&ide_lock, flags); - return 1; - } + hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL); + if (!hwgroup) + goto out_up; + + hwif->hwgroup = hwgroup; + memset(hwgroup, 0, sizeof(ide_hwgroup_t)); hwgroup->hwif = hwif->next = hwif; hwgroup->rq = NULL; @@ -1112,44 +1143,35 @@ /* clear nIEN */ hwif->OUTB(0x08, hwif->io_ports[IDE_CONTROL_OFFSET]); - if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) { - if (!match) - kfree(hwgroup); - spin_unlock_irqrestore(&ide_lock, flags); - return 1; - } + if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) + goto out_unlink; } /* - * Everything is okay, so link us into the hwgroup + * Link any new drives into the hwgroup, allocate + * the block device queue and initialize the drive. + * Note that ide_init_drive sends commands to the new + * drive. */ - hwif->hwgroup = hwgroup; - hwif->next = hwgroup->hwif->next; - hwgroup->hwif->next = hwif; - for (index = 0; index < MAX_DRIVES; ++index) { ide_drive_t *drive = &hwif->drives[index]; if (!drive->present) continue; - if (!hwgroup->drive) - hwgroup->drive = drive; - drive->next = hwgroup->drive->next; - hwgroup->drive->next = drive; - spin_unlock_irqrestore(&ide_lock, flags); ide_init_queue(drive); - spin_lock_irqsave(&ide_lock, flags); - } - - if (!hwgroup->hwif) { - hwgroup->hwif = HWIF(hwgroup->drive); -#ifdef DEBUG - printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name); -#endif + spin_lock_irq(&ide_lock); + if (!hwgroup->drive) { + /* first drive for hwgroup. */ + drive->next = drive; + hwgroup->drive = drive; + hwgroup->hwif = HWIF(hwgroup->drive); + } else { + drive->next = hwgroup->drive->next; + hwgroup->drive->next = drive; + } + spin_unlock_irq(&ide_lock); + ide_init_drive(drive); } - /* all CPUs; safe now that hwif->hwgroup is set up */ - spin_unlock_irqrestore(&ide_lock, flags); - #if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__) printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, hwif->io_ports[IDE_DATA_OFFSET], @@ -1168,6 +1190,30 @@ printk(" (%sed with %s)", hwif->sharing_irq ? "shar" : "serializ", match->name); printk("\n"); + up(&ide_cfg_sem); + return 0; +out_unlink: + spin_lock_irq(&ide_lock); + if (hwif->next == hwif) { + BUG_ON(match); + BUG_ON(hwgroup->hwif != hwif); + kfree(hwgroup); + } else { + ide_hwif_t *g; + g = hwgroup->hwif; + while (g->next != hwif) + g = g->next; + g->next = hwif->next; + if (hwgroup->hwif == hwif) { + /* Impossible. */ + printk(KERN_ERR "Duh. Uninitialized hwif listed as active hwif.\n"); + hwgroup->hwif = g; + } + BUG_ON(hwgroup->hwif == hwif); + } + spin_unlock_irq(&ide_lock); +out_up: + up(&ide_cfg_sem); return 0; } @@ -1340,6 +1386,7 @@ void export_ide_init_queue (ide_drive_t *drive) { ide_init_queue(drive); + ide_init_drive(drive); } EXPORT_SYMBOL(export_ide_init_queue); @@ -1384,7 +1431,8 @@ if (!hwif->present) continue; for (unit = 0; unit < MAX_DRIVES; ++unit) - ata_attach(&hwif->drives[unit]); + if (hwif->drives[unit].present) + ata_attach(&hwif->drives[unit]); } } if (!ide_probe) diff -urN linux-2.5.65-bk2/drivers/ide/ide-proc.c linux-2.5.65-bk3/drivers/ide/ide-proc.c --- linux-2.5.65-bk2/drivers/ide/ide-proc.c Mon Mar 17 13:44:07 2003 +++ linux-2.5.65-bk3/drivers/ide/ide-proc.c Mon Mar 31 12:41:40 2003 @@ -1,7 +1,8 @@ /* - * linux/drivers/ide/ide-proc.c Version 1.03 January 2, 1998 + * linux/drivers/ide/ide-proc.c Version 1.05 Mar 05, 2003 * * Copyright (C) 1997-1998 Mark Lord + * Copyright (C) 2003 Red Hat */ /* @@ -57,7 +58,6 @@ */ #include -#define __NO_VERSION__ #include #include @@ -365,6 +365,7 @@ case ide_cy82c693: name = "cy82c693"; break; case ide_4drives: name = "4drives"; break; case ide_pmac: name = "mac-io"; break; + case ide_pc9800: name = "pc9800"; break; default: name = "(unknown)"; break; } len = sprintf(page, "%s\n", name); @@ -568,14 +569,10 @@ (char *page, char **start, off_t off, int count, int *eof, void *data) { ide_drive_t *drive = (ide_drive_t *) data; - ide_driver_t *driver = (ide_driver_t *) drive->driver; int len; - if (!driver) - len = sprintf(page, "(none)\n"); - else - len = sprintf(page,"%llu\n", - (long long) ((ide_driver_t *)drive->driver)->capacity(drive)); + len = sprintf(page,"%llu\n", + (long long) (DRIVER(drive)->capacity(drive))); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } @@ -620,10 +617,7 @@ ide_driver_t *driver = drive->driver; int len; - if (!driver) - len = sprintf(page, "(none)\n"); - else - len = sprintf(page, "%s version %s\n", + len = sprintf(page, "%s version %s\n", driver->name, driver->version); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } @@ -775,8 +769,7 @@ ide_driver_t *driver = drive->driver; if (drive->proc) { - if (driver) - ide_remove_proc_entries(drive->proc, driver->proc); + ide_remove_proc_entries(drive->proc, driver->proc); ide_remove_proc_entries(drive->proc, generic_drive_entries); remove_proc_entry(drive->name, proc_ide_root); remove_proc_entry(drive->name, hwif->proc); diff -urN linux-2.5.65-bk2/drivers/ide/ide-tape.c linux-2.5.65-bk3/drivers/ide/ide-tape.c --- linux-2.5.65-bk2/drivers/ide/ide-tape.c Mon Mar 17 13:44:02 2003 +++ linux-2.5.65-bk3/drivers/ide/ide-tape.c Mon Mar 31 12:41:40 2003 @@ -422,7 +422,7 @@ * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device. */ -#define IDETAPE_VERSION "1.17b" +#define IDETAPE_VERSION "1.17b-ac1" #include #include @@ -2128,8 +2128,6 @@ if (temp > pc->buffer_size) { printk(KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n"); idetape_discard_data(drive, bcount.all); - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); return ide_started; } @@ -2156,8 +2154,6 @@ if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all); #endif - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* And set the interrupt handler again */ return ide_started; } @@ -2235,8 +2231,6 @@ return ide_do_reset(drive); } tape->cmd_start_time = jiffies; - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); /* Set the interrupt routine */ ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); #ifdef CONFIG_BLK_DEV_IDEDMA @@ -2325,8 +2319,6 @@ if (dma_ok) /* Will begin DMA later */ set_bit(PC_DMA_IN_PROGRESS, &pc->flags); if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) { - if (HWGROUP(drive)->handler != NULL) /* paranoia check */ - BUG(); ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL); OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG); return ide_started; @@ -5605,15 +5597,16 @@ * * 0 If this tape driver is not currently supported by us. */ -static int idetape_identify_device (ide_drive_t *drive,struct hd_driveid *id) +static int idetape_identify_device (ide_drive_t *drive) { struct idetape_id_gcw gcw; + struct hd_driveid *id = drive->id; #if IDETAPE_DEBUG_INFO unsigned short mask,i; #endif /* IDETAPE_DEBUG_INFO */ - if (!id) - return 0; + if (drive->id_read == 0) + return 1; *((unsigned short *) &gcw) = id->config; @@ -6287,7 +6280,7 @@ goto failed; if (drive->media != ide_tape) goto failed; - if (!idetape_identify_device (drive, drive->id)) { + if (!idetape_identify_device (drive)) { printk(KERN_ERR "ide-tape: %s: not supported by this version of ide-tape\n", drive->name); goto failed; } diff -urN linux-2.5.65-bk2/drivers/ide/ide-taskfile.c linux-2.5.65-bk3/drivers/ide/ide-taskfile.c --- linux-2.5.65-bk2/drivers/ide/ide-taskfile.c Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/drivers/ide/ide-taskfile.c Mon Mar 31 12:41:40 2003 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/ide-taskfile.c Version 0.33 April 11, 2002 + * linux/drivers/ide/ide-taskfile.c Version 0.38 March 05, 2003 * * Copyright (C) 2000-2002 Michael Cornwell * Copyright (C) 2000-2002 Andre Hedrick @@ -27,7 +27,6 @@ */ #include -#define __NO_VERSION__ #include #include #include @@ -642,7 +641,7 @@ * NOTE: could rewind beyond beginning :-/ */ } else { - printk("%s: MULTI-READ assume all data " \ + printk(KERN_ERR "%s: MULTI-READ assume all data " \ "transfered is bad status=0x%02x\n", drive->name, stat); } @@ -810,11 +809,6 @@ rq->errors = 0; return ide_started; #else /* ! ALTERNATE_STATE_DIAGRAM_MULTI_OUT */ - -#if 0 - if (wait_for_ready(drive, 100)) - IDE_DEBUG(__LINE__); //BUG(); -#else if (!(drive_is_ready(drive))) { int i; for (i=0; i<100; i++) { @@ -822,7 +816,7 @@ break; } } -#endif + /* * WARNING :: if the drive as not acked good status we may not * move the DATA-TRANSFER T-Bar as BSY != 0. @@ -864,7 +858,7 @@ * NOTE: could rewind beyond beginning :-/ */ } else { - printk("%s: MULTI-WRITE assume all data " \ + printk(KERN_ERR "%s: MULTI-WRITE assume all data " \ "transfered is bad status=0x%02x\n", drive->name, stat); } @@ -1497,7 +1491,7 @@ case TASKFILE_MULTI_OUT: if (!drive->mult_count) { /* (hs): give up if multcount is not set */ - printk("%s: %s Multimode Write " \ + printk(KERN_ERR "%s: %s Multimode Write " \ "multcount is not set\n", drive->name, __FUNCTION__); err = -EPERM; @@ -1525,7 +1519,7 @@ case TASKFILE_MULTI_IN: if (!drive->mult_count) { /* (hs): give up if multcount is not set */ - printk("%s: %s Multimode Read failure " \ + printk(KERN_ERR "%s: %s Multimode Read failure " \ "multcount is not set\n", drive->name, __FUNCTION__); err = -EPERM; diff -urN linux-2.5.65-bk2/drivers/ide/ide.c linux-2.5.65-bk3/drivers/ide/ide.c --- linux-2.5.65-bk2/drivers/ide/ide.c Mon Mar 17 13:43:50 2003 +++ linux-2.5.65-bk3/drivers/ide/ide.c Mon Mar 31 12:41:40 2003 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/ide.c Version 7.00alpha1 August 19 2002 + * linux/drivers/ide/ide.c Version 7.00beta2 Mar 05 2003 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -177,6 +177,7 @@ static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ static int initializing; /* set while initializing built-in drivers */ +DECLARE_MUTEX(ide_cfg_sem); spinlock_t ide_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED; static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ @@ -214,6 +215,8 @@ EXPORT_SYMBOL(idetape); EXPORT_SYMBOL(idescsi); +extern ide_driver_t idedefault_driver; +static void setup_driver_defaults (ide_drive_t *drive); /* * Do not even *think* about calling this! @@ -271,6 +274,8 @@ drive->max_failures = IDE_DEFAULT_MAX_FAILURES; drive->using_dma = 0; drive->is_flash = 0; + drive->driver = &idedefault_driver; + setup_driver_defaults(drive); drive->vdma = 0; INIT_LIST_HEAD(&drive->list); } @@ -349,9 +354,7 @@ { if (!drive->present) return 0; - if (drive->driver != NULL) - return DRIVER(drive)->capacity(drive); - return 0; + return DRIVER(drive)->capacity(drive); } EXPORT_SYMBOL(current_capacity); @@ -580,17 +583,19 @@ void ide_unregister (unsigned int index) { - ide_drive_t *drive, *d; + ide_drive_t *drive; ide_hwif_t *hwif, *g; ide_hwgroup_t *hwgroup; int irq_count = 0, unit, i; - unsigned long flags; ide_hwif_t old_hwif; if (index >= MAX_HWIFS) BUG(); - spin_lock_irqsave(&ide_lock, flags); + BUG_ON(in_interrupt()); + BUG_ON(irqs_disabled()); + down(&ide_cfg_sem); + spin_lock_irq(&ide_lock); hwif = &ide_hwifs[index]; if (!hwif->present) goto abort; @@ -600,25 +605,23 @@ continue; if (drive->usage) goto abort; - if (drive->driver != NULL && DRIVER(drive)->shutdown(drive)) + if (DRIVER(drive)->shutdown(drive)) goto abort; } hwif->present = 0; - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irq(&ide_lock); for (unit = 0; unit < MAX_DRIVES; ++unit) { drive = &hwif->drives[unit]; if (!drive->present) continue; - if (drive->driver != NULL) - DRIVER(drive)->cleanup(drive); + DRIVER(drive)->cleanup(drive); } #ifdef CONFIG_PROC_FS destroy_proc_ide_drives(hwif); #endif - spin_lock_irqsave(&ide_lock, flags); hwgroup = hwif->hwgroup; /* @@ -633,6 +636,7 @@ if (irq_count == 1) free_irq(hwif->irq, hwgroup); + spin_lock_irq(&ide_lock); /* * Note that we only release the standard ports, * and do not even try to handle any extra ports @@ -644,7 +648,6 @@ * Remove us from the hwgroup, and free * the hwgroup if we were the only member */ - d = hwgroup->drive; for (i = 0; i < MAX_DRIVES; ++i) { drive = &hwif->drives[i]; if (drive->de) { @@ -653,11 +656,23 @@ } if (!drive->present) continue; - while (hwgroup->drive->next != drive) - hwgroup->drive = hwgroup->drive->next; - hwgroup->drive->next = drive->next; - if (hwgroup->drive == drive) + if (drive == drive->next) { + /* special case: last drive from hwgroup. */ + BUG_ON(hwgroup->drive != drive); hwgroup->drive = NULL; + } else { + ide_drive_t *walk; + + walk = hwgroup->drive; + while (walk->next != drive) + walk = walk->next; + walk->next = drive->next; + if (hwgroup->drive == drive) { + hwgroup->drive = drive->next; + hwgroup->hwif = HWIF(hwgroup->drive); + } + } + BUG_ON(hwgroup->drive == drive); if (drive->id != NULL) { kfree(drive->id); drive->id = NULL; @@ -665,15 +680,28 @@ drive->present = 0; blk_cleanup_queue(&drive->queue); } - if (d->present) - hwgroup->drive = d; - while (hwgroup->hwif->next != hwif) - hwgroup->hwif = hwgroup->hwif->next; - hwgroup->hwif->next = hwif->next; - if (hwgroup->hwif == hwif) + if (hwif->next == hwif) { kfree(hwgroup); - else - hwgroup->hwif = HWIF(hwgroup->drive); + BUG_ON(hwgroup->hwif != hwif); + } else { + /* There is another interface in hwgroup. + * Unlink us, and set hwgroup->drive and ->hwif to + * something sane. + */ + g = hwgroup->hwif; + while (g->next != hwif) + g = g->next; + g->next = hwif->next; + if (hwgroup->hwif == hwif) { + /* Chose a random hwif for hwgroup->hwif. + * It's guaranteed that there are no drives + * left in the hwgroup. + */ + BUG_ON(hwgroup->drive != NULL); + hwgroup->hwif = g; + } + BUG_ON(hwgroup->hwif == hwif); + } #if !defined(CONFIG_DMA_NONPCI) if (hwif->dma_base) { @@ -813,7 +841,8 @@ hwif->hwif_data = old_hwif.hwif_data; abort: - spin_unlock_irqrestore(&ide_lock, flags); + spin_unlock_irq(&ide_lock); + up(&ide_cfg_sem); } EXPORT_SYMBOL(ide_unregister); @@ -998,7 +1027,7 @@ setting->set = set; setting->next = *p; - if (drive->driver) + if (drive->driver != &idedefault_driver) setting->auto_remove = 1; *p = setting; up(&ide_setting_sem); @@ -1255,13 +1284,14 @@ static int set_using_dma (ide_drive_t *drive, int arg) { - if (!drive->driver || !DRIVER(drive)->supports_dma) + if (!DRIVER(drive)->supports_dma) return -EPERM; if (!drive->id || !(drive->id->capability & 1)) return -EPERM; if (HWIF(drive)->ide_dma_check == NULL) return -EPERM; if (arg) { + if (HWIF(drive)->ide_dma_check(drive)) return -EIO; if (HWIF(drive)->ide_dma_on(drive)) return -EIO; } else { if (HWIF(drive)->ide_dma_off(drive)) return -EIO; @@ -1304,15 +1334,9 @@ return 0; } - if (drive->driver != NULL) { -#if 0 - ide_unregister_subdriver(drive); -#else - if (DRIVER(drive)->cleanup(drive)) { - drive->scsi = 0; - return 0; - } -#endif + if (DRIVER(drive)->cleanup(drive)) { + drive->scsi = 0; + return 0; } drive->scsi = (u8) arg; @@ -1353,7 +1377,7 @@ mdelay(50); #else __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/20); + schedule_timeout(1+HZ/20); #endif /* CONFIG_BLK_DEV_IDECS */ } @@ -1375,7 +1399,7 @@ { if (!drive->present || drive->usage || drive->dead) goto abort; - if (drive->driver != NULL && DRIVER(drive)->cleanup(drive)) + if (DRIVER(drive)->cleanup(drive)) goto abort; strncpy(drive->driver_req, driver, 9); if (ata_attach(drive)) { @@ -1387,7 +1411,7 @@ } else { drive->driver_req[0] = 0; } - if (DRIVER(drive) && !strcmp(DRIVER(drive)->name, driver)) + if (DRIVER(drive)!= &idedefault_driver && !strcmp(DRIVER(drive)->name, driver)) return 0; abort: return 1; @@ -1412,10 +1436,12 @@ spin_lock(&drivers_lock); module_put(driver->owner); } + drive->gendev.driver = &idedefault_driver.gen_driver; spin_unlock(&drivers_lock); + if(idedefault_driver.attach(drive) != 0) + panic("ide: default attach failed"); spin_lock(&drives_lock); list_add_tail(&drive->list, &ata_unused); - drive->gendev.driver = NULL; spin_unlock(&drives_lock); return 1; } @@ -1476,7 +1502,7 @@ case HDIO_GET_IDENTITY: if (bdev != bdev->bd_contains) return -EINVAL; - if (drive->id == NULL) + if (drive->id_read == 0) return -ENOMSG; if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142)) return -EFAULT; @@ -1521,7 +1547,7 @@ case HDIO_SCAN_HWIF: { int args[3]; - if (!capable(CAP_SYS_ADMIN)) return -EACCES; + if (!capable(CAP_SYS_RAWIO)) return -EACCES; if (copy_from_user(args, (void *)arg, 3 * sizeof(int))) return -EFAULT; if (ide_register(args[0], args[1], args[2]) == -1) @@ -1529,14 +1555,12 @@ return 0; } case HDIO_UNREGISTER_HWIF: - if (!capable(CAP_SYS_ADMIN)) return -EACCES; + if (!capable(CAP_SYS_RAWIO)) return -EACCES; /* (arg > MAX_HWIFS) checked in function */ ide_unregister(arg); return 0; case HDIO_SET_NICE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (drive->driver == NULL) - return -EPERM; if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1)))) return -EPERM; drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1; @@ -1550,18 +1574,26 @@ { unsigned long flags; if (!capable(CAP_SYS_ADMIN)) return -EACCES; -#if 1 + + /* + * Abort the current command on the + * group if there is one, taking + * care not to allow anything else + * to be queued and to die on the + * spot if we miss one somehow + */ + spin_lock_irqsave(&ide_lock, flags); - if ( HWGROUP(drive)->handler != NULL) { - printk(KERN_ERR "%s: ide_set_handler: handler not null; %p\n", drive->name, HWGROUP(drive)->handler); - (void) HWGROUP(drive)->handler(drive); -// HWGROUP(drive)->handler = NULL; - HWGROUP(drive)->expiry = NULL; - del_timer(&HWGROUP(drive)->timer); - } + + DRIVER(drive)->abort(drive, "drive reset"); + if(HWGROUP(drive)->handler) + BUG(); + + /* Ensure nothing gets queued after we + drop the lock. Reset will clear the busy */ + + HWGROUP(drive)->busy = 1; spin_unlock_irqrestore(&ide_lock, flags); - -#endif (void) ide_do_reset(drive); if (drive->suspend_reset) { /* @@ -1593,9 +1625,8 @@ if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (HWIF(drive)->busproc) - HWIF(drive)->busproc(drive, (int)arg); - return 0; - + return HWIF(drive)->busproc(drive, (int)arg); + return -EOPNOTSUPP; default: return -EINVAL; } @@ -2193,7 +2224,7 @@ static int default_shutdown(ide_drive_t *drive) { - if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) { + if (drive->usage || DRIVER(drive)->busy) { return 1; } drive->dead = 1; @@ -2261,6 +2292,11 @@ return 0; } +static ide_startstop_t default_abort (ide_drive_t *drive, const char *msg) +{ + return ide_abort(drive, msg); +} + static void setup_driver_defaults (ide_drive_t *drive) { ide_driver_t *d = drive->driver; @@ -2272,6 +2308,7 @@ if (d->end_request == NULL) d->end_request = default_end_request; if (d->sense == NULL) d->sense = default_sense; if (d->error == NULL) d->error = default_error; + if (d->abort == NULL) d->abort = default_abort; if (d->pre_reset == NULL) d->pre_reset = default_pre_reset; if (d->capacity == NULL) d->capacity = default_capacity; if (d->special == NULL) d->special = default_special; @@ -2282,9 +2319,11 @@ { unsigned long flags; + BUG_ON(drive->driver == NULL); + spin_lock_irqsave(&ide_lock, flags); if (version != IDE_SUBDRIVER_VERSION || !drive->present || - drive->driver != NULL || drive->usage || drive->dead) { + drive->driver != &idedefault_driver || drive->usage || drive->dead) { spin_unlock_irqrestore(&ide_lock, flags); return 1; } @@ -2294,6 +2333,7 @@ spin_lock(&drives_lock); list_add(&drive->list, &driver->drives); spin_unlock(&drives_lock); +// printk(KERN_INFO "%s: attached %s driver.\n", drive->name, driver->name); if ((drive->autotune == IDE_TUNE_DEFAULT) || (drive->autotune == IDE_TUNE_AUTO)) { /* DMA timings and setup moved to ide-probe.c */ @@ -2318,7 +2358,7 @@ unsigned long flags; spin_lock_irqsave(&ide_lock, flags); - if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) { + if (drive->usage || drive->driver == &idedefault_driver || DRIVER(drive)->busy) { spin_unlock_irqrestore(&ide_lock, flags); return 1; } @@ -2330,10 +2370,12 @@ ide_remove_proc_entries(drive->proc, generic_subdriver_entries); #endif auto_remove_settings(drive); - drive->driver = NULL; + drive->driver = &idedefault_driver; + setup_driver_defaults(drive); spin_unlock_irqrestore(&ide_lock, flags); spin_lock(&drives_lock); list_del_init(&drive->list); + list_add(&drive->list, &drive->driver->drives); spin_unlock(&drives_lock); return 0; } @@ -2343,10 +2385,7 @@ static int ide_drive_remove(struct device * dev) { ide_drive_t * drive = container_of(dev,ide_drive_t,gendev); - ide_driver_t * driver = drive->driver; - - if (driver && driver->cleanup) - driver->cleanup(drive); + DRIVER(drive)->cleanup(drive); return 0; } @@ -2366,7 +2405,8 @@ while (!list_empty(&list)) { ide_drive_t *drive = list_entry(list.next, ide_drive_t, list); list_del_init(&drive->list); - ata_attach(drive); + if (drive->present) + ata_attach(drive); } driver->gen_driver.name = (char *) driver->name; driver->gen_driver.bus = &ide_bus_type; diff -urN linux-2.5.65-bk2/drivers/ide/legacy/Makefile linux-2.5.65-bk3/drivers/ide/legacy/Makefile --- linux-2.5.65-bk2/drivers/ide/legacy/Makefile Mon Mar 17 13:43:43 2003 +++ linux-2.5.65-bk3/drivers/ide/legacy/Makefile Mon Mar 31 12:41:40 2003 @@ -2,6 +2,7 @@ obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o +obj-$(CONFIG_BLK_DEV_IDE_PC9800) += pc9800.o obj-$(CONFIG_BLK_DEV_PDC4030) += pdc4030.o obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o @@ -15,6 +16,10 @@ obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o # Last of all +ifneq ($(CONFIG_X86_PC9800),y) obj-$(CONFIG_BLK_DEV_HD) += hd.o +else +obj-$(CONFIG_BLK_DEV_HD) += hd98.o +endif EXTRA_CFLAGS := -Idrivers/ide diff -urN linux-2.5.65-bk2/drivers/ide/legacy/ali14xx.c linux-2.5.65-bk3/drivers/ide/legacy/ali14xx.c --- linux-2.5.65-bk2/drivers/ide/legacy/ali14xx.c Mon Mar 17 13:43:44 2003 +++ linux-2.5.65-bk3/drivers/ide/legacy/ali14xx.c Mon Mar 31 12:41:40 2003 @@ -229,10 +229,8 @@ return 1; } -#ifndef HWIF_PROBE_CLASSIC_METHOD probe_hwif_init(&ide_hwifs[0]); probe_hwif_init(&ide_hwifs[1]); -#endif /* HWIF_PROBE_CLASSIC_METHOD */ return 0; } diff -urN linux-2.5.65-bk2/drivers/ide/legacy/dtc2278.c linux-2.5.65-bk3/drivers/ide/legacy/dtc2278.c --- linux-2.5.65-bk2/drivers/ide/legacy/dtc2278.c Mon Mar 17 13:43:50 2003 +++ linux-2.5.65-bk3/drivers/ide/legacy/dtc2278.c Mon Mar 31 12:41:40 2003 @@ -138,11 +138,8 @@ ide_hwifs[1].mate = &ide_hwifs[0]; ide_hwifs[1].channel = 1; -#ifndef HWIF_PROBE_CLASSIC_METHOD probe_hwif_init(&ide_hwifs[0]); probe_hwif_init(&ide_hwifs[1]); -#endif /* HWIF_PROBE_CLASSIC_METHOD */ - } void __init dtc2278_release (void) diff -urN linux-2.5.65-bk2/drivers/ide/legacy/hd98.c linux-2.5.65-bk3/drivers/ide/legacy/hd98.c --- linux-2.5.65-bk2/drivers/ide/legacy/hd98.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/drivers/ide/legacy/hd98.c Mon Mar 31 12:41:40 2003 @@ -0,0 +1,904 @@ +/* + * Copyright (C) 1991, 1992 Linus Torvalds + * + * This is the low-level hd interrupt support. It traverses the + * request-list, using interrupts to jump between functions. As + * all the functions are called within interrupts, we may not + * sleep. Special care is recommended. + * + * modified by Drew Eckhardt to check nr of hd's from the CMOS. + * + * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug + * in the early extended-partition checks and added DM partitions + * + * IRQ-unmask, drive-id, multiple-mode, support for ">16 heads", + * and general streamlining by Mark Lord. + * + * Removed 99% of above. Use Mark's ide driver for those options. + * This is now a lightweight ST-506 driver. (Paul Gortmaker) + * + * Modified 1995 Russell King for ARM processor. + * + * Bugfix: max_sectors must be <= 255 or the wheels tend to come + * off in a hurry once you queue things up - Paul G. 02/2001 + */ + +/* Uncomment the following if you want verbose error reports. */ +/* #define VERBOSE_ERRORS */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* CMOS defines */ +#include +#include +#include + +#define REALLY_SLOW_IO +#include +#include +#include + +#define MAJOR_NR HD_MAJOR +#define DEVICE_NR(device) (minor(device)>>6) +#include + +#include "io_ports.h" + +#ifdef __arm__ +#undef HD_IRQ +#endif +#include +#ifdef __arm__ +#define HD_IRQ IRQ_HARDDISK +#endif + +/* Hd controller regster ports */ + +#define HD_DATA 0x640 /* _CTL when writing */ +#define HD_ERROR 0x642 /* see err-bits */ +#define HD_NSECTOR 0x644 /* nr of sectors to read/write */ +#define HD_SECTOR 0x646 /* starting sector */ +#define HD_LCYL 0x648 /* starting cylinder */ +#define HD_HCYL 0x64a /* high byte of starting cyl */ +#define HD_CURRENT 0x64c /* 101dhhhh , d=drive, hhhh=head */ +#define HD_STATUS 0x64e /* see status-bits */ +#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */ +#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */ +#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */ + +#define HD_CMD 0x74c /* used for resets */ +#define HD_ALTSTATUS 0x74c /* same as HD_STATUS but doesn't clear irq */ + +/* Bits of HD_STATUS */ +#define ERR_STAT 0x01 +#define INDEX_STAT 0x02 +#define ECC_STAT 0x04 /* Corrected error */ +#define DRQ_STAT 0x08 +#define SEEK_STAT 0x10 +#define SERVICE_STAT SEEK_STAT +#define WRERR_STAT 0x20 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +/* Bits for HD_ERROR */ +#define MARK_ERR 0x01 /* Bad address mark */ +#define TRK0_ERR 0x02 /* couldn't find track 0 */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* media change request */ +#define ID_ERR 0x10 /* ID field not found */ +#define MC_ERR 0x20 /* media changed */ +#define ECC_ERR 0x40 /* Uncorrectable ECC error */ +#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ +#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ + +static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED; + +#define TIMEOUT_VALUE (6*HZ) +#define HD_DELAY 0 + +#define MAX_ERRORS 16 /* Max read/write errors/sector */ +#define RESET_FREQ 8 /* Reset controller every 8th retry */ +#define RECAL_FREQ 4 /* Recalibrate every 4th retry */ +#define MAX_HD 2 + +#define STAT_OK (READY_STAT|SEEK_STAT) +#define OK_STATUS(s) (((s)&(STAT_OK|(BUSY_STAT|WRERR_STAT|ERR_STAT)))==STAT_OK) + +static void recal_intr(void); +static void bad_rw_intr(void); + +static char recalibrate[MAX_HD]; +static char special_op[MAX_HD]; + +static int reset; +static int hd_error; + +#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0) + +/* + * This struct defines the HD's and their types. + */ +struct hd_i_struct { + unsigned int head,sect,cyl,wpcom,lzone,ctl; +}; + +#ifdef HD_TYPE +struct hd_i_struct hd_info[] = { HD_TYPE }; +static int NR_HD = ((sizeof (hd_info))/(sizeof (struct hd_i_struct))); +#else +struct hd_i_struct hd_info[MAX_HD]; +static int NR_HD; +#endif + +static struct gendisk *hd_gendisk[MAX_HD]; + +static struct timer_list device_timer; + +#define TIMEOUT_VALUE (6*HZ) + +#define SET_TIMER \ + do { \ + mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \ + } while (0) + +static void (*do_hd)(void) = NULL; +#define SET_HANDLER(x) \ +if ((do_hd = (x)) != NULL) \ + SET_TIMER; \ +else \ + del_timer(&device_timer); + + +#if (HD_DELAY > 0) +unsigned long last_req; + +unsigned long read_timer(void) +{ + extern spinlock_t i8253_lock; + unsigned long t, flags; + int i; + + spin_lock_irqsave(&i8253_lock, flags); + t = jiffies * 11932; + outb_p(0, PIT_MODE); + i = inb_p(PIT_CH0); + i |= inb(PIT_CH0) << 8; + spin_unlock_irqrestore(&i8253_lock, flags); + return(t - i); +} +#endif + +void __init hd_setup(char *str, int *ints) +{ + int hdind = 0; + + if (ints[0] != 3) + return; + if (hd_info[0].head != 0) + hdind=1; + hd_info[hdind].head = ints[2]; + hd_info[hdind].sect = ints[3]; + hd_info[hdind].cyl = ints[1]; + hd_info[hdind].wpcom = 0; + hd_info[hdind].lzone = ints[1]; + hd_info[hdind].ctl = (ints[2] > 8 ? 8 : 0); + NR_HD = hdind+1; +} + +static void dump_status (const char *msg, unsigned int stat) +{ + char devc; + + devc = !blk_queue_empty(QUEUE) ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?'; +#ifdef VERBOSE_ERRORS + printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff); + if (stat & BUSY_STAT) printk("Busy "); + if (stat & READY_STAT) printk("DriveReady "); + if (stat & WRERR_STAT) printk("WriteFault "); + if (stat & SEEK_STAT) printk("SeekComplete "); + if (stat & DRQ_STAT) printk("DataRequest "); + if (stat & ECC_STAT) printk("CorrectedError "); + if (stat & INDEX_STAT) printk("Index "); + if (stat & ERR_STAT) printk("Error "); + printk("}\n"); + if ((stat & ERR_STAT) == 0) { + hd_error = 0; + } else { + hd_error = inb(HD_ERROR); + printk("hd%c: %s: error=0x%02x { ", devc, msg, hd_error & 0xff); + if (hd_error & BBD_ERR) printk("BadSector "); + if (hd_error & ECC_ERR) printk("UncorrectableError "); + if (hd_error & ID_ERR) printk("SectorIdNotFound "); + if (hd_error & ABRT_ERR) printk("DriveStatusError "); + if (hd_error & TRK0_ERR) printk("TrackZeroNotFound "); + if (hd_error & MARK_ERR) printk("AddrMarkNotFound "); + printk("}"); + if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { + printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), + inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); + if (!blk_queue_empty(QUEUE)) + printk(", sector=%ld", CURRENT->sector); + } + printk("\n"); + } +#else + printk("hd%c: %s: status=0x%02x.\n", devc, msg, stat & 0xff); + if ((stat & ERR_STAT) == 0) { + hd_error = 0; + } else { + hd_error = inb(HD_ERROR); + printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff); + } +#endif +} + +void check_status(void) +{ + int i = inb(HD_STATUS); + + if (!OK_STATUS(i)) { + dump_status("check_status", i); + bad_rw_intr(); + } +} + +static int controller_busy(void) +{ + int retries = 100000; + unsigned char status; + + do { + status = inb(HD_STATUS); + } while ((status & BUSY_STAT) && --retries); + return status; +} + +static int status_ok(void) +{ + unsigned char status = inb(HD_STATUS); + + if (status & BUSY_STAT) + return 1; /* Ancient, but does it make sense??? */ + if (status & WRERR_STAT) + return 0; + if (!(status & READY_STAT)) + return 0; + if (!(status & SEEK_STAT)) + return 0; + return 1; +} + +static int controller_ready(unsigned int drive, unsigned int head) +{ + int retry = 100; + + do { + if (controller_busy() & BUSY_STAT) + return 0; + outb(0xA0 | (drive<<4) | head, HD_CURRENT); + if (status_ok()) + return 1; + } while (--retry); + return 0; +} + +static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect, + unsigned int head,unsigned int cyl,unsigned int cmd, + void (*intr_addr)(void)) +{ + unsigned short port; + +#if (HD_DELAY > 0) + while (read_timer() - last_req < HD_DELAY) + /* nothing */; +#endif + if (reset) + return; + if (!controller_ready(drive, head)) { + reset = 1; + return; + } + SET_HANDLER(intr_addr); + outb(hd_info[drive].ctl,HD_CMD); + port=HD_DATA + 2; + outb(hd_info[drive].wpcom>>2, port); port += 2; + outb(nsect, port); port += 2; + outb(sect, port); port += 2; + outb(cyl, port); port += 2; + outb(cyl>>8, port); port += 2; + outb(0xA0|(drive<<4)|head, port); port += 2; + outb(cmd, port); +} + +static void hd_request (void); + +static int drive_busy(void) +{ + unsigned int i; + unsigned char c; + + for (i = 0; i < 500000 ; i++) { + c = inb(HD_STATUS); + if ((c & (BUSY_STAT | READY_STAT | SEEK_STAT)) == STAT_OK) + return 0; + } + dump_status("reset timed out", c); + return 1; +} + +static void reset_controller(void) +{ + int i; + + outb(4,HD_CMD); + for(i = 0; i < 1000; i++) barrier(); + outb(hd_info[0].ctl & 0x0f,HD_CMD); + for(i = 0; i < 1000; i++) barrier(); + if (drive_busy()) + printk("hd: controller still busy\n"); + else if ((hd_error = inb(HD_ERROR)) != 1) + printk("hd: controller reset failed: %02x\n",hd_error); +} + +static void reset_hd(void) +{ + static int i; + +repeat: + if (reset) { + reset = 0; + i = -1; + reset_controller(); + } else { + check_status(); + if (reset) + goto repeat; + } + if (++i < NR_HD) { + special_op[i] = recalibrate[i] = 1; + hd_out(i,hd_info[i].sect,hd_info[i].sect,hd_info[i].head-1, + hd_info[i].cyl,WIN_SPECIFY,&reset_hd); + if (reset) + goto repeat; + } else + hd_request(); +} + +/* + * Ok, don't know what to do with the unexpected interrupts: on some machines + * doing a reset and a retry seems to result in an eternal loop. Right now I + * ignore it, and just set the timeout. + * + * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the + * drive enters "idle", "standby", or "sleep" mode, so if the status looks + * "good", we just ignore the interrupt completely. + */ +void unexpected_hd_interrupt(void) +{ + unsigned int stat = inb(HD_STATUS); + + if (stat & (BUSY_STAT|DRQ_STAT|ECC_STAT|ERR_STAT)) { + dump_status ("unexpected interrupt", stat); + SET_TIMER; + } +} + +/* + * bad_rw_intr() now tries to be a bit smarter and does things + * according to the error returned by the controller. + * -Mika Liljeberg (liljeber@cs.Helsinki.FI) + */ +static void bad_rw_intr(void) +{ + int dev; + + if (blk_queue_empty(QUEUE)) + return; + dev = DEVICE_NR(CURRENT->rq_dev); + if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { + end_request(CURRENT, 0); + special_op[dev] = recalibrate[dev] = 1; + } else if (CURRENT->errors % RESET_FREQ == 0) + reset = 1; + else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0) + special_op[dev] = recalibrate[dev] = 1; + /* Otherwise just retry */ +} + +static inline int wait_DRQ(void) +{ + int retries = 100000, stat; + + while (--retries > 0) + if ((stat = inb(HD_STATUS)) & DRQ_STAT) + return 0; + dump_status("wait_DRQ", stat); + return -1; +} + +static void read_intr(void) +{ + int i, retries = 100000; + + do { + i = (unsigned) inb(HD_STATUS); + if (i & BUSY_STAT) + continue; + if (!OK_STATUS(i)) + break; + if (i & DRQ_STAT) + goto ok_to_read; + } while (--retries > 0); + dump_status("read_intr", i); + bad_rw_intr(); + hd_request(); + return; +ok_to_read: + insw(HD_DATA,CURRENT->buffer,256); + CURRENT->sector++; + CURRENT->buffer += 512; + CURRENT->errors = 0; + i = --CURRENT->nr_sectors; + --CURRENT->current_nr_sectors; +#ifdef DEBUG + printk("hd%c: read: sector %ld, remaining = %ld, buffer=0x%08lx\n", + dev+'a', CURRENT->sector, CURRENT->nr_sectors, + (unsigned long) CURRENT->buffer+512); +#endif + if (CURRENT->current_nr_sectors <= 0) + end_request(CURRENT, 1); + if (i > 0) { + SET_HANDLER(&read_intr); + return; + } + (void) inb(HD_STATUS); +#if (HD_DELAY > 0) + last_req = read_timer(); +#endif + if (!blk_queue_empty(QUEUE)) + hd_request(); + return; +} + +static void write_intr(void) +{ + int i; + int retries = 100000; + + do { + i = (unsigned) inb(HD_STATUS); + if (i & BUSY_STAT) + continue; + if (!OK_STATUS(i)) + break; + if ((CURRENT->nr_sectors <= 1) || (i & DRQ_STAT)) + goto ok_to_write; + } while (--retries > 0); + dump_status("write_intr", i); + bad_rw_intr(); + hd_request(); + return; +ok_to_write: + CURRENT->sector++; + i = --CURRENT->nr_sectors; + --CURRENT->current_nr_sectors; + CURRENT->buffer += 512; + if (!i || (CURRENT->bio && !SUBSECTOR(i))) + end_request(CURRENT, 1); + if (i > 0) { + SET_HANDLER(&write_intr); + outsw(HD_DATA,CURRENT->buffer,256); + local_irq_enable(); + } else { +#if (HD_DELAY > 0) + last_req = read_timer(); +#endif + hd_request(); + } + return; +} + +static void recal_intr(void) +{ + check_status(); +#if (HD_DELAY > 0) + last_req = read_timer(); +#endif + hd_request(); +} + +/* + * This is another of the error-routines I don't know what to do with. The + * best idea seems to just set reset, and start all over again. + */ +static void hd_times_out(unsigned long dummy) +{ + unsigned int dev; + + do_hd = NULL; + + if (blk_queue_empty(QUEUE)) + return; + + disable_irq(HD_IRQ); + local_irq_enable(); + reset = 1; + dev = DEVICE_NR(CURRENT->rq_dev); + printk("hd%c: timeout\n", dev+'a'); + if (++CURRENT->errors >= MAX_ERRORS) { +#ifdef DEBUG + printk("hd%c: too many errors\n", dev+'a'); +#endif + end_request(CURRENT, 0); + } + local_irq_disable(); + hd_request(); + enable_irq(HD_IRQ); +} + +int do_special_op (unsigned int dev) +{ + if (recalibrate[dev]) { + recalibrate[dev] = 0; + hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr); + return reset; + } + if (hd_info[dev].head > 16) { + printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a'); + end_request(CURRENT, 0); + } + special_op[dev] = 0; + return 1; +} + +/* + * The driver enables interrupts as much as possible. In order to do this, + * (a) the device-interrupt is disabled before entering hd_request(), + * and (b) the timeout-interrupt is disabled before the sti(). + * + * Interrupts are still masked (by default) whenever we are exchanging + * data/cmds with a drive, because some drives seem to have very poor + * tolerance for latency during I/O. The IDE driver has support to unmask + * interrupts for non-broken hardware, so use that driver if required. + */ +static void hd_request(void) +{ + unsigned int dev, block, nsect, sec, track, head, cyl; + + if (do_hd) + return; +repeat: + del_timer(&device_timer); + local_irq_enable(); + + if (blk_queue_empty(QUEUE)) { + do_hd = NULL; + return; + } + + if (reset) { + local_irq_disable(); + reset_hd(); + return; + } + dev = DEVICE_NR(CURRENT->rq_dev); + block = CURRENT->sector; + nsect = CURRENT->nr_sectors; + if (dev >= NR_HD) { + printk("hd: bad disk number: %d\n", dev); + end_request(CURRENT, 0); + goto repeat; + } + if (block >= get_capacity(hd_gendisk[dev]) || + ((block+nsect) > get_capacity(hd_gendisk[dev]))) { + printk("%s: bad access: block=%d, count=%d\n", + hd_gendisk[dev]->disk_name, block, nsect); + end_request(CURRENT, 0); + goto repeat; + } + + if (special_op[dev]) { + if (do_special_op(dev)) + goto repeat; + return; + } + sec = block % hd_info[dev].sect + 1; + track = block / hd_info[dev].sect; + head = track % hd_info[dev].head; + cyl = track / hd_info[dev].head; +#ifdef DEBUG + printk("hd%c: %sing: CHS=%d/%d/%d, sectors=%d, buffer=0x%08lx\n", + dev+'a', (CURRENT->cmd == READ)?"read":"writ", + cyl, head, sec, nsect, (unsigned long) CURRENT->buffer); +#endif + if(CURRENT->flags & REQ_CMD) { + switch (rq_data_dir(CURRENT)) { + case READ: + hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr); + if (reset) + goto repeat; + break; + case WRITE: + hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr); + if (reset) + goto repeat; + if (wait_DRQ()) { + bad_rw_intr(); + goto repeat; + } + outsw(HD_DATA,CURRENT->buffer,256); + break; + default: + printk("unknown hd-command\n"); + end_request(CURRENT, 0); + break; + } + } +} + +static void do_hd_request (request_queue_t * q) +{ + disable_irq(HD_IRQ); + hd_request(); + enable_irq(HD_IRQ); +} + +static int hd_ioctl(struct inode * inode, struct file * file, + unsigned int cmd, unsigned long arg) +{ + struct hd_geometry *loc = (struct hd_geometry *) arg; + int dev; + + if ((!inode) || kdev_none(inode->i_rdev)) + return -EINVAL; + dev = DEVICE_NR(inode->i_rdev); + if (dev >= NR_HD) + return -EINVAL; + switch (cmd) { + case HDIO_GETGEO: + { + struct hd_geometry g; + if (!loc) return -EINVAL; + g.heads = hd_info[dev].head; + g.sectors = hd_info[dev].sect; + g.cylinders = hd_info[dev].cyl; + g.start = get_start_sect(inode->i_bdev); + return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; + } + + default: + return -EINVAL; + } +} + +static int hd_open(struct inode * inode, struct file * filp) +{ + int target = DEVICE_NR(inode->i_rdev); + if (target >= NR_HD) + return -ENODEV; + return 0; +} + +/* + * Releasing a block device means we sync() it, so that it can safely + * be forgotten about... + */ + +extern struct block_device_operations hd_fops; + +static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + void (*handler)(void) = do_hd; + + do_hd = NULL; + del_timer(&device_timer); + if (!handler) + handler = unexpected_hd_interrupt; + handler(); + local_irq_enable(); +} + +static struct block_device_operations hd_fops = { + .open = hd_open, + .ioctl = hd_ioctl, +}; + +/* + * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags + * means we run the IRQ-handler with interrupts disabled: this is bad for + * interrupt latency, but anything else has led to problems on some + * machines. + * + * We enable interrupts in some of the routines after making sure it's + * safe. + */ + +static int __init hd_init(void) +{ + int drive; + if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) { + printk("hd: unable to get major %d for hard disk\n",MAJOR_NR); + return -1; + } + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock); + blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255); + init_timer(&device_timer); + device_timer.function = hd_times_out; + blk_queue_hardsect_size(QUEUE, 512); + +#ifdef __i386__ + if (!NR_HD) { + extern struct drive_info drive_info; + unsigned char *BIOS = (unsigned char *) &drive_info; + unsigned long flags; +#ifndef CONFIG_X86_PC9800 + int cmos_disks; +#endif + + for (drive=0 ; drive<2 ; drive++) { + hd_info[drive].cyl = *(unsigned short *) BIOS; + hd_info[drive].head = *(3+BIOS); + hd_info[drive].sect = *(2+BIOS); + hd_info[drive].wpcom = 0; + hd_info[drive].ctl = *(3+BIOS) > 8 ? 8 : 0; + hd_info[drive].lzone = *(unsigned short *) BIOS; + if (hd_info[drive].cyl && NR_HD == drive) + NR_HD++; + BIOS += 6; + } + + } +#endif /* __i386__ */ +#ifdef __arm__ + if (!NR_HD) { + /* We don't know anything about the drive. This means + * that you *MUST* specify the drive parameters to the + * kernel yourself. + */ + printk("hd: no drives specified - use hd=cyl,head,sectors" + " on kernel command line\n"); + } +#endif + if (!NR_HD) + goto out; + + for (drive=0 ; drive < NR_HD ; drive++) { + struct gendisk *disk = alloc_disk(); + if (!disk) + goto Enomem; + disk->major = MAJOR_NR; + disk->first_minor = drive << 6; + disk->minor_shift = 6; + disk->fops = &hd_fops; + sprintf(disk->disk_name, "hd%c", 'a'+drive); + hd_gendisk[drive] = disk; + } + for (drive=0 ; drive < NR_HD ; drive++) { + sector_t size = hd_info[drive].head * + hd_info[drive].sect * hd_info[drive].cyl; + set_capacity(hd_gendisk[drive], size); + printk ("%s: %ldMB, CHS=%d/%d/%d\n", + hd_gendisk[drive]->disk_name, + size / 2048, hd_info[drive].cyl, + hd_info[drive].head, hd_info[drive].sect); + } + + if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) { + printk("hd: unable to get IRQ%d for the hard disk driver\n", + HD_IRQ); + goto out1; + } + + if (!request_region(HD_DATA, 2, "hd(data)")) { + printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); + NR_HD = 0; + free_irq(HD_IRQ, NULL); + return; + } + + if (!request_region(HD_DATA + 2, 1, "hd")) + { + printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); + goto out2; + } + + if (!request_region(HD_DATA + 4, 1, "hd")) + { + printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); + goto out3; + } + + if (!request_region(HD_DATA + 6, 1, "hd")) + { + printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); + goto out4; + } + + if (!request_region(HD_DATA + 8, 1, "hd")) + { + printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); + goto out5; + } + + if (!request_region(HD_DATA + 10, 1, "hd")) + { + printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); + goto out6; + } + + if (!request_region(HD_DATA + 12, 1, "hd")) + { + printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); + goto out7; + } + + if (!request_region(HD_CMD, 1, "hd(cmd)")) + { + printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD); + goto out8; + } + + if (!request_region(HD_CMD + 2, 1, "hd(cmd)")) + { + printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD); + goto out9; + } + + for(drive=0; drive < NR_HD; drive++) { + struct hd_i_struct *p = hd_info + drive; + set_capacity(hd_gendisk[drive], p->head * p->sect * p->cyl); + add_disk(hd_gendisk[drive]); + } + return 0; + +out9: + release_region(HD_CMD, 1); +out8: + release_region(HD_DATA + 12, 1); +out7: + release_region(HD_DATA + 10, 1); +out6: + release_region(HD_DATA + 8, 1); +out5: + release_region(HD_DATA + 6, 1); +out4: + release_region(HD_DATA + 4, 1); +out3: + release_region(HD_DATA + 2, 1); +out2: + release_region(HD_DATA, 2); + free_irq(HD_IRQ, NULL); +out1: + for (drive = 0; drive < NR_HD; drive++) + put_disk(hd_gendisk[drive]); + NR_HD = 0; +out: + del_timer(&device_timer); + unregister_blkdev(MAJOR_NR,"hd"); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + return -1; +Enomem: + while (drive--) + put_disk(hd_gendisk[drive]); + goto out; +} + +static int parse_hd_setup (char *line) { + int ints[6]; + + (void) get_options(line, ARRAY_SIZE(ints), ints); + hd_setup(NULL, ints); + + return 1; +} +__setup("hd=", parse_hd_setup); + +module_init(hd_init); diff -urN linux-2.5.65-bk2/drivers/ide/legacy/ht6560b.c linux-2.5.65-bk3/drivers/ide/legacy/ht6560b.c --- linux-2.5.65-bk2/drivers/ide/legacy/ht6560b.c Mon Mar 17 13:44:40 2003 +++ linux-2.5.65-bk3/drivers/ide/legacy/ht6560b.c Mon Mar 31 12:41:40 2003 @@ -312,42 +312,7 @@ #endif } -void __init probe_ht6560b (void) -{ - int t; - - request_region(HT_CONFIG_PORT, 1, ide_hwifs[0].name); - ide_hwifs[0].chipset = ide_ht6560b; - ide_hwifs[1].chipset = ide_ht6560b; - ide_hwifs[0].selectproc = &ht6560b_selectproc; - ide_hwifs[1].selectproc = &ht6560b_selectproc; - ide_hwifs[0].tuneproc = &tune_ht6560b; - ide_hwifs[1].tuneproc = &tune_ht6560b; - ide_hwifs[0].serialized = 1; /* is this needed? */ - ide_hwifs[1].serialized = 1; /* is this needed? */ - ide_hwifs[0].mate = &ide_hwifs[1]; - ide_hwifs[1].mate = &ide_hwifs[0]; - ide_hwifs[1].channel = 1; - - /* - * Setting default configurations for drives - */ - t = (HT_CONFIG_DEFAULT << 8); - t |= HT_TIMING_DEFAULT; - ide_hwifs[0].drives[0].drive_data = t; - ide_hwifs[0].drives[1].drive_data = t; - t |= (HT_SECONDARY_IF << 8); - ide_hwifs[1].drives[0].drive_data = t; - ide_hwifs[1].drives[1].drive_data = t; - -#ifndef HWIF_PROBE_CLASSIC_METHOD - probe_hwif_init(&ide_hwifs[0]); - probe_hwif_init(&ide_hwifs[1]); -#endif /* HWIF_PROBE_CLASSIC_METHOD */ - -} - -void __init ht6560b_release (void) +void ht6560b_release (void) { if (ide_hwifs[0].chipset != ide_ht6560b && ide_hwifs[1].chipset != ide_ht6560b) @@ -371,60 +336,80 @@ release_region(HT_CONFIG_PORT, 1); } -#ifndef MODULE -/* - * init_ht6560b: - * - * called by ide.c when parsing command line - */ - -void __init init_ht6560b (void) +int __init ht6560b_mod_init(void) { - if (check_region(HT_CONFIG_PORT,1)) { + int t; + + if (!request_region(HT_CONFIG_PORT, 1, ide_hwifs[0].name)) { printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n", __FUNCTION__); - return; + return -ENODEV; } + if (!try_to_init_ht6560b()) { - printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__); - return; + printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__); + goto release_region; } - probe_ht6560b(); -} -#else + ide_hwifs[0].chipset = ide_ht6560b; + ide_hwifs[1].chipset = ide_ht6560b; + ide_hwifs[0].selectproc = &ht6560b_selectproc; + ide_hwifs[1].selectproc = &ht6560b_selectproc; + ide_hwifs[0].tuneproc = &tune_ht6560b; + ide_hwifs[1].tuneproc = &tune_ht6560b; + ide_hwifs[0].serialized = 1; /* is this needed? */ + ide_hwifs[1].serialized = 1; /* is this needed? */ + ide_hwifs[0].mate = &ide_hwifs[1]; + ide_hwifs[1].mate = &ide_hwifs[0]; + ide_hwifs[1].channel = 1; -MODULE_AUTHOR("See Local File"); -MODULE_DESCRIPTION("HT-6560B EIDE-controller support"); -MODULE_LICENSE("GPL"); + /* + * Setting default configurations for drives + */ + t = (HT_CONFIG_DEFAULT << 8); + t |= HT_TIMING_DEFAULT; + ide_hwifs[0].drives[0].drive_data = t; + ide_hwifs[0].drives[1].drive_data = t; + t |= (HT_SECONDARY_IF << 8); + ide_hwifs[1].drives[0].drive_data = t; + ide_hwifs[1].drives[1].drive_data = t; -int __init ht6560b_mod_init(void) -{ - if (check_region(HT_CONFIG_PORT,1)) { - printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n", - __FUNCTION__); - return -ENODEV; - } + probe_hwif_init(&ide_hwifs[0]); + probe_hwif_init(&ide_hwifs[1]); - if (!try_to_init_ht6560b()) { - printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__); +#ifdef MODULE + if (ide_hwifs[0].chipset != ide_ht6560b && + ide_hwifs[1].chipset != ide_ht6560b) { + ht6560b_release(); return -ENODEV; } +#endif - probe_ht6560b(); - if (ide_hwifs[0].chipset != ide_ht6560b && - ide_hwifs[1].chipset != ide_ht6560b) { - ht6560b_release(); - return -ENODEV; - } - return 0; + return 0; + +release_region: + release_region(HT_CONFIG_PORT, 1); + return -ENODEV; } -module_init(ht6560b_mod_init); +MODULE_AUTHOR("See Local File"); +MODULE_DESCRIPTION("HT-6560B EIDE-controller support"); +MODULE_LICENSE("GPL"); + +#ifdef MODULE void __init ht6560b_mod_exit(void) { ht6560b_release(); } + +module_init(ht6560b_mod_init); module_exit(ht6560b_mod_exit); +#else +/* + * called by ide.c when parsing command line + */ +void __init init_ht6560b (void) +{ + ht6560b_mod_init(); /* ignore return value */ +} #endif - diff -urN linux-2.5.65-bk2/drivers/ide/legacy/pc9800.c linux-2.5.65-bk3/drivers/ide/legacy/pc9800.c --- linux-2.5.65-bk2/drivers/ide/legacy/pc9800.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/drivers/ide/legacy/pc9800.c Mon Mar 31 12:41:40 2003 @@ -0,0 +1,80 @@ +/* + * ide_pc9800.c + * + * Copyright (C) 1997-2000 Linux/98 project, + * Kyoto University Microcomputer Club. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define PC9800_IDE_BANKSELECT 0x432 + +#undef PC9800_IDE_DEBUG + +static void pc9800_select(ide_drive_t *drive) +{ +#ifdef PC9800_IDE_DEBUG + byte old; + + /* Too noisy: */ + /* printk(KERN_DEBUG "pc9800_select(%s)\n", drive->name); */ + + outb(0x80, PC9800_IDE_BANKSELECT); + old = inb(PC9800_IDE_BANKSELECT); + if (old != HWIF(drive)->index) + printk(KERN_DEBUG "ide-pc9800: switching bank #%d -> #%d\n", + old, HWIF(drive)->index); +#endif + outb(HWIF(drive)->index, PC9800_IDE_BANKSELECT); +} + +void __init ide_probe_for_pc9800(void) +{ + u8 saved_bank; + + if (!PC9800_9821_P() /* || !PC9821_IDEIF_DOUBLE_P() */) + return; + + if (!request_region(PC9800_IDE_BANKSELECT, 1, "ide0/1 bank")) { + printk(KERN_ERR + "ide: bank select port (%#x) is already occupied!\n", + PC9800_IDE_BANKSELECT); + return; + } + + /* Do actual probing. */ + if ((saved_bank = inb(PC9800_IDE_BANKSELECT)) == (u8) ~0 + || (outb(saved_bank ^ 1, PC9800_IDE_BANKSELECT), + /* Next outb is dummy for reading status. */ + outb(0x80, PC9800_IDE_BANKSELECT), + inb(PC9800_IDE_BANKSELECT) != (saved_bank ^ 1))) { + printk(KERN_INFO + "ide: pc9800 type bank selecting port not found\n"); + release_region(PC9800_IDE_BANKSELECT, 1); + return; + } + + /* Restore original value, just in case. */ + outb(saved_bank, PC9800_IDE_BANKSELECT); + + /* These ports are probably used by IDE I/F. */ + request_region(0x430, 1, "ide"); + request_region(0x435, 1, "ide"); + + if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET] == HD_DATA && + ide_hwifs[1].io_ports[IDE_DATA_OFFSET] == HD_DATA) { + ide_hwifs[0].chipset = ide_pc9800; + ide_hwifs[0].mate = &ide_hwifs[1]; + ide_hwifs[0].selectproc = pc9800_select; + ide_hwifs[1].chipset = ide_pc9800; + ide_hwifs[1].mate = &ide_hwifs[0]; + ide_hwifs[1].selectproc = pc9800_select; + } +} diff -urN linux-2.5.65-bk2/drivers/ide/legacy/pdc4030.c linux-2.5.65-bk3/drivers/ide/legacy/pdc4030.c --- linux-2.5.65-bk2/drivers/ide/legacy/pdc4030.c Mon Mar 17 13:44:06 2003 +++ linux-2.5.65-bk3/drivers/ide/legacy/pdc4030.c Mon Mar 31 12:41:40 2003 @@ -256,12 +256,11 @@ if (!ident.current_tm[i+2].cyl) hwif2->drives[i].noprobe = 1; } -#ifndef HWIF_PROBE_CLASSIC_METHOD + probe_hwif_init(&ide_hwifs[hwif->index]); probe_hwif_init(&ide_hwifs[hwif2->index]); -#endif /* HWIF_PROBE_CLASSIC_METHOD */ - return 1; + return 1; } /* diff -urN linux-2.5.65-bk2/drivers/ide/legacy/qd65xx.c linux-2.5.65-bk3/drivers/ide/legacy/qd65xx.c --- linux-2.5.65-bk2/drivers/ide/legacy/qd65xx.c Mon Mar 17 13:43:44 2003 +++ linux-2.5.65-bk3/drivers/ide/legacy/qd65xx.c Mon Mar 31 12:41:40 2003 @@ -359,9 +359,7 @@ hwif->drives[0].io_32bit = hwif->drives[1].io_32bit = 1; hwif->tuneproc = tuneproc; -#ifndef HWIF_PROBE_CLASSIC_METHOD probe_hwif_init(hwif); -#endif /* HWIF_PROBE_CLASSIC_METHOD */ } /* diff -urN linux-2.5.65-bk2/drivers/ide/legacy/umc8672.c linux-2.5.65-bk3/drivers/ide/legacy/umc8672.c --- linux-2.5.65-bk2/drivers/ide/legacy/umc8672.c Mon Mar 17 13:43:44 2003 +++ linux-2.5.65-bk3/drivers/ide/legacy/umc8672.c Mon Mar 31 12:41:40 2003 @@ -162,10 +162,8 @@ ide_hwifs[1].mate = &ide_hwifs[0]; ide_hwifs[1].channel = 1; -#ifndef HWIF_PROBE_CLASSIC_METHOD probe_hwif_init(&ide_hwifs[0]); probe_hwif_init(&ide_hwifs[1]); -#endif /* HWIF_PROBE_CLASSIC_METHOD */ return 0; } diff -urN linux-2.5.65-bk2/drivers/ide/pci/aec62xx.c linux-2.5.65-bk3/drivers/ide/pci/aec62xx.c --- linux-2.5.65-bk2/drivers/ide/pci/aec62xx.c Mon Mar 17 13:44:41 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/aec62xx.c Mon Mar 31 12:41:40 2003 @@ -38,6 +38,7 @@ char *chipset_nums[] = {"error", "error", "error", "error", "error", "error", "850UF", "860", "860R", "865", "865R", "error" }; + int len; int i; for (i = 0; i < n_aec_devs; i++) { @@ -170,7 +171,11 @@ #endif /* DEBUG_AEC_REGS */ } } - return p-buffer;/* => must be less than 4k! */ + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } #endif /* defined(DISPLAY_AEC62xx_TIMINGS) && defined(CONFIG_PROC_FS) */ @@ -324,7 +329,7 @@ ide_hwif_t *hwif = HWIF(drive); struct hd_driveid *id = drive->id; - if (id && (id->capability & 1) && drive->autodma) { + if ((id->capability & 1) && drive->autodma) { /* Consult the list of known "bad" drives */ if (hwif->ide_dma_bad_drive(drive)) goto fast_ata_pio; diff -urN linux-2.5.65-bk2/drivers/ide/pci/alim15x3.c linux-2.5.65-bk3/drivers/ide/pci/alim15x3.c --- linux-2.5.65-bk2/drivers/ide/pci/alim15x3.c Mon Mar 17 13:44:03 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/alim15x3.c Mon Mar 31 12:41:40 2003 @@ -518,7 +518,7 @@ if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) { /* Consult the list of known "bad" drives */ if (hwif->ide_dma_bad_drive(drive)) - goto fast_ata_pio; + goto ata_pio; if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) { if (id->dma_ultra & hwif->ultra_mask) { /* Force if Capable UltraDMA */ @@ -540,12 +540,12 @@ if (!config_chipset_for_dma(drive)) goto no_dma_set; } else { - goto fast_ata_pio; + goto ata_pio; } - } else if ((id->capability & 8) || (id->field_valid & 2)) { -fast_ata_pio: + } else { +ata_pio: + hwif->tuneproc(drive, 255); no_dma_set: - hwif->tuneproc(drive, 5); return hwif->ide_dma_off_quietly(drive); } return hwif->ide_dma_on(drive); @@ -753,6 +753,8 @@ return; } + hwif->atapi_dma = 1; + if (m5229_revision > 0x20) hwif->ultra_mask = 0x3f; hwif->mwdma_mask = 0x07; diff -urN linux-2.5.65-bk2/drivers/ide/pci/amd74xx.c linux-2.5.65-bk3/drivers/ide/pci/amd74xx.c --- linux-2.5.65-bk2/drivers/ide/pci/amd74xx.c Mon Mar 17 13:44:50 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/amd74xx.c Mon Mar 31 12:41:40 2003 @@ -98,6 +98,7 @@ unsigned int v, u, i; unsigned short c, w; unsigned char t; + int len; char *p = buffer; amd_print("----------AMD BusMastering IDE Configuration----------------"); @@ -167,7 +168,11 @@ amd_print_drive("Cycle Time: ", "%8dns", cycle[i]); amd_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 1000, speed[i] / 100 % 10); - return p - buffer; /* hoping it is less than 4K... */ + /* hoping p - buffer is less than 4K... */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } #endif diff -urN linux-2.5.65-bk2/drivers/ide/pci/cmd640.c linux-2.5.65-bk3/drivers/ide/pci/cmd640.c --- linux-2.5.65-bk2/drivers/ide/pci/cmd640.c Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/cmd640.c Mon Mar 31 12:41:40 2003 @@ -197,8 +197,8 @@ * Interface to access cmd640x registers */ static unsigned int cmd640_key; -static void (*put_cmd640_reg)(u16 reg, u8 val); -static u8 (*get_cmd640_reg)(u16 reg); +static void (*__put_cmd640_reg)(u16 reg, u8 val); +static u8 (*__get_cmd640_reg)(u16 reg); /* * This is read from the CFR reg, and is used in several places. @@ -215,49 +215,32 @@ static void put_cmd640_reg_pci1 (u16 reg, u8 val) { - unsigned long flags; - - spin_lock_irqsave(&ide_lock, flags); outb_p((reg & 0xfc) | cmd640_key, 0xcf8); outb_p(val, (reg & 3) | 0xcfc); - spin_unlock_irqrestore(&ide_lock, flags); } static u8 get_cmd640_reg_pci1 (u16 reg) { - u8 b; - unsigned long flags; - - spin_lock_irqsave(&ide_lock, flags); outb_p((reg & 0xfc) | cmd640_key, 0xcf8); - b = inb_p((reg & 3) | 0xcfc); - spin_unlock_irqrestore(&ide_lock, flags); - return b; + return inb_p((reg & 3) | 0xcfc); } /* PCI method 2 access (from CMD datasheet) */ static void put_cmd640_reg_pci2 (u16 reg, u8 val) { - unsigned long flags; - - spin_lock_irqsave(&ide_lock, flags); outb_p(0x10, 0xcf8); outb_p(val, cmd640_key + reg); outb_p(0, 0xcf8); - spin_unlock_irqrestore(&ide_lock, flags); } static u8 get_cmd640_reg_pci2 (u16 reg) { u8 b; - unsigned long flags; - spin_lock_irqsave(&ide_lock, flags); outb_p(0x10, 0xcf8); b = inb_p(cmd640_key + reg); outb_p(0, 0xcf8); - spin_unlock_irqrestore(&ide_lock, flags); return b; } @@ -265,26 +248,36 @@ static void put_cmd640_reg_vlb (u16 reg, u8 val) { - unsigned long flags; - - spin_lock_irqsave(&ide_lock, flags); outb_p(reg, cmd640_key); outb_p(val, cmd640_key + 4); - spin_unlock_irqrestore(&ide_lock, flags); } static u8 get_cmd640_reg_vlb (u16 reg) { + outb_p(reg, cmd640_key); + return inb_p(cmd640_key + 4); +} + +static u8 get_cmd640_reg(u16 reg) +{ u8 b; unsigned long flags; spin_lock_irqsave(&ide_lock, flags); - outb_p(reg, cmd640_key); - b = inb_p(cmd640_key + 4); + b = __get_cmd640_reg(reg); spin_unlock_irqrestore(&ide_lock, flags); return b; } +static void put_cmd640_reg(u16 reg, u8 val) +{ + unsigned long flags; + + spin_lock_irqsave(&ide_lock, flags); + __put_cmd640_reg(reg,val); + spin_unlock_irqrestore(&ide_lock, flags); +} + static int __init match_pci_cmd640_device (void) { const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06}; @@ -307,8 +300,8 @@ */ static int __init probe_for_cmd640_pci1 (void) { - get_cmd640_reg = get_cmd640_reg_pci1; - put_cmd640_reg = put_cmd640_reg_pci1; + __get_cmd640_reg = get_cmd640_reg_pci1; + __put_cmd640_reg = put_cmd640_reg_pci1; for (cmd640_key = 0x80000000; cmd640_key <= 0x8000f800; cmd640_key += 0x800) { @@ -323,8 +316,8 @@ */ static int __init probe_for_cmd640_pci2 (void) { - get_cmd640_reg = get_cmd640_reg_pci2; - put_cmd640_reg = put_cmd640_reg_pci2; + __get_cmd640_reg = get_cmd640_reg_pci2; + __put_cmd640_reg = put_cmd640_reg_pci2; for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) { if (match_pci_cmd640_device()) return 1; /* success */ @@ -339,8 +332,8 @@ { u8 b; - get_cmd640_reg = get_cmd640_reg_vlb; - put_cmd640_reg = put_cmd640_reg_vlb; + __get_cmd640_reg = get_cmd640_reg_vlb; + __put_cmd640_reg = put_cmd640_reg_vlb; cmd640_key = 0x178; b = get_cmd640_reg(CFR); if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) { @@ -454,7 +447,7 @@ unsigned long flags; spin_lock_irqsave(&ide_lock, flags); - b = get_cmd640_reg(reg); + b = __get_cmd640_reg(reg); if (mode) { /* want prefetch on? */ #if CMD640_PREFETCH_MASKS drive->no_unmask = 1; @@ -468,7 +461,7 @@ drive->io_32bit = 0; b |= prefetch_masks[index]; /* disable prefetch */ } - put_cmd640_reg(reg, b); + __put_cmd640_reg(reg, b); spin_unlock_irqrestore(&ide_lock, flags); } @@ -576,9 +569,9 @@ * and then the active/recovery counts into the DRWTIM reg * (this converts counts of 16 into counts of zero -- okay). */ - setup_count |= get_cmd640_reg(arttim_regs[index]) & 0x3f; - put_cmd640_reg(arttim_regs[index], setup_count); - put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); + setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f; + __put_cmd640_reg(arttim_regs[index], setup_count); + __put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); spin_unlock_irqrestore(&ide_lock, flags); } diff -urN linux-2.5.65-bk2/drivers/ide/pci/cs5520.c linux-2.5.65-bk3/drivers/ide/pci/cs5520.c --- linux-2.5.65-bk2/drivers/ide/pci/cs5520.c Mon Mar 17 13:43:40 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/cs5520.c Mon Mar 31 12:41:40 2003 @@ -65,6 +65,7 @@ { char *p = buffer; unsigned long bmiba = pci_resource_start(bmide_dev, 2); + int len; u8 c0 = 0, c1 = 0; u16 reg16; u32 reg32; @@ -94,7 +95,10 @@ pci_read_config_dword(bmide_dev, 0x68, ®32); p += sprintf(p, "16bit Secondary: %08x\n", reg32); - return p-buffer; + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } #endif @@ -259,9 +263,9 @@ { ata_index_t index; ide_pci_device_t *d = &cyrix_chipsets[id->driver_data]; - - ide_setup_pci_noise(dev, d); - + + ide_setup_pci_noise(dev, d); + /* We must not grab the entire device, it has 'ISA' space in its BARS too and we will freak out other bits of the kernel */ if(pci_enable_device_bars(dev, 1<<2)) @@ -271,15 +275,15 @@ } pci_set_master(dev); pci_set_dma_mask(dev, 0xFFFFFFFF); - init_chipset_cs5520(dev, d->name); - + init_chipset_cs5520(dev, d->name); + index.all = 0xf0f0; /* * Now the chipset is configured we can let the core * do all the device setup for us */ - + ide_pci_setup_ports(dev, d, 1, 14, &index); printk("Index.b %d %d\n", index.b.low, index.b.high); @@ -288,7 +292,7 @@ probe_hwif_init(&ide_hwifs[index.b.low]); if((index.b.high & 0xf0) != 0xf0) probe_hwif_init(&ide_hwifs[index.b.high]); - + MOD_INC_USE_COUNT; return 0; } diff -urN linux-2.5.65-bk2/drivers/ide/pci/hpt34x.c linux-2.5.65-bk3/drivers/ide/pci/hpt34x.c --- linux-2.5.65-bk2/drivers/ide/pci/hpt34x.c Mon Mar 17 13:44:03 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/hpt34x.c Mon Mar 31 12:41:40 2003 @@ -58,7 +58,7 @@ static int hpt34x_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - int i; + int i, len; p += sprintf(p, "\n " "HPT34X Chipset.\n"); @@ -96,7 +96,11 @@ } p += sprintf(p, "\n"); - return p-buffer; /* => must be less than 4k! */ + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } #endif /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */ diff -urN linux-2.5.65-bk2/drivers/ide/pci/hpt366.c linux-2.5.65-bk3/drivers/ide/pci/hpt366.c --- linux-2.5.65-bk2/drivers/ide/pci/hpt366.c Mon Mar 17 13:44:08 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/hpt366.c Mon Mar 31 12:41:40 2003 @@ -85,7 +85,7 @@ char *chipset_nums[] = {"366", "366", "368", "370", "370A", "372", "302", "371", "374" }; - int i; + int i, len; p += sprintf(p, "\n " "HighPoint HPT366/368/370/372/374\n"); @@ -153,8 +153,12 @@ } } p += sprintf(p, "\n"); + + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; - return p-buffer;/* => must be less than 4k! */ + return len > count ? count : len; } #endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ diff -urN linux-2.5.65-bk2/drivers/ide/pci/pdc202xx_new.c linux-2.5.65-bk3/drivers/ide/pci/pdc202xx_new.c --- linux-2.5.65-bk2/drivers/ide/pci/pdc202xx_new.c Mon Mar 17 13:44:22 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/pdc202xx_new.c Mon Mar 31 12:41:40 2003 @@ -77,13 +77,17 @@ static int pdcnew_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - int i; + int i, len; for (i = 0; i < n_pdc202_devs; i++) { struct pci_dev *dev = pdc202_devs[i]; p = pdcnew_info(buffer, dev); } - return p-buffer; /* => must be less than 4k! */ + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } #endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */ diff -urN linux-2.5.65-bk2/drivers/ide/pci/pdc202xx_old.c linux-2.5.65-bk3/drivers/ide/pci/pdc202xx_old.c --- linux-2.5.65-bk2/drivers/ide/pci/pdc202xx_old.c Mon Mar 17 13:44:49 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/pdc202xx_old.c Mon Mar 31 12:41:40 2003 @@ -177,13 +177,17 @@ static int pdc202xx_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - int i; + int i, len; for (i = 0; i < n_pdc202_devs; i++) { struct pci_dev *dev = pdc202_devs[i]; p = pdc202xx_info(buffer, dev); } - return p-buffer; /* => must be less than 4k! */ + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } #endif /* defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) */ diff -urN linux-2.5.65-bk2/drivers/ide/pci/piix.c linux-2.5.65-bk3/drivers/ide/pci/piix.c --- linux-2.5.65-bk2/drivers/ide/pci/piix.c Mon Mar 31 12:41:36 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/piix.c Mon Mar 31 12:41:40 2003 @@ -1,5 +1,5 @@ /* - * linux/drivers/ide/pci/piix.c Version 0.42 January 11, 2003 + * linux/drivers/ide/pci/piix.c Version 0.44 March 20, 2003 * * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer * Copyright (C) 1998-2000 Andre Hedrick @@ -146,7 +146,9 @@ case PCI_DEVICE_ID_INTEL_82801BA_9: case PCI_DEVICE_ID_INTEL_82801CA_10: case PCI_DEVICE_ID_INTEL_82801CA_11: + case PCI_DEVICE_ID_INTEL_82801DB_10: case PCI_DEVICE_ID_INTEL_82801DB_11: + case PCI_DEVICE_ID_INTEL_82801EB_11: case PCI_DEVICE_ID_INTEL_82801E_11: p += sprintf(p, "PIIX4 Ultra 100 "); break; @@ -279,7 +281,9 @@ case PCI_DEVICE_ID_INTEL_82801CA_10: case PCI_DEVICE_ID_INTEL_82801CA_11: case PCI_DEVICE_ID_INTEL_82801E_11: + case PCI_DEVICE_ID_INTEL_82801DB_10: case PCI_DEVICE_ID_INTEL_82801DB_11: + case PCI_DEVICE_ID_INTEL_82801EB_11: mode = 3; break; /* UDMA 66 capable */ @@ -551,7 +555,7 @@ drive->init_speed = 0; - if (id && (id->capability & 1) && drive->autodma) { + if ((id->capability & 1) && drive->autodma) { /* Consult the list of known "bad" drives */ if (hwif->ide_dma_bad_drive(drive)) goto fast_ata_pio; @@ -605,7 +609,9 @@ case PCI_DEVICE_ID_INTEL_82801BA_9: case PCI_DEVICE_ID_INTEL_82801CA_10: case PCI_DEVICE_ID_INTEL_82801CA_11: + case PCI_DEVICE_ID_INTEL_82801DB_10: case PCI_DEVICE_ID_INTEL_82801DB_11: + case PCI_DEVICE_ID_INTEL_82801EB_11: case PCI_DEVICE_ID_INTEL_82801E_11: { unsigned int extra = 0; @@ -794,7 +800,9 @@ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13}, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14}, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_11,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_11, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16}, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_10,PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17}, { 0, }, }; diff -urN linux-2.5.65-bk2/drivers/ide/pci/piix.h linux-2.5.65-bk3/drivers/ide/pci/piix.h --- linux-2.5.65-bk2/drivers/ide/pci/piix.h Mon Mar 17 13:43:46 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/piix.h Mon Mar 31 12:41:40 2003 @@ -251,11 +251,53 @@ .extra = 0, },{ /* 15 */ .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801EB_11, + .name = "ICH5", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 16 */ + .vendor = PCI_VENDOR_ID_INTEL, .device = PCI_DEVICE_ID_INTEL_82801E_11, .name = "C-ICH", .init_setup = init_setup_piix, .init_chipset = init_chipset_piix, .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 17 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DB_10, + .name = "ICH4", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, + .init_hwif = init_hwif_piix, + .init_dma = init_dma_piix, + .channels = 2, + .autodma = AUTODMA, + .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, + .bootable = ON_BOARD, + .extra = 0, + },{ /* 17 */ + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DB_10, + .name = "ICH4", + .init_setup = init_setup_piix, + .init_chipset = init_chipset_piix, + .init_iops = NULL, .init_hwif = init_hwif_piix, .init_dma = init_dma_piix, .channels = 2, diff -urN linux-2.5.65-bk2/drivers/ide/pci/sc1200.c linux-2.5.65-bk3/drivers/ide/pci/sc1200.c --- linux-2.5.65-bk2/drivers/ide/pci/sc1200.c Mon Mar 17 13:44:09 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/sc1200.c Mon Mar 31 12:41:40 2003 @@ -87,6 +87,7 @@ { char *p = buffer; unsigned long bibma = pci_resource_start(bmide_dev, 4); + int len; u8 c0 = 0, c1 = 0; /* @@ -111,7 +112,10 @@ p += sprintf(p, "DMA\n"); p += sprintf(p, "PIO\n"); - return p-buffer; + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } #endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ diff -urN linux-2.5.65-bk2/drivers/ide/pci/serverworks.c linux-2.5.65-bk3/drivers/ide/pci/serverworks.c --- linux-2.5.65-bk2/drivers/ide/pci/serverworks.c Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/serverworks.c Mon Mar 31 12:41:40 2003 @@ -57,7 +57,7 @@ static int svwks_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; - int i; + int i, len; p += sprintf(p, "\n " "ServerWorks OSB4/CSB5/CSB6\n"); @@ -195,7 +195,11 @@ } p += sprintf(p, "\n"); - return p-buffer; /* => must be less than 4k! */ + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } #endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ diff -urN linux-2.5.65-bk2/drivers/ide/pci/siimage.c linux-2.5.65-bk3/drivers/ide/pci/siimage.c --- linux-2.5.65-bk2/drivers/ide/pci/siimage.c Mon Mar 17 13:44:03 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/siimage.c Mon Mar 31 12:41:40 2003 @@ -55,6 +55,7 @@ static int siimage_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; + int len; u16 i; p += sprintf(p, "\n"); @@ -62,7 +63,11 @@ struct pci_dev *dev = siimage_devs[i]; p = print_siimage_get_info(p, dev, i); } - return p-buffer; /* => must be less than 4k! */ + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } #endif /* defined(DISPLAY_SIIMAGE_TIMINGS) && defined(CONFIG_PROC_FS) */ diff -urN linux-2.5.65-bk2/drivers/ide/pci/sis5513.c linux-2.5.65-bk3/drivers/ide/pci/sis5513.c --- linux-2.5.65-bk2/drivers/ide/pci/sis5513.c Mon Mar 17 13:44:06 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/sis5513.c Mon Mar 31 12:41:40 2003 @@ -424,6 +424,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; + int len; u8 reg; u16 reg2, reg3; @@ -494,7 +495,10 @@ p = get_masters_info(p); p = get_slaves_info(p); - return p-buffer; + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } #endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ diff -urN linux-2.5.65-bk2/drivers/ide/pci/slc90e66.c linux-2.5.65-bk3/drivers/ide/pci/slc90e66.c --- linux-2.5.65-bk2/drivers/ide/pci/slc90e66.c Mon Mar 17 13:44:38 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/slc90e66.c Mon Mar 31 12:41:40 2003 @@ -34,8 +34,9 @@ static int slc90e66_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; + int len; unsigned long bibma = pci_resource_start(bmide_dev, 4); - u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; + u16 reg40 = 0, psitre = 0, reg42 = 0, ssitre = 0; u8 c0 = 0, c1 = 0; u8 reg44 = 0, reg47 = 0, reg48 = 0, reg4a = 0, reg4b = 0; @@ -110,7 +111,11 @@ * FIXME.... Add configuration junk data....blah blah...... */ - return p-buffer; /* => must be less than 4k! */ + /* p - buffer must be less than 4k! */ + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } #endif /* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */ diff -urN linux-2.5.65-bk2/drivers/ide/pci/via82cxxx.c linux-2.5.65-bk3/drivers/ide/pci/via82cxxx.c --- linux-2.5.65-bk2/drivers/ide/pci/via82cxxx.c Mon Mar 17 13:43:37 2003 +++ linux-2.5.65-bk3/drivers/ide/pci/via82cxxx.c Mon Mar 31 12:41:40 2003 @@ -140,6 +140,7 @@ uen[4], udma[4], umul[4], active8b[4], recover8b[4]; struct pci_dev *dev = bmide_dev; unsigned int v, u, i; + int len; u16 c, w; u8 t, x; char *p = buffer; @@ -269,7 +270,10 @@ speed[i] / 1000, speed[i] / 100 % 10); /* hoping it is less than 4K... */ - return p - buffer; + len = (p - buffer) - offset; + *addr = buffer + offset; + + return len > count ? count : len; } #endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */ diff -urN linux-2.5.65-bk2/drivers/macintosh/mac_hid.c linux-2.5.65-bk3/drivers/macintosh/mac_hid.c --- linux-2.5.65-bk2/drivers/macintosh/mac_hid.c Mon Mar 17 13:44:42 2003 +++ linux-2.5.65-bk3/drivers/macintosh/mac_hid.c Mon Mar 31 12:41:40 2003 @@ -25,38 +25,56 @@ #if defined(CONFIG_SYSCTL) /* file(s) in /proc/sys/dev/mac_hid */ -ctl_table mac_hid_files[] = -{ - { - DEV_MAC_HID_MOUSE_BUTTON_EMULATION, - "mouse_button_emulation", &mouse_emulate_buttons, sizeof(int), - 0644, NULL, &proc_dointvec - }, - { - DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE, - "mouse_button2_keycode", &mouse_button2_keycode, sizeof(int), - 0644, NULL, &proc_dointvec - }, - { - DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE, - "mouse_button3_keycode", &mouse_button3_keycode, sizeof(int), - 0644, NULL, &proc_dointvec - }, - { 0 } +ctl_table mac_hid_files[] = { + { + .ctl_name = DEV_MAC_HID_MOUSE_BUTTON_EMULATION, + .procname = "mouse_button_emulation", + .data = &mouse_emulate_buttons, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE, + .procname = "mouse_button2_keycode", + .data = &mouse_button2_keycode, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { + .ctl_name = DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE, + .procname = "mouse_button3_keycode", + .data = &mouse_button3_keycode, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { .ctl_name = 0 } }; /* dir in /proc/sys/dev */ -ctl_table mac_hid_dir[] = -{ - { DEV_MAC_HID, "mac_hid", NULL, 0, 0555, mac_hid_files }, - { 0 } +ctl_table mac_hid_dir[] = { + { + .ctl_name = DEV_MAC_HID, + .procname = "mac_hid", + .maxlen = 0, + .mode = 0555, + .child = mac_hid_files, + }, + { .ctl_name = 0 } }; /* /proc/sys/dev itself, in case that is not there yet */ -ctl_table mac_hid_root_dir[] = -{ - { CTL_DEV, "dev", NULL, 0, 0555, mac_hid_dir }, - { 0 } +ctl_table mac_hid_root_dir[] = { + { + .ctl_name = CTL_DEV, + .procname = "dev", + .maxlen = 0, + .mode = 0555, + .child = mac_hid_dir, + }, + { .ctl_name = 0 } }; static struct ctl_table_header *mac_hid_sysctl_header; diff -urN linux-2.5.65-bk2/drivers/media/dvb/dvb-core/Kconfig linux-2.5.65-bk3/drivers/media/dvb/dvb-core/Kconfig --- linux-2.5.65-bk2/drivers/media/dvb/dvb-core/Kconfig Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/drivers/media/dvb/dvb-core/Kconfig Mon Mar 31 12:41:40 2003 @@ -5,13 +5,3 @@ DVB core utility functions for device handling, software fallbacks etc. Say Y when you have a DVB card and want to use it. If unsure say N. - -config DVB_DEVFS_ONLY - bool "devfs only" - depends on DVB_CORE=y && DEVFS_FS - help - Drop support for old major/minor device scheme and support only devfs - systems. This saves some code. - - If unsure say N. - diff -urN linux-2.5.65-bk2/drivers/media/dvb/dvb-core/dvbdev.c linux-2.5.65-bk3/drivers/media/dvb/dvb-core/dvbdev.c --- linux-2.5.65-bk2/drivers/media/dvb/dvb-core/dvbdev.c Mon Mar 17 13:43:46 2003 +++ linux-2.5.65-bk3/drivers/media/dvb/dvb-core/dvbdev.c Mon Mar 31 12:41:40 2003 @@ -21,8 +21,6 @@ * */ -/*#define CONFIG_DVB_DEVFS_ONLY 1*/ - #include #include #include @@ -56,17 +54,8 @@ }; -#ifdef CONFIG_DVB_DEVFS_ONLY - - #define DVB_MAX_IDS ~0 - #define nums2minor(num,type,id) 0 - #define DVB_DEVFS_FLAGS (DEVFS_FL_DEFAULT|DEVFS_FL_AUTO_DEVNUM) - -#else - - #define DVB_MAX_IDS 4 - #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) - #define DVB_DEVFS_FLAGS (DEVFS_FL_DEFAULT) +#define DVB_MAX_IDS 4 +#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) static @@ -234,8 +223,7 @@ sprintf(name, "%s%d", dnames[type], id); dvbdev->devfs_handle = devfs_register(adap->devfs_handle, name, - DVB_DEVFS_FLAGS, - DVB_MAJOR, + 0, DVB_MAJOR, nums2minor(adap->num, type, id), S_IFCHR | S_IRUSR | S_IWUSR, dvbdev->fops, dvbdev); diff -urN linux-2.5.65-bk2/drivers/media/radio/miropcm20-rds-core.c linux-2.5.65-bk3/drivers/media/radio/miropcm20-rds-core.c --- linux-2.5.65-bk2/drivers/media/radio/miropcm20-rds-core.c Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/drivers/media/radio/miropcm20-rds-core.c Mon Mar 31 12:41:40 2003 @@ -13,8 +13,6 @@ * RDS support for MiroSound PCM20 radio */ -#define _NO_VERSION_ - #include #include #include diff -urN linux-2.5.65-bk2/drivers/media/video/bttv-cards.c linux-2.5.65-bk3/drivers/media/video/bttv-cards.c --- linux-2.5.65-bk2/drivers/media/video/bttv-cards.c Mon Mar 17 13:44:05 2003 +++ linux-2.5.65-bk3/drivers/media/video/bttv-cards.c Mon Mar 31 12:41:40 2003 @@ -24,8 +24,6 @@ */ -#define __NO_VERSION__ 1 - #include #include #include diff -urN linux-2.5.65-bk2/drivers/media/video/bttv-if.c linux-2.5.65-bk3/drivers/media/video/bttv-if.c --- linux-2.5.65-bk2/drivers/media/video/bttv-if.c Mon Mar 17 13:43:40 2003 +++ linux-2.5.65-bk3/drivers/media/video/bttv-if.c Mon Mar 31 12:41:40 2003 @@ -25,8 +25,6 @@ */ -#define __NO_VERSION__ 1 - #include #include #include diff -urN linux-2.5.65-bk2/drivers/media/video/bttv-risc.c linux-2.5.65-bk3/drivers/media/video/bttv-risc.c --- linux-2.5.65-bk2/drivers/media/video/bttv-risc.c Mon Mar 17 13:44:06 2003 +++ linux-2.5.65-bk3/drivers/media/video/bttv-risc.c Mon Mar 31 12:41:40 2003 @@ -23,8 +23,6 @@ */ -#define __NO_VERSION__ 1 - #include #include #include diff -urN linux-2.5.65-bk2/drivers/media/video/cpia.c linux-2.5.65-bk3/drivers/media/video/cpia.c --- linux-2.5.65-bk2/drivers/media/video/cpia.c Mon Mar 17 13:44:20 2003 +++ linux-2.5.65-bk3/drivers/media/video/cpia.c Mon Mar 31 12:41:40 2003 @@ -23,7 +23,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* #define _CPIA_DEBUG_ define for verbose debug output */ +/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ +/* #define _CPIA_DEBUG_ 1 */ + #include #include @@ -1796,7 +1798,7 @@ retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data); if (retval) - LOG("%x - failed\n", command); + DBG("%x - failed\n", command); return retval; } @@ -2174,7 +2176,7 @@ } if (ll == 1) { if (*ibuf != EOL) { - LOG("EOL not found giving up after %d/%d" + DBG("EOL not found giving up after %d/%d" " bytes\n", origsize-size, origsize); return -1; } @@ -3158,7 +3160,8 @@ static void put_cam(struct cpia_camera_ops* ops) { - module_put(ops->owner); + if (ops->owner) + module_put(ops->owner); } /* ------------------------- V4L interface --------------------- */ @@ -3173,16 +3176,15 @@ return -ENODEV; } + if (cam->open_count > 0) { + DBG("Camera already open\n"); + return -EBUSY; + } + if (!try_module_get(cam->ops->owner)) return -ENODEV; down(&cam->busy_lock); - err = -EBUSY; - if (cam->open_count > 0) { - DBG("Camera already open\n"); - goto oops; - } - err = -ENOMEM; if (!cam->raw_image) { cam->raw_image = rvmalloc(CPIA_MAX_IMAGE_SIZE); @@ -3206,10 +3208,11 @@ cam->ops->close(cam->lowlevel_data); goto oops; } - - if(signal_pending(current)) - return -EINTR; + err = -EINTR; + if(signal_pending(current)) + goto oops; + /* Set ownership of /proc/cpia/videoX to current user */ if(cam->proc_entry) cam->proc_entry->uid = current->uid; @@ -3451,6 +3454,14 @@ cam->params.colourParams.contrast = 80; } + /* Adjust flicker control if necessary */ + if(cam->params.flickerControl.allowableOverExposure < 0) + cam->params.flickerControl.allowableOverExposure = + -find_over_exposure(cam->params.colourParams.brightness); + if(cam->params.flickerControl.flickerMode != 0) + cam->cmd_queue |= COMMAND_SETFLICKERCTRL; + + /* queue command to update camera */ cam->cmd_queue |= COMMAND_SETCOLOURPARAMS; up(&cam->param_lock); @@ -3600,7 +3611,7 @@ { int *frame = arg; - //DBG("VIDIOCSYNC: %d\n", frame); + //DBG("VIDIOCSYNC: %d\n", *frame); if (*frame<0 || *frame >= FRAME_NUM) { retval = -EINVAL; @@ -3628,52 +3639,53 @@ } case VIDIOCGCAPTURE: + { + struct video_capture *vc = arg; + DBG("VIDIOCGCAPTURE\n"); - if (copy_to_user(arg, &cam->vc, sizeof(struct video_capture))) - retval = -EFAULT; + + *vc = cam->vc; + break; + } case VIDIOCSCAPTURE: { - struct video_capture vc; + struct video_capture *vc = arg; DBG("VIDIOCSCAPTURE\n"); - if (copy_from_user(&vc, arg, sizeof(vc))) { - retval = -EFAULT; - break; - } - if (vc.decimation != 0) { /* How should this be used? */ + if (vc->decimation != 0) { /* How should this be used? */ retval = -EINVAL; break; } - if (vc.flags != 0) { /* Even/odd grab not supported */ + if (vc->flags != 0) { /* Even/odd grab not supported */ retval = -EINVAL; break; } /* Clip to the resolution we can set for the ROI (every 8 columns and 4 rows) */ - vc.x = vc.x & ~(__u32)7; - vc.y = vc.y & ~(__u32)3; - vc.width = vc.width & ~(__u32)7; - vc.height = vc.height & ~(__u32)3; - - if(vc.width == 0 || vc.height == 0 || - vc.x + vc.width > cam->vw.width || - vc.y + vc.height > cam->vw.height) { + vc->x = vc->x & ~(__u32)7; + vc->y = vc->y & ~(__u32)3; + vc->width = vc->width & ~(__u32)7; + vc->height = vc->height & ~(__u32)3; + + if(vc->width == 0 || vc->height == 0 || + vc->x + vc->width > cam->vw.width || + vc->y + vc->height > cam->vw.height) { retval = -EINVAL; break; } - DBG("%d,%d/%dx%d\n", vc.x,vc.y,vc.width, vc.height); + DBG("%d,%d/%dx%d\n", vc->x,vc->y,vc->width, vc->height); down(&cam->param_lock); - cam->vc.x = vc.x; - cam->vc.y = vc.y; - cam->vc.width = vc.width; - cam->vc.height = vc.height; + cam->vc.x = vc->x; + cam->vc.y = vc->y; + cam->vc.width = vc->width; + cam->vc.height = vc->height; set_vw_size(cam); cam->cmd_queue |= COMMAND_SETFORMAT; @@ -3688,16 +3700,20 @@ case VIDIOCGUNIT: { - struct video_unit vu; - vu.video = cam->vdev.minor; - vu.vbi = VIDEO_NO_UNIT; - vu.radio = VIDEO_NO_UNIT; - vu.audio = VIDEO_NO_UNIT; - vu.teletext = VIDEO_NO_UNIT; + struct video_unit *vu = arg; + + DBG("VIDIOCGUNIT\n"); + + vu->video = cam->vdev.minor; + vu->vbi = VIDEO_NO_UNIT; + vu->radio = VIDEO_NO_UNIT; + vu->audio = VIDEO_NO_UNIT; + vu->teletext = VIDEO_NO_UNIT; + break; } - + /* pointless to implement overlay with this camera */ case VIDIOCCAPTURE: case VIDIOCGFBUF: @@ -3728,12 +3744,13 @@ return video_usercopy(inode, file, cmd, arg, cpia_do_ioctl); } + /* FIXME */ static int cpia_mmap(struct file *file, struct vm_area_struct *vma) { struct video_device *dev = file->private_data; unsigned long start = vma->vm_start; - unsigned long size = vma->vm_end-vma->vm_start; + unsigned long size = vma->vm_end - vma->vm_start; unsigned long page, pos; struct cam_data *cam = dev->priv; int retval; @@ -3956,9 +3973,6 @@ printk(KERN_DEBUG "video_register_device failed\n"); return NULL; } -#ifdef CONFIG_PROC_FS - create_proc_cpia_cam(camera); -#endif /* get version information from camera: open/reset/close */ @@ -3975,6 +3989,10 @@ /* close cpia */ camera->ops->close(camera->lowlevel_data); +#ifdef CONFIG_PROC_FS + create_proc_cpia_cam(camera); +#endif + printk(KERN_INFO " CPiA Version: %d.%02d (%d.%d)\n", camera->params.version.firmwareVersion, camera->params.version.firmwareRevision, @@ -3997,6 +4015,7 @@ DBG("unregistering video\n"); video_unregister_device(&cam->vdev); if (cam->open_count) { + put_cam(cam->ops); DBG("camera open -- setting ops to NULL\n"); cam->ops = NULL; } @@ -4019,9 +4038,6 @@ proc_cpia_create(); #endif -#ifdef CONFIG_VIDEO_CPIA_PP - cpia_pp_init(); -#endif #ifdef CONFIG_KMOD #ifdef CONFIG_VIDEO_CPIA_PP_MODULE request_module("cpia_pp"); @@ -4031,6 +4047,10 @@ request_module("cpia_usb"); #endif #endif /* CONFIG_KMOD */ + +#ifdef CONFIG_VIDEO_CPIA_PP + cpia_pp_init(); +#endif #ifdef CONFIG_VIDEO_CPIA_USB cpia_usb_init(); #endif diff -urN linux-2.5.65-bk2/drivers/media/video/cpia.h linux-2.5.65-bk3/drivers/media/video/cpia.h --- linux-2.5.65-bk2/drivers/media/video/cpia.h Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/drivers/media/video/cpia.h Mon Mar 31 12:41:40 2003 @@ -27,12 +27,16 @@ */ #define CPIA_MAJ_VER 1 -#define CPIA_MIN_VER 2 -#define CPIA_PATCH_VER 2 +#define CPIA_MIN_VER 2 +#define CPIA_PATCH_VER 3 -#define CPIA_PP_MAJ_VER 1 -#define CPIA_PP_MIN_VER 2 -#define CPIA_PP_PATCH_VER 2 +#define CPIA_PP_MAJ_VER CPIA_MAJ_VER +#define CPIA_PP_MIN_VER CPIA_MIN_VER +#define CPIA_PP_PATCH_VER CPIA_PATCH_VER + +#define CPIA_USB_MAJ_VER CPIA_MAJ_VER +#define CPIA_USB_MIN_VER CPIA_MIN_VER +#define CPIA_USB_PATCH_VER CPIA_PATCH_VER #define CPIA_MAX_FRAME_SIZE_UNALIGNED (352 * 288 * 4) /* CIF at RGB32 */ #define CPIA_MAX_FRAME_SIZE ((CPIA_MAX_FRAME_SIZE_UNALIGNED + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) /* align above to PAGE_SIZE */ diff -urN linux-2.5.65-bk2/drivers/media/video/cpia_pp.c linux-2.5.65-bk3/drivers/media/video/cpia_pp.c --- linux-2.5.65-bk2/drivers/media/video/cpia_pp.c Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/drivers/media/video/cpia_pp.c Mon Mar 31 12:41:40 2003 @@ -22,6 +22,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ +/* #define _CPIA_DEBUG_ 1 */ + #include #include @@ -34,6 +37,7 @@ #include #include #include +#include #include @@ -49,68 +53,10 @@ static int cpia_pp_streamRead(void *privdata, u8 *buffer, int noblock); static int cpia_pp_close(void *privdata); -#define ABOUT "Parallel port driver for Vision CPiA based cameras" -/* IEEE 1284 Compatiblity Mode signal names */ -#define nStrobe PARPORT_CONTROL_STROBE /* inverted */ -#define nAutoFd PARPORT_CONTROL_AUTOFD /* inverted */ -#define nInit PARPORT_CONTROL_INIT -#define nSelectIn PARPORT_CONTROL_SELECT -#define IntrEnable PARPORT_CONTROL_INTEN /* normally zero for no IRQ */ -#define DirBit PARPORT_CONTROL_DIRECTION /* 0 = Forward, 1 = Reverse */ - -#define nFault PARPORT_STATUS_ERROR -#define Select PARPORT_STATUS_SELECT -#define PError PARPORT_STATUS_PAPEROUT -#define nAck PARPORT_STATUS_ACK -#define Busy PARPORT_STATUS_BUSY /* inverted */ - -/* some more */ -#define HostClk nStrobe -#define HostAck nAutoFd -#define nReverseRequest nInit -#define Active_1284 nSelectIn -#define nPeriphRequest nFault -#define XFlag Select -#define nAckReverse PError -#define PeriphClk nAck -#define PeriphAck Busy - -/* these can be used to correct for the inversion on some bits */ -#define STATUS_INVERSION_MASK (Busy) -#define CONTROL_INVERSION_MASK (nStrobe|nAutoFd|nSelectIn) - -#define ECR_empty 0x01 -#define ECR_full 0x02 -#define ECR_serviceIntr 0x04 -#define ECR_dmaEn 0x08 -#define ECR_nErrIntrEn 0x10 - -#define ECR_mode_mask 0xE0 -#define ECR_SPP_mode 0x00 -#define ECR_PS2_mode 0x20 -#define ECR_FIFO_mode 0x40 -#define ECR_ECP_mode 0x60 - -#define ECP_FIFO_SIZE 16 -#define DMA_BUFFER_SIZE PAGE_SIZE - /* for 16bit DMA make sure DMA_BUFFER_SIZE is 16 bit aligned */ -#define PARPORT_CHUNK_SIZE PAGE_SIZE/* >=2.3.x */ - /* we read this many bytes at once */ - -#define GetECRMasked(port,mask) (parport_read_econtrol(port) & (mask)) -#define GetStatus(port) ((parport_read_status(port)^STATUS_INVERSION_MASK)&(0xf8)) -#define SetStatus(port,val) parport_write_status(port,(val)^STATUS_INVERSION_MASK) -#define GetControl(port) ((parport_read_control(port)^CONTROL_INVERSION_MASK)&(0x3f)) -#define SetControl(port,val) parport_write_control(port,(val)^CONTROL_INVERSION_MASK) - -#define GetStatusMasked(port,mask) (GetStatus(port) & (mask)) -#define GetControlMasked(port,mask) (GetControl(port) & (mask)) -#define SetControlMasked(port,mask) SetControl(port,GetControl(port) | (mask)); -#define ClearControlMasked(port,mask) SetControl(port,GetControl(port)&~(mask)); -#define FrobControlBit(port,mask,value) SetControl(port,(GetControl(port)&~(mask))|((value)&(mask))); +#define ABOUT "Parallel port driver for Vision CPiA based cameras" -#define PACKET_LENGTH 8 +#define PACKET_LENGTH 8 /* Magic numbers for defining port-device mappings */ #define PPCPIA_PARPORT_UNSPEC -4 @@ -162,30 +108,7 @@ }; static LIST_HEAD(cam_list); -static spinlock_t cam_list_lock_pp = SPIN_LOCK_UNLOCKED; - -#ifdef _CPIA_DEBUG_ -#define DEB_PORT(port) { \ -u8 controll = GetControl(port); \ -u8 statusss = GetStatus(port); \ -DBG("nsel %c per %c naut %c nstrob %c nak %c busy %c nfaul %c sel %c init %c dir %c\n",\ -((controll & nSelectIn) ? 'U' : 'D'), \ -((statusss & PError) ? 'U' : 'D'), \ -((controll & nAutoFd) ? 'U' : 'D'), \ -((controll & nStrobe) ? 'U' : 'D'), \ -((statusss & nAck) ? 'U' : 'D'), \ -((statusss & Busy) ? 'U' : 'D'), \ -((statusss & nFault) ? 'U' : 'D'), \ -((statusss & Select) ? 'U' : 'D'), \ -((controll & nInit) ? 'U' : 'D'), \ -((controll & DirBit) ? 'R' : 'F') \ -); } -#else -#define DEB_PORT(port) {} -#endif - -#define WHILE_OUT_TIMEOUT (HZ/10) -#define DMA_TIMEOUT 10*HZ +static spinlock_t cam_list_lock_pp; /* FIXME */ static void cpia_parport_enable_irq( struct parport *port ) { @@ -200,6 +123,205 @@ return; } +/* Special CPiA PPC modes: These are invoked by using the 1284 Extensibility + * Link Flag during negotiation */ +#define UPLOAD_FLAG 0x08 +#define NIBBLE_TRANSFER 0x01 +#define ECP_TRANSFER 0x03 + +#define PARPORT_CHUNK_SIZE PAGE_SIZE + + +/**************************************************************************** + * + * CPiA-specific low-level parport functions for nibble uploads + * + ***************************************************************************/ +/* CPiA nonstandard "Nibble" mode (no nDataAvail signal after each byte). */ +/* The standard kernel parport_ieee1284_read_nibble() fails with the CPiA... */ + +static size_t cpia_read_nibble (struct parport *port, + void *buffer, size_t len, + int flags) +{ + /* adapted verbatim, with one change, from + parport_ieee1284_read_nibble() in drivers/parport/ieee1284-ops.c */ + + unsigned char *buf = buffer; + int i; + unsigned char byte = 0; + + len *= 2; /* in nibbles */ + for (i=0; i < len; i++) { + unsigned char nibble; + + /* The CPiA firmware suppresses the use of nDataAvail (nFault LO) + * after every second nibble to signal that more + * data is available. (the total number of Bytes that + * should be sent is known; if too few are received, an error + * will be recorded after a timeout). + * This is incompatible with parport_ieee1284_read_nibble(), + * which expects to find nFault LO after every second nibble. + */ + + /* Solution: modify cpia_read_nibble to only check for + * nDataAvail before the first nibble is sent. + */ + + /* Does the error line indicate end of data? */ + if (((i /*& 1*/) == 0) && + (parport_read_status(port) & PARPORT_STATUS_ERROR)) { + port->physport->ieee1284.phase = IEEE1284_PH_HBUSY_DNA; + DBG("%s: No more nibble data (%d bytes)\n", + port->name, i/2); + + /* Go to reverse idle phase. */ + parport_frob_control (port, + PARPORT_CONTROL_AUTOFD, + PARPORT_CONTROL_AUTOFD); + port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE; + break; + } + + /* Event 7: Set nAutoFd low. */ + parport_frob_control (port, + PARPORT_CONTROL_AUTOFD, + PARPORT_CONTROL_AUTOFD); + + /* Event 9: nAck goes low. */ + port->ieee1284.phase = IEEE1284_PH_REV_DATA; + if (parport_wait_peripheral (port, + PARPORT_STATUS_ACK, 0)) { + /* Timeout -- no more data? */ + DBG("%s: Nibble timeout at event 9 (%d bytes)\n", + port->name, i/2); + parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); + break; + } + + + /* Read a nibble. */ + nibble = parport_read_status (port) >> 3; + nibble &= ~8; + if ((nibble & 0x10) == 0) + nibble |= 8; + nibble &= 0xf; + + /* Event 10: Set nAutoFd high. */ + parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); + + /* Event 11: nAck goes high. */ + if (parport_wait_peripheral (port, + PARPORT_STATUS_ACK, + PARPORT_STATUS_ACK)) { + /* Timeout -- no more data? */ + DBG("%s: Nibble timeout at event 11\n", + port->name); + break; + } + + if (i & 1) { + /* Second nibble */ + byte |= nibble << 4; + *buf++ = byte; + } else + byte = nibble; + } + + i /= 2; /* i is now in bytes */ + + if (i == len) { + /* Read the last nibble without checking data avail. */ + port = port->physport; + if (parport_read_status (port) & PARPORT_STATUS_ERROR) + port->ieee1284.phase = IEEE1284_PH_HBUSY_DNA; + else + port->ieee1284.phase = IEEE1284_PH_HBUSY_DAVAIL; + } + + return i; +} + +/* CPiA nonstandard "Nibble Stream" mode (2 nibbles per cycle, instead of 1) + * (See CPiA Data sheet p. 31) + * + * "Nibble Stream" mode used by CPiA for uploads to non-ECP ports is a + * nonstandard variant of nibble mode which allows the same (mediocre) + * data flow of 8 bits per cycle as software-enabled ECP by TRISTATE-capable + * parallel ports, but works also for non-TRISTATE-capable ports. + * (Standard nibble mode only send 4 bits per cycle) + * + */ + +static size_t cpia_read_nibble_stream(struct parport *port, + void *buffer, size_t len, + int flags) +{ + int i; + unsigned char *buf = buffer; + int endseen = 0; + + for (i=0; i < len; i++) { + unsigned char nibble[2], byte = 0; + int j; + + /* Image Data is complete when 4 consecutive EOI bytes (0xff) are seen */ + if (endseen > 3 ) + break; + + /* Event 7: Set nAutoFd low. */ + parport_frob_control (port, + PARPORT_CONTROL_AUTOFD, + PARPORT_CONTROL_AUTOFD); + + /* Event 9: nAck goes low. */ + port->ieee1284.phase = IEEE1284_PH_REV_DATA; + if (parport_wait_peripheral (port, + PARPORT_STATUS_ACK, 0)) { + /* Timeout -- no more data? */ + DBG("%s: Nibble timeout at event 9 (%d bytes)\n", + port->name, i/2); + parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); + break; + } + + /* Read lower nibble */ + nibble[0] = parport_read_status (port) >>3; + + /* Event 10: Set nAutoFd high. */ + parport_frob_control (port, PARPORT_CONTROL_AUTOFD, 0); + + /* Event 11: nAck goes high. */ + if (parport_wait_peripheral (port, + PARPORT_STATUS_ACK, + PARPORT_STATUS_ACK)) { + /* Timeout -- no more data? */ + DBG("%s: Nibble timeout at event 11\n", + port->name); + break; + } + + /* Read upper nibble */ + nibble[1] = parport_read_status (port) >>3; + + /* reassemble the byte */ + for (j = 0; j < 2 ; j++ ) { + nibble[j] &= ~8; + if ((nibble[j] & 0x10) == 0) + nibble[j] |= 8; + nibble[j] &= 0xf; + } + byte = (nibble[0] |(nibble[1] << 4)); + *buf++ = byte; + + if(byte == EOI) + endseen++; + else + endseen = 0; + } + return i; +} + /**************************************************************************** * * EndTransferMode @@ -219,20 +341,25 @@ { int retry; - /* After some commands the camera needs extra time before - * it will respond again, so we try up to 3 times */ - for(retry=0; retry<3; ++retry) { + /* The CPiA uses ECP protocol for Downloads from the Host to the camera. + * This will be software-emulated if ECP hardware is not present + */ + + /* the usual camera maximum response time is 10ms, but after receiving + * some commands, it needs up to 40ms. (Data Sheet p. 32)*/ + + for(retry = 0; retry < 4; ++retry) { if(!parport_negotiate(cam->port, IEEE1284_MODE_ECP)) { break; } + mdelay(10); } - if(retry == 3) { - DBG("Unable to negotiate ECP mode\n"); + if(retry == 4) { + DBG("Unable to negotiate IEEE1284 ECP Download mode\n"); return -1; } return 0; } - /**************************************************************************** * * ReverseSetup @@ -241,24 +368,35 @@ static int ReverseSetup(struct pp_cam_entry *cam, int extensibility) { int retry; - int mode = IEEE1284_MODE_ECP; - if(extensibility) mode = 8|3|IEEE1284_EXT_LINK; + int upload_mode, mode = IEEE1284_MODE_ECP; + int transfer_mode = ECP_TRANSFER; - /* After some commands the camera needs extra time before - * it will respond again, so we try up to 3 times */ - for(retry=0; retry<3; ++retry) { + if (!(cam->port->modes & PARPORT_MODE_ECP) && + !(cam->port->modes & PARPORT_MODE_TRISTATE)) { + mode = IEEE1284_MODE_NIBBLE; + transfer_mode = NIBBLE_TRANSFER; + } + + upload_mode = mode; + if(extensibility) mode = UPLOAD_FLAG|transfer_mode|IEEE1284_EXT_LINK; + + /* the usual camera maximum response time is 10ms, but after + * receiving some commands, it needs up to 40ms. */ + + for(retry = 0; retry < 4; ++retry) { if(!parport_negotiate(cam->port, mode)) { break; } + mdelay(10); } - if(retry == 3) { + if(retry == 4) { if(extensibility) - DBG("Unable to negotiate extensibility mode\n"); + DBG("Unable to negotiate upload extensibility mode\n"); else - DBG("Unable to negotiate ECP mode\n"); + DBG("Unable to negotiate upload mode\n"); return -1; } - if(extensibility) cam->port->ieee1284.mode = IEEE1284_MODE_ECP; + if(extensibility) cam->port->ieee1284.mode = upload_mode; return 0; } @@ -296,14 +434,21 @@ static int ReadPacket(struct pp_cam_entry *cam, u8 *packet, size_t size) { int retval=0; + if (packet == NULL) { return -EINVAL; } if (ReverseSetup(cam, 0)) { return -EIO; } - if(parport_read(cam->port, packet, size) != size) { - retval = -EIO; + + /* support for CPiA variant nibble reads */ + if(cam->port->ieee1284.mode == IEEE1284_MODE_NIBBLE) { + if(cpia_read_nibble(cam->port, packet, size, 0) != size) + retval = -EIO; + } else { + if(parport_read(cam->port, packet, size) != size) + retval = -EIO; } EndTransferMode(cam); return retval; @@ -347,11 +492,29 @@ * cpia_pp_streamRead * ***************************************************************************/ +static int cpia_pp_read(struct parport *port, u8 *buffer, int len) +{ + int bytes_read; + + /* support for CPiA variant "nibble stream" reads */ + if(port->ieee1284.mode == IEEE1284_MODE_NIBBLE) + bytes_read = cpia_read_nibble_stream(port,buffer,len,0); + else { + int new_bytes; + for(bytes_read=0; bytes_readport, buffer, CPIA_MAX_IMAGE_SIZE ); - - EndTransferMode(cam); - DBG("read %d bytes\n", read_bytes); - if( read_bytes<0) return -EIO; endseen = 0; - for( i=0; i3 ) { - cam->image_complete=1; - DBG("endseen at %d bytes\n", i); - } + block_size = PARPORT_CHUNK_SIZE; + while( !cam->image_complete ) { + cond_resched(); + + new_bytes = cpia_pp_read(cam->port, buffer, block_size ); + if( new_bytes <= 0 ) { + break; + } + i=-1; + while(++iimage_complete=1; + break; + } + if( CPIA_MAX_IMAGE_SIZE-read_bytes <= PARPORT_CHUNK_SIZE ) { + block_size=CPIA_MAX_IMAGE_SIZE-read_bytes; + } + } + EndTransferMode(cam); return cam->image_complete ? read_bytes : -EIO; } - /**************************************************************************** * * cpia_pp_transferCmd @@ -530,9 +702,8 @@ struct pp_cam_entry *cam; struct cam_data *cpia; - if (!(port->modes & PARPORT_MODE_ECP) && - !(port->modes & PARPORT_MODE_TRISTATE)) { - LOG("port is not ECP capable\n"); + if (!(port->modes & PARPORT_MODE_PCSPP)) { + LOG("port is not supported by CPiA driver\n"); return -ENXIO; } @@ -575,29 +746,33 @@ static void cpia_pp_detach (struct parport *port) { struct list_head *tmp; - struct cam_data *cpia; + struct cam_data *cpia = NULL; struct pp_cam_entry *cam; spin_lock( &cam_list_lock_pp ); list_for_each (tmp, &cam_list) { cpia = list_entry(tmp, struct cam_data, cam_data_list); - cam = cpia->lowlevel_data; + cam = (struct pp_cam_entry *) cpia->lowlevel_data; if (cam && cam->port->number == port->number) { list_del(&cpia->cam_data_list); - cpia_unregister_camera(cpia); - - if(cam->open_count > 0) { - cpia_pp_close(cam); - } - - parport_unregister_device(cam->pdev); - - kfree(cam); - cpia->lowlevel_data = NULL; break; } + cpia = NULL; } spin_unlock( &cam_list_lock_pp ); + + if (!cpia) { + DBG("cpia_pp_detach failed to find cam_data in cam_list\n"); + return; + } + + cam = (struct pp_cam_entry *) cpia->lowlevel_data; + cpia_unregister_camera(cpia); + if(cam->open_count > 0) + cpia_pp_close(cam); + parport_unregister_device(cam->pdev); + cpia->lowlevel_data = NULL; + kfree(cam); } static void cpia_pp_attach (struct parport *port) @@ -645,11 +820,12 @@ return 0; } + spin_lock_init( &cam_list_lock_pp ); + if (parport_register_driver (&cpia_pp_driver)) { LOG ("unable to register with parport\n"); return -EIO; } - return 0; } diff -urN linux-2.5.65-bk2/drivers/media/video/cpia_usb.c linux-2.5.65-bk3/drivers/media/video/cpia_usb.c --- linux-2.5.65-bk2/drivers/media/video/cpia_usb.c Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/drivers/media/video/cpia_usb.c Mon Mar 31 12:41:40 2003 @@ -21,11 +21,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* define _CPIA_DEBUG_ for verbose debug output (see cpia.h) */ +/* #define _CPIA_DEBUG_ 1 */ + #include #include #include #include -#include #include #include #include @@ -105,7 +107,7 @@ }; static LIST_HEAD(cam_list); -static spinlock_t cam_list_lock_usb = SPIN_LOCK_UNLOCKED; +static spinlock_t cam_list_lock_usb; static void cpia_usb_complete(struct urb *urb, struct pt_regs *regs) { @@ -464,12 +466,14 @@ { struct usb_cpia *ucpia = (struct usb_cpia *) privdata; - ucpia->open = 0; + if(!ucpia) + return -ENODEV; - cpia_usb_free_resources(ucpia, 1); + ucpia->open = 0; - if (!ucpia->present) - kfree(ucpia); + /* ucpia->present = 0 protects against trying to reset the + * alt setting if camera is physically disconnected while open */ + cpia_usb_free_resources(ucpia, ucpia->present); return 0; } @@ -565,7 +569,7 @@ vfree(ucpia->buffers[0]); ucpia->buffers[0] = NULL; fail_alloc_0: - + kfree(ucpia); return -EIO; } @@ -588,9 +592,6 @@ .id_table = cpia_id_table, }; -/* don't use dev, it may be NULL! (see usb_cpia_cleanup) */ -/* _disconnect from usb_cpia_cleanup is not necessary since usb_deregister */ -/* will do it for us as well as passing a udev structure - jerdfelt */ static void cpia_disconnect(struct usb_interface *intf) { struct cam_data *cam = usb_get_intfdata(intf); @@ -606,12 +607,11 @@ list_del(&cam->cam_data_list); spin_unlock( &cam_list_lock_usb ); - /* Don't even try to reset the altsetting if we're disconnected */ - cpia_usb_free_resources(ucpia, 0); - ucpia->present = 0; cpia_unregister_camera(cam); + if(ucpia->open) + cpia_usb_close(cam->lowlevel_data); ucpia->curbuff->status = FRAME_ERROR; @@ -639,29 +639,25 @@ ucpia->buffers[0] = NULL; } - if (!ucpia->open) { - kfree(ucpia); - cam->lowlevel_data = NULL; - } + cam->lowlevel_data = NULL; + kfree(ucpia); } static int __init usb_cpia_init(void) { + printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT, + CPIA_USB_MAJ_VER,CPIA_USB_MIN_VER,CPIA_USB_PATCH_VER); + + spin_lock_init(&cam_list_lock_usb); return usb_register(&cpia_driver); } static void __exit usb_cpia_cleanup(void) { -/* - struct cam_data *cam; - - while ((cam = cam_list) != NULL) - cpia_disconnect(NULL, cam); -*/ - usb_deregister(&cpia_driver); } module_init (usb_cpia_init); module_exit (usb_cpia_cleanup); + diff -urN linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-i2c.c linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-i2c.c --- linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-i2c.c Mon Mar 17 13:43:43 2003 +++ linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-i2c.c Mon Mar 31 12:41:40 2003 @@ -19,8 +19,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define __NO_VERSION__ 1 - #include #include #include diff -urN linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-oss.c linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-oss.c --- linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-oss.c Mon Mar 17 13:44:06 2003 +++ linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-oss.c Mon Mar 31 12:41:40 2003 @@ -19,8 +19,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define __NO_VERSION__ 1 - #include #include #include diff -urN linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-ts.c linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-ts.c --- linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-ts.c Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-ts.c Mon Mar 31 12:41:40 2003 @@ -19,8 +19,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define __NO_VERSION__ 1 - #include #include #include diff -urN linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-tvaudio.c linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-tvaudio.c --- linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-tvaudio.c Mon Mar 17 13:43:37 2003 +++ linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-tvaudio.c Mon Mar 31 12:41:40 2003 @@ -19,8 +19,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define __NO_VERSION__ 1 - #include #include #include diff -urN linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-vbi.c linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-vbi.c --- linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-vbi.c Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-vbi.c Mon Mar 31 12:41:40 2003 @@ -19,8 +19,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define __NO_VERSION__ 1 - #include #include #include diff -urN linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-video.c linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-video.c --- linux-2.5.65-bk2/drivers/media/video/saa7134/saa7134-video.c Mon Mar 17 13:43:44 2003 +++ linux-2.5.65-bk3/drivers/media/video/saa7134/saa7134-video.c Mon Mar 31 12:41:40 2003 @@ -19,8 +19,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define __NO_VERSION__ 1 - #include #include #include diff -urN linux-2.5.65-bk2/drivers/media/video/w9966.c linux-2.5.65-bk3/drivers/media/video/w9966.c --- linux-2.5.65-bk2/drivers/media/video/w9966.c Mon Mar 17 13:43:48 2003 +++ linux-2.5.65-bk3/drivers/media/video/w9966.c Mon Mar 31 12:41:40 2003 @@ -742,7 +742,7 @@ case VIDIOCGTUNER: { struct video_tuner *vtune = arg; - if(vtune->tuner != 0); + if(vtune->tuner != 0) return -EINVAL; strcpy(vtune->name, "no tuner"); vtune->rangelow = 0; diff -urN linux-2.5.65-bk2/drivers/message/i2o/Kconfig linux-2.5.65-bk3/drivers/message/i2o/Kconfig --- linux-2.5.65-bk2/drivers/message/i2o/Kconfig Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/drivers/message/i2o/Kconfig Mon Mar 31 12:41:40 2003 @@ -3,6 +3,7 @@ config I2O tristate "I2O support" + depends on PCI ---help--- The Intelligent Input/Output (I2O) architecture allows hardware drivers to be split into two parts: an operating system specific diff -urN linux-2.5.65-bk2/drivers/message/i2o/Makefile linux-2.5.65-bk3/drivers/message/i2o/Makefile --- linux-2.5.65-bk2/drivers/message/i2o/Makefile Mon Mar 17 13:44:20 2003 +++ linux-2.5.65-bk3/drivers/message/i2o/Makefile Mon Mar 31 12:41:40 2003 @@ -5,7 +5,6 @@ # In the future, some of these should be built conditionally. # -obj-$(CONFIG_I2O_PCI) += i2o_pci.o obj-$(CONFIG_I2O) += i2o_core.o i2o_config.o obj-$(CONFIG_I2O_BLOCK) += i2o_block.o obj-$(CONFIG_I2O_SCSI) += i2o_scsi.o diff -urN linux-2.5.65-bk2/drivers/message/i2o/i2o_block.c linux-2.5.65-bk3/drivers/message/i2o/i2o_block.c --- linux-2.5.65-bk2/drivers/message/i2o/i2o_block.c Mon Mar 17 13:44:21 2003 +++ linux-2.5.65-bk3/drivers/message/i2o/i2o_block.c Mon Mar 31 12:41:41 2003 @@ -754,7 +754,7 @@ * hit the fan big time. The card seems to recover but loses * the pending writes. Deeply ungood except for testing fsck */ - if(i2ob_dev[unit].i2odev->controller->bus.pci.promise) + if(i2ob_dev[unit].i2odev->controller->promise) panic("I2O controller firmware failed. Reboot and force a filesystem check.\n"); default: printk(KERN_INFO "%s: Received event 0x%X we didn't register for\n" @@ -1140,10 +1140,10 @@ if(d->controller->battery == 0) i2ob_dev[i].wcache = CACHE_WRITETHROUGH; - if(d->controller->type == I2O_TYPE_PCI && d->controller->bus.pci.promise) + if(d->controller->promise) i2ob_dev[i].wcache = CACHE_WRITETHROUGH; - if(d->controller->type == I2O_TYPE_PCI && d->controller->bus.pci.short_req) + if(d->controller->short_req) { blk_queue_max_sectors(q, 8); blk_queue_max_phys_segments(q, 8); diff -urN linux-2.5.65-bk2/drivers/message/i2o/i2o_core.c linux-2.5.65-bk3/drivers/message/i2o/i2o_core.c --- linux-2.5.65-bk2/drivers/message/i2o/i2o_core.c Mon Mar 17 13:44:14 2003 +++ linux-2.5.65-bk3/drivers/message/i2o/i2o_core.c Mon Mar 31 12:41:41 2003 @@ -50,6 +50,9 @@ #include #include +#ifdef CONFIG_MTRR +#include +#endif // CONFIG_MTRR #include "i2o_lan.h" @@ -103,6 +106,8 @@ void i2o_report_controller_unit(struct i2o_controller *, struct i2o_device *); +static void i2o_pci_dispose(struct i2o_controller *c); + /* * I2O System Table. Contains information about * all the IOPs in the system. Used to inform IOPs @@ -206,7 +211,6 @@ */ static int verbose; -MODULE_PARM(verbose, "i"); /* * I2O Core reply handler @@ -549,7 +553,8 @@ if(__i2o_delete_device(c->devices)<0) { /* Shouldnt happen */ - c->bus_disable(c); + I2O_IRQ_WRITE32(c, 0xFFFFFFFF); + c->enabled = 0; up(&i2o_configuration_lock); return -EBUSY; } @@ -584,7 +589,7 @@ i2o_reset_controller(c); /* Release IRQ */ - c->destructor(c); + i2o_pci_dispose(c); *p=c->next; up(&i2o_configuration_lock); @@ -1651,7 +1656,7 @@ for (iop = i2o_controller_chain; iop; iop = iop->next) { - if(iop->type != I2O_TYPE_PCI || !iop->bus.pci.dpt) + if(!iop->dpt) i2o_quiesce_controller(iop); } @@ -1911,65 +1916,62 @@ u32 msg[12]; dma_addr_t sys_tbl_phys; int ret; + struct resource *root; u32 *privbuf = kmalloc(16, GFP_KERNEL); if(privbuf == NULL) return -ENOMEM; - if(iop->type == I2O_TYPE_PCI) - { - struct resource *root; - if(iop->status_block->current_mem_size < iop->status_block->desired_mem_size) - { - struct resource *res = &iop->mem_resource; - res->name = iop->pdev->bus->name; - res->flags = IORESOURCE_MEM; - res->start = 0; - res->end = 0; - printk("%s: requires private memory resources.\n", iop->name); - root = pci_find_parent_resource(iop->pdev, res); - if(root==NULL) - printk("Can't find parent resource!\n"); - if(root && allocate_resource(root, res, - iop->status_block->desired_mem_size, - iop->status_block->desired_mem_size, - iop->status_block->desired_mem_size, - 1<<20, /* Unspecified, so use 1Mb and play safe */ - NULL, - NULL)>=0) - { - iop->mem_alloc = 1; - iop->status_block->current_mem_size = 1 + res->end - res->start; - iop->status_block->current_mem_base = res->start; - printk(KERN_INFO "%s: allocated %ld bytes of PCI memory at 0x%08lX.\n", - iop->name, 1+res->end-res->start, res->start); - } - } - if(iop->status_block->current_io_size < iop->status_block->desired_io_size) - { - struct resource *res = &iop->io_resource; - res->name = iop->pdev->bus->name; - res->flags = IORESOURCE_IO; - res->start = 0; - res->end = 0; - printk("%s: requires private memory resources.\n", iop->name); - root = pci_find_parent_resource(iop->pdev, res); - if(root==NULL) - printk("Can't find parent resource!\n"); - if(root && allocate_resource(root, res, - iop->status_block->desired_io_size, - iop->status_block->desired_io_size, - iop->status_block->desired_io_size, - 1<<20, /* Unspecified, so use 1Mb and play safe */ - NULL, - NULL)>=0) - { - iop->io_alloc = 1; - iop->status_block->current_io_size = 1 + res->end - res->start; - iop->status_block->current_mem_base = res->start; - printk(KERN_INFO "%s: allocated %ld bytes of PCI I/O at 0x%08lX.\n", - iop->name, 1+res->end-res->start, res->start); - } + if(iop->status_block->current_mem_size < iop->status_block->desired_mem_size) + { + struct resource *res = &iop->mem_resource; + res->name = iop->pdev->bus->name; + res->flags = IORESOURCE_MEM; + res->start = 0; + res->end = 0; + printk("%s: requires private memory resources.\n", iop->name); + root = pci_find_parent_resource(iop->pdev, res); + if(root==NULL) + printk("Can't find parent resource!\n"); + if(root && allocate_resource(root, res, + iop->status_block->desired_mem_size, + iop->status_block->desired_mem_size, + iop->status_block->desired_mem_size, + 1<<20, /* Unspecified, so use 1Mb and play safe */ + NULL, + NULL)>=0) + { + iop->mem_alloc = 1; + iop->status_block->current_mem_size = 1 + res->end - res->start; + iop->status_block->current_mem_base = res->start; + printk(KERN_INFO "%s: allocated %ld bytes of PCI memory at 0x%08lX.\n", + iop->name, 1+res->end-res->start, res->start); + } + } + if(iop->status_block->current_io_size < iop->status_block->desired_io_size) + { + struct resource *res = &iop->io_resource; + res->name = iop->pdev->bus->name; + res->flags = IORESOURCE_IO; + res->start = 0; + res->end = 0; + printk("%s: requires private memory resources.\n", iop->name); + root = pci_find_parent_resource(iop->pdev, res); + if(root==NULL) + printk("Can't find parent resource!\n"); + if(root && allocate_resource(root, res, + iop->status_block->desired_io_size, + iop->status_block->desired_io_size, + iop->status_block->desired_io_size, + 1<<20, /* Unspecified, so use 1Mb and play safe */ + NULL, + NULL)>=0) + { + iop->io_alloc = 1; + iop->status_block->current_io_size = 1 + res->end - res->start; + iop->status_block->current_mem_base = res->start; + printk(KERN_INFO "%s: allocated %ld bytes of PCI I/O at 0x%08lX.\n", + iop->name, 1+res->end-res->start, res->start); } } else @@ -3427,48 +3429,256 @@ } -EXPORT_SYMBOL(i2o_controller_chain); -EXPORT_SYMBOL(i2o_num_controllers); -EXPORT_SYMBOL(i2o_find_controller); -EXPORT_SYMBOL(i2o_unlock_controller); -EXPORT_SYMBOL(i2o_status_get); -EXPORT_SYMBOL(i2o_install_handler); -EXPORT_SYMBOL(i2o_remove_handler); -EXPORT_SYMBOL(i2o_install_controller); -EXPORT_SYMBOL(i2o_delete_controller); -EXPORT_SYMBOL(i2o_run_queue); +/** + * i2o_pci_dispose - Free bus specific resources + * @c: I2O controller + * + * Disable interrupts and then free interrupt, I/O and mtrr resources + * used by this controller. Called by the I2O core on unload. + */ + +static void i2o_pci_dispose(struct i2o_controller *c) +{ + I2O_IRQ_WRITE32(c,0xFFFFFFFF); + if(c->irq > 0) + free_irq(c->irq, c); + iounmap(((u8 *)c->post_port)-0x40); -EXPORT_SYMBOL(i2o_claim_device); -EXPORT_SYMBOL(i2o_release_device); -EXPORT_SYMBOL(i2o_device_notify_on); -EXPORT_SYMBOL(i2o_device_notify_off); +#ifdef CONFIG_MTRR + if(c->mtrr_reg0 > 0) + mtrr_del(c->mtrr_reg0, 0, 0); + if(c->mtrr_reg1 > 0) + mtrr_del(c->mtrr_reg1, 0, 0); +#endif +} -EXPORT_SYMBOL(i2o_post_this); -EXPORT_SYMBOL(i2o_post_wait); -EXPORT_SYMBOL(i2o_post_wait_mem); +/** + * i2o_pci_interrupt - Bus specific interrupt handler + * @irq: interrupt line + * @dev_id: cookie + * + * Handle an interrupt from a PCI based I2O controller. This turns out + * to be rather simple. We keep the controller pointer in the cookie. + */ + +static void i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r) +{ + struct i2o_controller *c = dev_id; + i2o_run_queue(c); +} -EXPORT_SYMBOL(i2o_query_scalar); -EXPORT_SYMBOL(i2o_set_scalar); -EXPORT_SYMBOL(i2o_query_table); -EXPORT_SYMBOL(i2o_clear_table); -EXPORT_SYMBOL(i2o_row_add_table); -EXPORT_SYMBOL(i2o_issue_params); +/** + * i2o_pci_install - Install a PCI i2o controller + * @dev: PCI device of the I2O controller + * + * Install a PCI (or in theory AGP) i2o controller. Devices are + * initialized, configured and registered with the i2o core subsystem. Be + * very careful with ordering. There may be pending interrupts. + * + * To Do: Add support for polled controllers + */ -EXPORT_SYMBOL(i2o_event_register); -EXPORT_SYMBOL(i2o_event_ack); +int __init i2o_pci_install(struct pci_dev *dev) +{ + struct i2o_controller *c=kmalloc(sizeof(struct i2o_controller), + GFP_KERNEL); + unsigned long mem; + u32 memptr = 0; + u32 size; + + int i; -EXPORT_SYMBOL(i2o_report_status); -EXPORT_SYMBOL(i2o_dump_message); + if(c==NULL) + { + printk(KERN_ERR "i2o: Insufficient memory to add controller.\n"); + return -ENOMEM; + } + memset(c, 0, sizeof(*c)); -EXPORT_SYMBOL(i2o_get_class_name); + for(i=0; i<6; i++) + { + /* Skip I/O spaces */ + if(!(pci_resource_flags(dev, i) & IORESOURCE_IO)) + { + memptr = pci_resource_start(dev, i); + break; + } + } + + if(i==6) + { + printk(KERN_ERR "i2o: I2O controller has no memory regions defined.\n"); + kfree(c); + return -EINVAL; + } + + size = dev->resource[i].end-dev->resource[i].start+1; + /* Map the I2O controller */ + + printk(KERN_INFO "i2o: PCI I2O controller at 0x%08X size=%d\n", memptr, size); + mem = (unsigned long)ioremap(memptr, size); + if(mem==0) + { + printk(KERN_ERR "i2o: Unable to map controller.\n"); + kfree(c); + return -EINVAL; + } -EXPORT_SYMBOL_GPL(i2o_sys_init); + c->irq = -1; + c->dpt = 0; + c->short_req = 0; + c->pdev = dev; + + c->irq_mask = mem+0x34; + c->post_port = mem+0x40; + c->reply_port = mem+0x44; -MODULE_AUTHOR("Red Hat Software"); -MODULE_DESCRIPTION("I2O Core"); -MODULE_LICENSE("GPL"); + c->mem_phys = memptr; + c->mem_offset = mem; + + /* + * Cards that fall apart if you hit them with large I/O + * loads... + */ + + if(dev->vendor == PCI_VENDOR_ID_NCR && dev->device == 0x0630) + { + c->short_req = 1; + printk(KERN_INFO "I2O: Symbios FC920 workarounds activated.\n"); + } + if(dev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) + { + c->promise = 1; + printk(KERN_INFO "I2O: Promise workarounds activated.\n"); + } + + /* + * Cards that go bananas if you quiesce them before you reset + * them + */ + + if(dev->vendor == PCI_VENDOR_ID_DPT) + c->dpt=1; + + /* + * Enable Write Combining MTRR for IOP's memory region + */ +#ifdef CONFIG_MTRR + c->mtrr_reg0 = + mtrr_add(c->mem_phys, size, MTRR_TYPE_WRCOMB, 1); + /* + * If it is an INTEL i960 I/O processor then set the first 64K to + * Uncacheable since the region contains the Messaging unit which + * shouldn't be cached. + */ + c->mtrr_reg1 = -1; + if(dev->vendor == PCI_VENDOR_ID_INTEL || dev->vendor == PCI_VENDOR_ID_DPT) + { + printk(KERN_INFO "I2O: MTRR workaround for Intel i960 processor\n"); + c->mtrr_reg1 = mtrr_add(c->mem_phys, 65536, MTRR_TYPE_UNCACHABLE, 1); + if(c->mtrr_reg1< 0) + { + printk(KERN_INFO "i2o_pci: Error in setting MTRR_TYPE_UNCACHABLE\n"); + mtrr_del(c->mtrr_reg0, c->mem_phys, size); + c->mtrr_reg0 = -1; + } + } + +#endif + + I2O_IRQ_WRITE32(c,0xFFFFFFFF); + + i = i2o_install_controller(c); + + if(i<0) + { + printk(KERN_ERR "i2o: Unable to install controller.\n"); + kfree(c); + iounmap((void *)mem); + return i; + } + + c->irq = dev->irq; + if(c->irq) + { + i=request_irq(dev->irq, i2o_pci_interrupt, SA_SHIRQ, + c->name, c); + if(i<0) + { + printk(KERN_ERR "%s: unable to allocate interrupt %d.\n", + c->name, dev->irq); + c->irq = -1; + i2o_delete_controller(c); + iounmap((void *)mem); + return -EBUSY; + } + } + + printk(KERN_INFO "%s: Installed at IRQ%d\n", c->name, dev->irq); + I2O_IRQ_WRITE32(c,0x0); + c->enabled = 1; + return 0; +} + +static int dpt; + +/** + * i2o_pci_scan - Scan the pci bus for controllers + * + * Scan the PCI devices on the system looking for any device which is a + * memory of the Intelligent, I2O class. We attempt to set up each such device + * and register it with the core. + * + * Returns the number of controllers registered + * + * Note; Do not change this to a hot plug interface. I2O 1.5 itself + * does not support hot plugging. + */ + +int __init i2o_pci_scan(void) +{ + struct pci_dev *dev; + int count=0; + + printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); + + pci_for_each_dev(dev) + { + if((dev->class>>8)!=PCI_CLASS_INTELLIGENT_I2O) + continue; + if(dev->vendor == PCI_VENDOR_ID_DPT && !dpt) + { + if(dev->device == 0xA501 || dev->device == 0xA511) + { + printk(KERN_INFO "i2o: Skipping Adaptec/DPT I2O raid with preferred native driver.\n"); + continue; + } + } + if((dev->class&0xFF)>1) + { + printk(KERN_INFO "i2o: I2O Controller found but does not support I2O 1.5 (skipping).\n"); + continue; + } + if (pci_enable_device(dev)) + continue; + printk(KERN_INFO "i2o: I2O controller on bus %d at %d.\n", + dev->bus->number, dev->devfn); + if(pci_set_dma_mask(dev, 0xffffffff)) + { + printk(KERN_WARNING "I2O controller on bus %d at %d : No suitable DMA available\n", dev->bus->number, dev->devfn); + continue; + } + pci_set_master(dev); + if(i2o_pci_install(dev)==0) + count++; + } + if(count) + printk(KERN_INFO "i2o: %d I2O controller%s found and installed.\n", count, + count==1?"":"s"); + return count?count:-ENODEV; +} static int i2o_core_init(void) { @@ -3496,6 +3706,7 @@ else printk(KERN_INFO "I2O: Event thread created as pid %d\n", evt_pid); + i2o_pci_scan(); if(i2o_num_controllers) i2o_sys_init(); @@ -3532,3 +3743,40 @@ module_init(i2o_core_init); module_exit(i2o_core_exit); +MODULE_PARM(dpt, "i"); +MODULE_PARM_DESC(dpt, "Set this if you want to drive DPT cards normally handled by dpt_i2o"); +MODULE_PARM(verbose, "i"); +MODULE_PARM_DESC(verbose, "Verbose diagnostics"); + +MODULE_AUTHOR("Red Hat Software"); +MODULE_DESCRIPTION("I2O Core"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(i2o_controller_chain); +EXPORT_SYMBOL(i2o_num_controllers); +EXPORT_SYMBOL(i2o_find_controller); +EXPORT_SYMBOL(i2o_unlock_controller); +EXPORT_SYMBOL(i2o_status_get); +EXPORT_SYMBOL(i2o_install_handler); +EXPORT_SYMBOL(i2o_remove_handler); +EXPORT_SYMBOL(i2o_install_controller); +EXPORT_SYMBOL(i2o_delete_controller); +EXPORT_SYMBOL(i2o_run_queue); +EXPORT_SYMBOL(i2o_claim_device); +EXPORT_SYMBOL(i2o_release_device); +EXPORT_SYMBOL(i2o_device_notify_on); +EXPORT_SYMBOL(i2o_device_notify_off); +EXPORT_SYMBOL(i2o_post_this); +EXPORT_SYMBOL(i2o_post_wait); +EXPORT_SYMBOL(i2o_post_wait_mem); +EXPORT_SYMBOL(i2o_query_scalar); +EXPORT_SYMBOL(i2o_set_scalar); +EXPORT_SYMBOL(i2o_query_table); +EXPORT_SYMBOL(i2o_clear_table); +EXPORT_SYMBOL(i2o_row_add_table); +EXPORT_SYMBOL(i2o_issue_params); +EXPORT_SYMBOL(i2o_event_register); +EXPORT_SYMBOL(i2o_event_ack); +EXPORT_SYMBOL(i2o_report_status); +EXPORT_SYMBOL(i2o_dump_message); +EXPORT_SYMBOL(i2o_get_class_name); diff -urN linux-2.5.65-bk2/drivers/message/i2o/i2o_pci.c linux-2.5.65-bk3/drivers/message/i2o/i2o_pci.c --- linux-2.5.65-bk2/drivers/message/i2o/i2o_pci.c Mon Mar 17 13:43:43 2003 +++ linux-2.5.65-bk3/drivers/message/i2o/i2o_pci.c Mon Mar 31 12:41:41 2003 @@ -32,9 +32,6 @@ #include -#ifdef CONFIG_MTRR -#include -#endif // CONFIG_MTRR static int dpt; diff -urN linux-2.5.65-bk2/drivers/message/i2o/i2o_proc.c linux-2.5.65-bk3/drivers/message/i2o/i2o_proc.c --- linux-2.5.65-bk2/drivers/message/i2o/i2o_proc.c Mon Mar 17 13:44:12 2003 +++ linux-2.5.65-bk3/drivers/message/i2o/i2o_proc.c Mon Mar 31 12:41:41 2003 @@ -836,10 +836,14 @@ u16 row_count; u16 more_flag; i2o_exec_execute_ddm_table ddm_table[MAX_I2O_MODULES]; - } result; + } *result; i2o_exec_execute_ddm_table ddm_table; + result = kmalloc(sizeof(*result), GFP_KERNEL); + if(!result) + return -ENOMEM; + spin_lock(&i2o_proc_lock); len = 0; @@ -847,18 +851,17 @@ c, ADAPTER_TID, 0x0003, -1, NULL, 0, - &result, sizeof(result)); + result, sizeof(*result)); if (token < 0) { len += i2o_report_query_status(buf+len, token,"0x0003 Executing DDM List"); - spin_unlock(&i2o_proc_lock); - return len; + goto out; } len += sprintf(buf+len, "Tid Module_type Vendor Mod_id Module_name Vrs Data_size Code_size\n"); - ddm_table=result.ddm_table[0]; + ddm_table=result->ddm_table[0]; - for(i=0; i < result.row_count; ddm_table=result.ddm_table[++i]) + for(i=0; i < result->row_count; ddm_table=result->ddm_table[++i]) { len += sprintf(buf+len, "0x%03x ", ddm_table.ddm_tid & 0xFFF); @@ -882,9 +885,9 @@ len += sprintf(buf+len, "\n"); } - +out: spin_unlock(&i2o_proc_lock); - + kfree(result); return len; } @@ -1047,7 +1050,11 @@ u16 row_count; u16 more_flag; i2o_group_info group[256]; - } result; + } *result; + + result = kmalloc(sizeof(*result), GFP_KERNEL); + if(!result) + return -ENOMEM; spin_lock(&i2o_proc_lock); @@ -1055,24 +1062,23 @@ token = i2o_query_table(I2O_PARAMS_TABLE_GET, d->controller, d->lct_data.tid, 0xF000, -1, NULL, 0, - &result, sizeof(result)); + result, sizeof(*result)); if (token < 0) { len = i2o_report_query_status(buf+len, token, "0xF000 Params Descriptor"); - spin_unlock(&i2o_proc_lock); - return len; + goto out; } len += sprintf(buf+len, "# Group FieldCount RowCount Type Add Del Clear\n"); - for (i=0; i < result.row_count; i++) + for (i=0; i < result->row_count; i++) { len += sprintf(buf+len, "%-3d", i); - len += sprintf(buf+len, "0x%04X ", result.group[i].group_number); - len += sprintf(buf+len, "%10d ", result.group[i].field_count); - len += sprintf(buf+len, "%8d ", result.group[i].row_count); + len += sprintf(buf+len, "0x%04X ", result->group[i].group_number); + len += sprintf(buf+len, "%10d ", result->group[i].field_count); + len += sprintf(buf+len, "%8d ", result->group[i].row_count); - properties = result.group[i].properties; + properties = result->group[i].properties; if (properties & 0x1) len += sprintf(buf+len, "Table "); else len += sprintf(buf+len, "Scalar "); if (properties & 0x2) len += sprintf(buf+len, " + "); @@ -1085,11 +1091,11 @@ len += sprintf(buf+len, "\n"); } - if (result.more_flag) + if (result->more_flag) len += sprintf(buf+len, "There is more...\n"); - +out: spin_unlock(&i2o_proc_lock); - + kfree(result); return len; } @@ -1220,7 +1226,11 @@ u16 row_count; u16 more_flag; i2o_user_table user[64]; - } result; + } *result; + + result = kmalloc(sizeof(*result), GFP_KERNEL); + if(!result) + return -ENOMEM; spin_lock(&i2o_proc_lock); len = 0; @@ -1228,28 +1238,28 @@ token = i2o_query_table(I2O_PARAMS_TABLE_GET, d->controller, d->lct_data.tid, 0xF003, -1, NULL, 0, - &result, sizeof(result)); + result, sizeof(*result)); if (token < 0) { len += i2o_report_query_status(buf+len, token,"0xF003 User Table"); - spin_unlock(&i2o_proc_lock); - return len; + goto out; } len += sprintf(buf+len, "# Instance UserTid ClaimType\n"); - for(i=0; i < result.row_count; i++) + for(i=0; i < result->row_count; i++) { len += sprintf(buf+len, "%-3d", i); - len += sprintf(buf+len, "%#8x ", result.user[i].instance); - len += sprintf(buf+len, "%#7x ", result.user[i].user_tid); - len += sprintf(buf+len, "%#9x\n", result.user[i].claim_type); + len += sprintf(buf+len, "%#8x ", result->user[i].instance); + len += sprintf(buf+len, "%#7x ", result->user[i].user_tid); + len += sprintf(buf+len, "%#9x\n", result->user[i].claim_type); } - if (result.more_flag) + if (result->more_flag) len += sprintf(buf+len, "There is more...\n"); - +out: spin_unlock(&i2o_proc_lock); + kfree(result); return len; } @@ -2264,24 +2274,27 @@ u16 row_count; u16 more_flag; u8 mc_addr[256][8]; - } result; + } *result; + + result = kmalloc(sizeof(*result), GFP_KERNEL); + if(!result) + return -ENOMEM; spin_lock(&i2o_proc_lock); len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, d->controller, d->lct_data.tid, 0x0002, -1, - NULL, 0, &result, sizeof(result)); + NULL, 0, result, sizeof(*result)); if (token < 0) { len += i2o_report_query_status(buf+len, token,"0x002 LAN Multicast MAC Address"); - spin_unlock(&i2o_proc_lock); - return len; + goto out; } - for (i = 0; i < result.row_count; i++) + for (i = 0; i < result->row_count; i++) { - memcpy(mc_addr, result.mc_addr[i], 8); + memcpy(mc_addr, result->mc_addr[i], 8); len += sprintf(buf+len, "MC MAC address[%d]: " "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", @@ -2289,8 +2302,9 @@ mc_addr[3], mc_addr[4], mc_addr[5], mc_addr[6], mc_addr[7]); } - +out: spin_unlock(&i2o_proc_lock); + kfree(result); return len; } @@ -2495,32 +2509,36 @@ u16 row_count; u16 more_flag; u8 alt_addr[256][8]; - } result; + } *result; + + result = kmalloc(sizeof(*result), GFP_KERNEL); + if(!result) + return -ENOMEM; spin_lock(&i2o_proc_lock); len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, d->controller, d->lct_data.tid, - 0x0006, -1, NULL, 0, &result, sizeof(result)); + 0x0006, -1, NULL, 0, result, sizeof(*result)); if (token < 0) { len += i2o_report_query_status(buf+len, token, "0x0006 LAN Alternate Address (optional)"); - spin_unlock(&i2o_proc_lock); - return len; + goto out; } - for (i=0; i < result.row_count; i++) + for (i=0; i < result->row_count; i++) { - memcpy(alt_addr,result.alt_addr[i],8); + memcpy(alt_addr,result->alt_addr[i],8); len += sprintf(buf+len, "Alternate address[%d]: " "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", i, alt_addr[0], alt_addr[1], alt_addr[2], alt_addr[3], alt_addr[4], alt_addr[5], alt_addr[6], alt_addr[7]); } - +out: spin_unlock(&i2o_proc_lock); + kfree(result); return len; } diff -urN linux-2.5.65-bk2/drivers/message/i2o/i2o_scsi.c linux-2.5.65-bk3/drivers/message/i2o/i2o_scsi.c --- linux-2.5.65-bk2/drivers/message/i2o/i2o_scsi.c Mon Mar 17 13:44:38 2003 +++ linux-2.5.65-bk3/drivers/message/i2o/i2o_scsi.c Mon Mar 31 12:41:41 2003 @@ -85,7 +85,7 @@ static u32 *retry[32]; static struct i2o_controller *retry_ctrl[32]; static struct timer_list retry_timer; -static spinlock_t retry_lock; +static spinlock_t retry_lock = SPIN_LOCK_UNLOCKED; static int retry_ct = 0; static atomic_t queue_depth; diff -urN linux-2.5.65-bk2/drivers/mtd/nftlmount.c linux-2.5.65-bk3/drivers/mtd/nftlmount.c --- linux-2.5.65-bk2/drivers/mtd/nftlmount.c Mon Mar 17 13:43:40 2003 +++ linux-2.5.65-bk3/drivers/mtd/nftlmount.c Mon Mar 31 12:41:41 2003 @@ -21,7 +21,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/drivers/net/3c501.c linux-2.5.65-bk3/drivers/net/3c501.c --- linux-2.5.65-bk2/drivers/net/3c501.c Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/drivers/net/3c501.c Mon Mar 31 12:41:41 2003 @@ -955,7 +955,7 @@ * init_module: * * When the driver is loaded as a module this function is called. We fake up - * a device structure with the base I/O and interrupt set as if it was being + * a device structure with the base I/O and interrupt set as if it were being * called from Space.c. This minimises the extra code that would otherwise * be required. * diff -urN linux-2.5.65-bk2/drivers/net/irda/ali-ircc.c linux-2.5.65-bk3/drivers/net/irda/ali-ircc.c --- linux-2.5.65-bk2/drivers/net/irda/ali-ircc.c Mon Mar 17 13:44:04 2003 +++ linux-2.5.65-bk3/drivers/net/irda/ali-ircc.c Mon Mar 31 12:41:41 2003 @@ -248,7 +248,6 @@ struct ali_ircc_cb *self; struct pm_dev *pmdev; int dongle_id; - int ret; int err; IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); diff -urN linux-2.5.65-bk2/drivers/net/sk98lin/skvpd.c linux-2.5.65-bk3/drivers/net/sk98lin/skvpd.c --- linux-2.5.65-bk2/drivers/net/sk98lin/skvpd.c Mon Mar 17 13:44:08 2003 +++ linux-2.5.65-bk3/drivers/net/sk98lin/skvpd.c Mon Mar 31 12:41:41 2003 @@ -121,7 +121,7 @@ ******************************************************************************/ /* - Please refer skvpd.txt for infomation how to include this module + Please refer skvpd.txt for information how to include this module */ static const char SysKonnectFileId[] = "@(#)$Id: skvpd.c,v 1.26 2000/06/13 08:00:01 mkarl Exp $ (C) SK" ; diff -urN linux-2.5.65-bk2/drivers/net/tulip/winbond-840.c linux-2.5.65-bk3/drivers/net/tulip/winbond-840.c --- linux-2.5.65-bk2/drivers/net/tulip/winbond-840.c Mon Mar 17 13:43:46 2003 +++ linux-2.5.65-bk3/drivers/net/tulip/winbond-840.c Mon Mar 31 12:41:41 2003 @@ -17,7 +17,7 @@ Support and updates available at http://www.scyld.com/network/drivers.html - Do not remove the copyright infomation. + Do not remove the copyright information. Do not change the version information unless an improvement has been made. Merely removing my name, as Compex has done in the past, does not count as an improvement. diff -urN linux-2.5.65-bk2/drivers/pcmcia/bulkmem.c linux-2.5.65-bk3/drivers/pcmcia/bulkmem.c --- linux-2.5.65-bk2/drivers/pcmcia/bulkmem.c Mon Mar 17 13:44:51 2003 +++ linux-2.5.65-bk3/drivers/pcmcia/bulkmem.c Mon Mar 31 12:41:41 2003 @@ -31,8 +31,6 @@ ======================================================================*/ -#define __NO_VERSION__ - #include #include #include diff -urN linux-2.5.65-bk2/drivers/pcmcia/cardbus.c linux-2.5.65-bk3/drivers/pcmcia/cardbus.c --- linux-2.5.65-bk2/drivers/pcmcia/cardbus.c Mon Mar 17 13:43:50 2003 +++ linux-2.5.65-bk3/drivers/pcmcia/cardbus.c Mon Mar 31 12:41:41 2003 @@ -46,8 +46,6 @@ */ -#define __NO_VERSION__ - #include #include #include diff -urN linux-2.5.65-bk2/drivers/pcmcia/cistpl.c linux-2.5.65-bk3/drivers/pcmcia/cistpl.c --- linux-2.5.65-bk2/drivers/pcmcia/cistpl.c Mon Mar 17 13:43:50 2003 +++ linux-2.5.65-bk3/drivers/pcmcia/cistpl.c Mon Mar 31 12:41:41 2003 @@ -31,8 +31,6 @@ ======================================================================*/ -#define __NO_VERSION__ - #include #include #include diff -urN linux-2.5.65-bk2/drivers/pcmcia/cs.c linux-2.5.65-bk3/drivers/pcmcia/cs.c --- linux-2.5.65-bk2/drivers/pcmcia/cs.c Mon Mar 17 13:43:49 2003 +++ linux-2.5.65-bk3/drivers/pcmcia/cs.c Mon Mar 31 12:41:41 2003 @@ -895,6 +895,10 @@ c = &s->config[reg->Function]; } else c = CONFIG(handle); + + if (c == NULL) + return CS_NO_CARD; + if (!(c->state & CONFIG_LOCKED)) return CS_CONFIGURATION_LOCKED; diff -urN linux-2.5.65-bk2/drivers/pcmcia/rsrc_mgr.c linux-2.5.65-bk3/drivers/pcmcia/rsrc_mgr.c --- linux-2.5.65-bk2/drivers/pcmcia/rsrc_mgr.c Mon Mar 17 13:44:10 2003 +++ linux-2.5.65-bk3/drivers/pcmcia/rsrc_mgr.c Mon Mar 31 12:41:41 2003 @@ -31,8 +31,6 @@ ======================================================================*/ -#define __NO_VERSION__ - #include #include #include diff -urN linux-2.5.65-bk2/drivers/pnp/pnpbios/core.c linux-2.5.65-bk3/drivers/pnp/pnpbios/core.c --- linux-2.5.65-bk2/drivers/pnp/pnpbios/core.c Mon Mar 31 12:41:37 2003 +++ linux-2.5.65-bk3/drivers/pnp/pnpbios/core.c Mon Mar 31 12:41:41 2003 @@ -969,7 +969,7 @@ spin_lock_init(&pnp_bios_lock); - if(pnpbios_disabled) { + if(pnpbios_disabled || (dmi_broken & BROKEN_PNP_BIOS)) { printk(KERN_INFO "PnPBIOS: Disabled\n"); return -ENODEV; } diff -urN linux-2.5.65-bk2/drivers/pnp/pnpbios/proc.c linux-2.5.65-bk3/drivers/pnp/pnpbios/proc.c --- linux-2.5.65-bk2/drivers/pnp/pnpbios/proc.c Mon Mar 17 13:44:45 2003 +++ linux-2.5.65-bk3/drivers/pnp/pnpbios/proc.c Mon Mar 31 12:41:41 2003 @@ -19,7 +19,6 @@ */ //#include -#define __NO_VERSION__ //#include #include diff -urN linux-2.5.65-bk2/drivers/scsi/advansys.c linux-2.5.65-bk3/drivers/scsi/advansys.c --- linux-2.5.65-bk2/drivers/scsi/advansys.c Mon Mar 17 13:43:50 2003 +++ linux-2.5.65-bk3/drivers/scsi/advansys.c Mon Mar 31 12:41:41 2003 @@ -7099,7 +7099,7 @@ * then return the number of underrun bytes. */ if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 && - qdonep->remain_bytes <= scp->request_bufflen != 0) { + qdonep->remain_bytes <= scp->request_bufflen) { ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n", (unsigned) qdonep->remain_bytes); scp->resid = qdonep->remain_bytes; diff -urN linux-2.5.65-bk2/drivers/scsi/aha152x.c linux-2.5.65-bk3/drivers/scsi/aha152x.c --- linux-2.5.65-bk2/drivers/scsi/aha152x.c Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/drivers/scsi/aha152x.c Mon Mar 31 12:41:42 2003 @@ -2651,7 +2651,7 @@ static void datai_run(struct Scsi_Host *shpnt) { - unsigned int the_time; + unsigned long the_time; int fifodata, data_count; /* @@ -2793,7 +2793,7 @@ static void datao_run(struct Scsi_Host *shpnt) { - unsigned int the_time; + unsigned long the_time; int data_count; /* until phase changes or all data sent */ diff -urN linux-2.5.65-bk2/drivers/scsi/aha1542.c linux-2.5.65-bk3/drivers/scsi/aha1542.c --- linux-2.5.65-bk2/drivers/scsi/aha1542.c Mon Mar 17 13:44:06 2003 +++ linux-2.5.65-bk3/drivers/scsi/aha1542.c Mon Mar 31 12:41:42 2003 @@ -1020,7 +1020,7 @@ static int __init do_setup(char *str) { - int ints[4]; + int ints[5]; int count=setup_idx; diff -urN linux-2.5.65-bk2/drivers/scsi/cpqfcTSinit.c linux-2.5.65-bk3/drivers/scsi/cpqfcTSinit.c --- linux-2.5.65-bk2/drivers/scsi/cpqfcTSinit.c Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/drivers/scsi/cpqfcTSinit.c Mon Mar 31 12:41:42 2003 @@ -686,7 +686,7 @@ if( (vendor_cmd->rw_flag == VENDOR_READ_OPCODE) && vendor_cmd->len ) if( copy_to_user( vendor_cmd->bufp, buf, vendor_cmd->len)) - return( -EFAULT); + result = -EFAULT; if( buf) kfree( buf); diff -urN linux-2.5.65-bk2/drivers/scsi/gdth.c linux-2.5.65-bk3/drivers/scsi/gdth.c --- linux-2.5.65-bk2/drivers/scsi/gdth.c Mon Mar 17 13:44:14 2003 +++ linux-2.5.65-bk3/drivers/scsi/gdth.c Mon Mar 31 12:41:42 2003 @@ -4,7 +4,7 @@ * Intel Corporation: Storage RAID Controllers * * * * gdth.c * - * Copyright (C) 1995-02 ICP vortex, an Intel company, Achim Leubner * + * Copyright (C) 1995-03 ICP vortex, an Intel company, Achim Leubner * * * * * * Additions/Fixes: Boji Tony Kannanthanam * @@ -24,11 +24,17 @@ * along with this kernel; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * - * Tested with Linux 1.2.13, ..., 2.2.20, ..., 2.4.18 * + * Tested with Linux 1.2.13, ..., 2.2.20, ..., 2.4.20 * * * * $Log: gdth.c,v $ - * Revision 1.61 2002/10/03 09:35:22 boji - * Fixed SCREENSERVICE initialisation in SMP cases. + * Revision 1.62 2003/02/27 15:01:59 achim + * Dynamic DMA mapping implemented + * New (character device) IOCTL interface added + * Other controller related changes made + * + * Revision 1.61 2002/11/08 13:09:52 boji + * Added support for XSCALE based RAID Controllers + * Fixed SCREENSERVICE initialization in SMP cases * Added checks for gdth_polling before GDTH_HA_LOCK * * Revision 1.60 2002/02/05 09:35:22 achim @@ -216,7 +222,7 @@ * * Revision 1.9 1997/09/04 10:07:25 achim * IO-mapping with virt_to_bus(), gdth_readb(), gdth_writeb(), ... - * register_reboot_notifier() to get a notify on shutdown used + * register_reboot_notifier() to get a notify on shutown used * * Revision 1.8 1997/04/02 12:14:30 achim * Version 1.00 (see gdth.h), tested with kernel 2.0.29 @@ -248,7 +254,7 @@ * Initial revision * ************************************************************************/ -#ident "$Id: gdth.c,v 1.60 2002/02/05 09:35:22 achim Exp $" +#ident "$Id: gdth.c,v 1.62 2003/02/27 15:01:59 achim Exp $" /* All GDT Disk Array Controllers are fully supported by this driver. * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the @@ -300,18 +306,21 @@ */ /* The meaning of the Scsi_Pointer members in this driver is as follows: - * ptr: Chaining - * this_residual: Command priority - * buffer: Unused - * buffers_residual: Timeout value - * Status: Command status (gdth_do_cmd()) - * Message: Additional info (gdth_do_cmd()) - * have_data_in: Flag for gdth_wait_completion() - * sent_command: Opcode special command - * phase: Service/parameter/return code special command + * ptr: Chaining + * this_residual: Command priority + * buffer: phys. DMA sense buffer + * dma_handle: phys. DMA buffer (kernel >= 2.4.0) + * buffers_residual: Timeout value + * Status: Command status (gdth_do_cmd()), DMA mem. mappings + * Message: Additional info (gdth_do_cmd()), DMA direction + * have_data_in: Flag for gdth_wait_completion() + * sent_command: Opcode special command + * phase: Service/parameter/return code special command */ -#error Please convert me to Documentation/DMA-mapping.txt +/* default: activate /proc and character device IOCTL interface */ +#define GDTH_IOCTL_PROC +#define GDTH_IOCTL_CHRDEV #include @@ -324,6 +333,7 @@ #include #include #include +#include #include #include #include @@ -340,6 +350,7 @@ #include #include #include +#include #if LINUX_VERSION_CODE >= 0x020322 #include #elif LINUX_VERSION_CODE >= 0x02015F @@ -353,6 +364,9 @@ #endif #include "scsi.h" #include "hosts.h" +#if LINUX_VERSION_CODE < 0x020503 +#include "sd.h" +#endif #include "gdth.h" @@ -378,7 +392,8 @@ gdth_evt_str *estr); static void gdth_clear_events(void); -static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count); +static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp, + char *buffer,ushort count); static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp); static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive); @@ -408,6 +423,13 @@ static const char *gdth_ctr_name(int hanum); +#ifdef GDTH_IOCTL_CHRDEV +static int gdth_open(struct inode *inode, struct file *filep); +static int gdth_close(struct inode *inode, struct file *filep); +static int gdth_ioctl(struct inode *inode, struct file *filep, + unsigned int cmd, unsigned long arg); +#endif + #if LINUX_VERSION_CODE >= 0x010300 static void gdth_flush(int hanum); #if LINUX_VERSION_CODE >= 0x020100 @@ -604,6 +626,9 @@ static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */ static int elastidx; static int eoldidx; +#ifdef GDTH_IOCTL_CHRDEV +static int major; +#endif #define DIN 1 /* IN data direction */ #define DOU 2 /* OUT data direction */ @@ -641,24 +666,35 @@ #define __init #endif -#if LINUX_VERSION_CODE >= 0x02015F +#if LINUX_VERSION_CODE >= 0x020503 +#define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock) +#define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags) +#define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags) + +#define GDTH_LOCK_SCSI_DONE(dev, flags) spin_lock_irqsave(dev->host_lock,flags) +#define GDTH_UNLOCK_SCSI_DONE(dev, flags) spin_unlock_irqrestore(dev->host_lock,flags) +#define GDTH_LOCK_SCSI_DOCMD(dev) spin_lock_irq(dev->host_lock) +#define GDTH_UNLOCK_SCSI_DOCMD(dev) spin_unlock_irq(dev->host_lock) + +#elif LINUX_VERSION_CODE >= 0x02015F #define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock) #define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags) #define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags) -#define GDTH_LOCK_SCSI_DONE(dev, flags) spin_lock_irqsave(dev->host_lock,flags) -#define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(dev->host_lock,flags) -#define GDTH_LOCK_SCSI_DOCMD(dev) spin_lock_irq(dev->host_lock) -#define GDTH_UNLOCK_SCSI_DOCMD(dev) spin_unlock_irq(dev->host_lock) +#define GDTH_LOCK_SCSI_DONE(flags) spin_lock_irqsave(&io_request_lock,flags) +#define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags) +#define GDTH_LOCK_SCSI_DOCMD() spin_lock_irq(&io_request_lock) +#define GDTH_UNLOCK_SCSI_DOCMD() spin_unlock_irq(&io_request_lock) + #else #define GDTH_INIT_LOCK_HA(ha) do {} while (0) #define GDTH_LOCK_HA(ha,flags) do {save_flags(flags); cli();} while (0) #define GDTH_UNLOCK_HA(ha,flags) do {restore_flags(flags);} while (0) -#define GDTH_LOCK_SCSI_DONE(dev, flags) do {} while (0) -#define GDTH_UNLOCK_SCSI_DONE(dev, flags) do {} while (0) -#define GDTH_LOCK_SCSI_DOCMD(dev) do {} while (0) -#define GDTH_UNLOCK_SCSI_DOCMD(dev) do {} while (0) +#define GDTH_LOCK_SCSI_DONE(flags) do {} while (0) +#define GDTH_UNLOCK_SCSI_DONE(flags) do {} while (0) +#define GDTH_LOCK_SCSI_DOCMD() do {} while (0) +#define GDTH_UNLOCK_SCSI_DOCMD() do {} while (0) #endif /* LILO and modprobe/insmod parameters */ @@ -702,10 +738,21 @@ MODULE_PARM(virt_ctr, "i"); MODULE_PARM(shared_access, "i"); MODULE_AUTHOR("Achim Leubner"); +#endif +#if LINUX_VERSION_CODE >= 0x02040B MODULE_LICENSE("GPL"); #endif #endif +#ifdef GDTH_IOCTL_CHRDEV +/* ioctl interface */ +static struct file_operations gdth_fops = { + ioctl:gdth_ioctl, + open:gdth_open, + release:gdth_close, +}; +#endif + /* /proc support */ #if LINUX_VERSION_CODE >= 0x010300 #include @@ -813,6 +860,8 @@ PCI_DEVICE_ID_VORTEX_GDTNEWRX); gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SRC); + gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_SRC_XSCALE); return cnt; } @@ -820,10 +869,11 @@ /* Vortex only makes RAID controllers. * We do not really want to specify all 550 ids here, so wildcard match. */ -static struct pci_device_id gdthtable[] = { - {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID }, - {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID }, - {0} +static struct pci_device_id gdthtable[] __devinitdata = { + {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, + {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, + {0} }; MODULE_DEVICE_TABLE(pci,gdthtable); #endif @@ -1235,6 +1285,9 @@ ha->stype = (ulong32)pcistr->device_id; ha->subdevice_id = pcistr->subdevice_id; ha->irq = pcistr->irq; +#if LINUX_VERSION_CODE >= 0x20400 + ha->pdev = pcistr->pdev; +#endif if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */ TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq)); @@ -1511,6 +1564,11 @@ PCI_ROM_ADDRESS, rom_addr); #endif + /* Ensure that it is safe to access the non HW portions of DPMEM. + * Aditional check needed for Xscale based RAID controllers */ + while( ((int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg) ) & 3 ) + gdth_delay(1); + /* check and reset interface area */ dp6m_ptr = (gdt6m_dpram_str *)ha->brd; gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u); @@ -1840,7 +1898,7 @@ if (ha->type == GDT_EISA) { if (ha->pccb->OpCode == GDT_INIT) /* store DMA buffer */ - outl(virt_to_bus(ha->pccb), ha->bmic + MAILBOXREG); + outl(ha->ccb_phys, ha->bmic + MAILBOXREG); outb(ha->pccb->Service, ha->bmic + LDOORREG); } else if (ha->type == GDT_ISA) { gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event); @@ -1916,7 +1974,7 @@ cmd_ptr->u.ioctl.subfunc = p1; cmd_ptr->u.ioctl.channel = p2; cmd_ptr->u.ioctl.param_size = (ushort)p3; - cmd_ptr->u.ioctl.p_param = virt_to_bus(ha->pscratch); + cmd_ptr->u.ioctl.p_param = ha->scratch_phys; } else { cmd_ptr->u.cache.DeviceNo = (ushort)p1; cmd_ptr->u.cache.BlockNo = p2; @@ -1965,6 +2023,8 @@ gdth_raw_iochan_str *iocr; gdth_arcdl_str *alst; gdth_alist_str *alst2; + gdth_oem_str_ioctl *oemstr; + #ifdef GDTH_RTC unchar rtc[12]; ulong flags; @@ -2233,6 +2293,27 @@ } } + /* Determine OEM string using IOCTL */ + oemstr = (gdth_oem_str_ioctl *)ha->pscratch; + oemstr->params.ctl_version = 0x01; + oemstr->params.buffer_size = sizeof(oemstr->text); + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, + CACHE_READ_OEM_STRING_RECORD,INVALID_CHANNEL, + sizeof(gdth_oem_str_ioctl))) { + TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n")); + printk("GDT CTR%d Vendor: %s\n",hanum,oemstr->text.oem_company_name); + /* Save the Host Drive inquiry data */ + strncpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,7); + ha->oem_name[7] = '\0'; + } else { + /* Old method, based on PCI ID */ + TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n")); + if (ha->oem_id == OEM_ID_INTEL) + strcpy(ha->oem_name,"Intel "); + else + strcpy(ha->oem_name,"ICP "); + } + /* scanning for host drives */ for (i = 0; i < cdev_cnt; ++i) gdth_analyse_hdrive(hanum,i); @@ -2313,8 +2394,13 @@ GDTH_LOCK_HA(ha, flags); scp->SCp.this_residual = (int)priority; +#if LINUX_VERSION_CODE >= 0x02053C b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; +#else + b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel; + t = scp->target; +#endif #if LINUX_VERSION_CODE >= 0x010300 if (priority >= DEFAULT_PRI) { if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || @@ -2357,7 +2443,7 @@ register gdth_ha_str *ha; register Scsi_Cmnd *pscp; register Scsi_Cmnd *nscp; - unchar b, t, firsttime; + unchar b, t, l, firsttime; unchar this_cmd, next_cmd; ulong flags = 0; int cmd_index; @@ -2365,7 +2451,7 @@ TRACE(("gdth_next() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); if (!gdth_polling) - GDTH_LOCK_HA(ha, flags); + GDTH_LOCK_HA(ha, flags); ha->cmd_cnt = ha->cmd_offs_dpmem = 0; this_cmd = firsttime = TRUE; @@ -2375,8 +2461,15 @@ for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) { if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr) pscp = (Scsi_Cmnd *)pscp->SCp.ptr; +#if LINUX_VERSION_CODE >= 0x02053C b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel; t = nscp->device->id; + l = nscp->device->lun; +#else + b = virt_ctr ? NUMDATA(nscp->host)->busnum : nscp->channel; + t = nscp->target; + l = nscp->lun; +#endif if (nscp->SCp.this_residual >= DEFAULT_PRI) { if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) @@ -2404,16 +2497,16 @@ nscp->SCp.phase = CACHESERVICE; /* default: cache svc. */ if (nscp->cmnd[0] == TEST_UNIT_READY) { TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n", - b, t, nscp->lun)); + b, t, l)); /* TEST_UNIT_READY -> set scan mode */ if ((ha->scan_mode & 0x0f) == 0) { - if (b == 0 && t == 0 && nscp->device->lun == 0) { + if (b == 0 && t == 0 && l == 0) { ha->scan_mode |= 1; TRACE2(("Scan mode: 0x%x\n", ha->scan_mode)); } } else if ((ha->scan_mode & 0x0f) == 1) { - if (b == 0 && ((t == 0 && nscp->device->lun == 1) || - (t == 1 && nscp->device->lun == 0))) { + if (b == 0 && ((t == 0 && l == 1) || + (t == 1 && l == 0))) { nscp->SCp.sent_command = GDT_SCAN_START; nscp->SCp.phase = ((ha->scan_mode & 0x10 ? 1:0) << 8) | SCSIRAWSERVICE; @@ -2465,7 +2558,7 @@ /* io_request_lock already active ! */ nscp->scsi_done(nscp); if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); + GDTH_LOCK_HA(ha,flags); } } } else @@ -2483,19 +2576,19 @@ this_cmd = FALSE; else ha->raw[BUS_L2P(ha,b)].io_cnt[t]++; - } else if (t >= MAX_HDRIVES || !ha->hdr[t].present || nscp->device->lun != 0) { + } else if (t >= MAX_HDRIVES || !ha->hdr[t].present || l != 0) { TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n", - nscp->cmnd[0], b, t, nscp->lun)); + nscp->cmnd[0], b, t, l)); nscp->result = DID_BAD_TARGET << 16; if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; else { if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); + GDTH_LOCK_HA(ha,flags); } } else { switch (nscp->cmnd[0]) { @@ -2521,20 +2614,20 @@ if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; else { - if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); - if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_LOCK_HA(ha,flags); } } else if (gdth_internal_cache_cmd(hanum,nscp)) { if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); + GDTH_LOCK_HA(ha,flags); } break; @@ -2549,12 +2642,12 @@ if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; else { - if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); - if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_LOCK_HA(ha,flags); } } else { nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0; @@ -2589,12 +2682,12 @@ if (!nscp->SCp.have_data_in) nscp->SCp.have_data_in++; else { - if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); - if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); + if (!gdth_polling) + GDTH_LOCK_HA(ha,flags); } } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) this_cmd = FALSE; @@ -2611,11 +2704,11 @@ nscp->SCp.have_data_in++; else { if (!gdth_polling) - GDTH_UNLOCK_HA(ha,flags); + GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); if (!gdth_polling) - GDTH_LOCK_HA(ha,flags); + GDTH_LOCK_HA(ha,flags); } break; } @@ -2636,7 +2729,7 @@ } if (!gdth_polling) - GDTH_UNLOCK_HA(ha, flags); + GDTH_UNLOCK_HA(ha, flags); if (gdth_polling && ha->cmd_cnt > 0) { if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT)) @@ -2645,27 +2738,54 @@ } } -static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count) +static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp, + char *buffer,ushort count) { ushort cpcount,i; ushort cpsum,cpnow; struct scatterlist *sl; + gdth_ha_str *ha; + int sgcnt; + char *address; cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen; + ha = HADATA(gdth_ctr_tab[hanum]); + if (scp->use_sg) { sl = (struct scatterlist *)scp->request_buffer; - for (i=0,cpsum=0; iuse_sg; ++i,++sl) { - cpnow = (ushort)sl->length; +#if LINUX_VERSION_CODE >= 0x020400 + sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,PCI_DMA_FROMDEVICE); + for (i=0,cpsum=0; ibufflen)); if (cpsum+cpnow > cpcount) cpnow = cpcount - cpsum; cpsum += cpnow; - memcpy((char*)sl->address,buffer,cpnow); + address = (char *)phys_to_virt(sg_dma_address(sl)); + memcpy(address,buffer,cpnow); + if (cpsum == cpcount) + break; + buffer += cpnow; + } + pci_unmap_sg(ha->pdev,scp->request_buffer, + scp->use_sg,PCI_DMA_FROMDEVICE); +#else + sgcnt = scp->use_sg; + for (i=0,cpsum=0; ilength; + TRACE(("copy_internal() now %d sum %d count %d %d\n", + cpnow,cpsum,cpcount,(ushort)scp->bufflen)); + if (cpsum+cpnow > cpcount) + cpnow = cpcount - cpsum; + cpsum += cpnow; + address = (char *)sl->address; + memcpy(address,buffer,cpnow); if (cpsum == cpcount) break; buffer += cpnow; } +#endif } else { TRACE(("copy_internal() count %d\n",cpcount)); memcpy((char*)scp->request_buffer,buffer,cpcount); @@ -2682,7 +2802,11 @@ gdth_modep_data mpd; ha = HADATA(gdth_ctr_tab[hanum]); +#if LINUX_VERSION_CODE >= 0x02053C t = scp->device->id; +#else + t = scp->target; +#endif TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n", scp->cmnd[0],t)); @@ -2706,13 +2830,10 @@ inq.version = 2; inq.resp_aenc = 2; inq.add_length= 32; - if (ha->oem_id == OEM_ID_INTEL) - strcpy(inq.vendor,"Intel "); - else - strcpy(inq.vendor,"ICP "); + strcpy(inq.vendor,ha->oem_name); sprintf(inq.product,"Host Drive #%02d",t); strcpy(inq.revision," "); - gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data)); + gdth_copy_internal_data(hanum,scp,(char*)&inq,sizeof(gdth_inq_data)); break; case REQUEST_SENSE: @@ -2722,7 +2843,7 @@ sd.key = NO_SENSE; sd.info = 0; sd.add_length= 0; - gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data)); + gdth_copy_internal_data(hanum,scp,(char*)&sd,sizeof(gdth_sense_data)); break; case MODE_SENSE: @@ -2734,14 +2855,14 @@ mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); - gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data)); + gdth_copy_internal_data(hanum,scp,(char*)&mpd,sizeof(gdth_modep_data)); break; case READ_CAPACITY: TRACE2(("Read capacity hdrive %d\n",t)); rdc.last_block_no = ntohl(ha->hdr[t].size-1); rdc.block_length = ntohl(SECTOR_SIZE); - gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data)); + gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data)); break; default: @@ -2766,8 +2887,8 @@ register gdth_cmd_str *cmdp; struct scatterlist *sl; ushort i, cnt; - ulong32 no; - int cmd_index, read_write; + ulong32 no, phys_addr; + int cmd_index, read_write, sgcnt; ha = HADATA(gdth_ctr_tab[hanum]); cmdp = ha->pccb; @@ -2789,7 +2910,7 @@ gdth_set_sema0(hanum); /* fill command */ - read_write = FALSE; + read_write = 0; if (scp->SCp.sent_command != -1) cmdp->OpCode = scp->SCp.sent_command; /* special cache cmd. */ else if (scp->cmnd[0] == RESERVE) @@ -2803,15 +2924,16 @@ cmdp->OpCode = GDT_UNMOUNT; else cmdp->OpCode = GDT_FLUSH; - } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10) { - read_write = TRUE; + } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10 || + scp->cmnd[0] == WRITE_12) { + read_write = 1; if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) && (ha->cache_feat & GDT_WR_THROUGH))) cmdp->OpCode = GDT_WRITE_THR; else cmdp->OpCode = GDT_WRITE; } else { - read_write = TRUE; + read_write = 2; cmdp->OpCode = GDT_READ; } @@ -2835,10 +2957,22 @@ if (scp->use_sg) { cmdp->u.cache.DestAddr= 0xffffffff; sl = (struct scatterlist *)scp->request_buffer; - for (i=0; iuse_sg; ++i,++sl) { + sgcnt = scp->use_sg; +#if LINUX_VERSION_CODE >= 0x020400 + scp->SCp.Status = GDTH_MAP_SG; + scp->SCp.Message = (read_write == 1 ? + PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); + sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); + for (i=0; iu.cache.sg_lst[i].sg_ptr = sg_dma_address(sl); + cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl); + } +#else + for (i=0; iu.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address); cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length; } +#endif cmdp->u.cache.sg_canz = (ulong32)i; #ifdef GDTH_STATISTICS @@ -2850,15 +2984,24 @@ if (iu.cache.sg_lst[i].sg_len = 0; } else { +#if LINUX_VERSION_CODE >= 0x020400 + scp->SCp.Status = GDTH_MAP_SINGLE; + scp->SCp.Message = (read_write == 1 ? + PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); + phys_addr = pci_map_single(ha->pdev,scp->request_buffer, + scp->request_bufflen,scp->SCp.Message); + scp->SCp.dma_handle = phys_addr; +#else + phys_addr = virt_to_bus(scp->request_buffer); +#endif if (ha->cache_feat & SCATTER_GATHER) { cmdp->u.cache.DestAddr = 0xffffffff; cmdp->u.cache.sg_canz = 1; - cmdp->u.cache.sg_lst[0].sg_ptr = - virt_to_bus(scp->request_buffer); + cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr; cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen; cmdp->u.cache.sg_lst[1].sg_len = 0; } else { - cmdp->u.cache.DestAddr = virt_to_bus(scp->request_buffer); + cmdp->u.cache.DestAddr = phys_addr; cmdp->u.cache.sg_canz= 0; } } @@ -2896,12 +3039,18 @@ register gdth_cmd_str *cmdp; struct scatterlist *sl; ushort i; - int cmd_index; + ulong32 phys_addr, sense_paddr; + int cmd_index, sgcnt; unchar t,l; ha = HADATA(gdth_ctr_tab[hanum]); +#if LINUX_VERSION_CODE >= 0x02053C t = scp->device->id; l = scp->device->lun; +#else + t = scp->target; + l = scp->lun; +#endif cmdp = ha->pccb; TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n", scp->cmnd[0],b,t,l)); @@ -2931,6 +3080,13 @@ /* evaluate command size */ ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst); } else { +#if LINUX_VERSION_CODE >= 0x020400 + sense_paddr = pci_map_single(ha->pdev,scp->sense_buffer, + 16,PCI_DMA_FROMDEVICE); + scp->SCp.buffer = (struct scatterlist *)sense_paddr; +#else + sense_paddr = virt_to_bus(scp->sense_buffer); +#endif cmdp->OpCode = GDT_WRITE; /* always */ cmdp->BoardNode = LOCALBOARD; cmdp->u.raw.reserved = 0; @@ -2944,7 +3100,7 @@ cmdp->u.raw.link_p = 0; cmdp->u.raw.sdlen = scp->request_bufflen; cmdp->u.raw.sense_len = 16; - cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer); + cmdp->u.raw.sense_data = sense_paddr; cmdp->u.raw.direction = gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN; memcpy(cmdp->u.raw.cmd,scp->cmnd,12); @@ -2952,10 +3108,21 @@ if (scp->use_sg) { cmdp->u.raw.sdata = 0xffffffff; sl = (struct scatterlist *)scp->request_buffer; - for (i=0; iuse_sg; ++i,++sl) { + sgcnt = scp->use_sg; +#if LINUX_VERSION_CODE >= 0x020400 + scp->SCp.Status = GDTH_MAP_SG; + scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; + sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); + for (i=0; iu.raw.sg_lst[i].sg_ptr = sg_dma_address(sl); + cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl); + } +#else + for (i=0; iu.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address); cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length; } +#endif cmdp->u.raw.sg_ranz = (ulong32)i; #ifdef GDTH_STATISTICS @@ -2967,14 +3134,23 @@ if (iu.raw.sg_lst[i].sg_len = 0; } else { +#if LINUX_VERSION_CODE >= 0x020400 + scp->SCp.Status = GDTH_MAP_SINGLE; + scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; + phys_addr = pci_map_single(ha->pdev,scp->request_buffer, + scp->request_bufflen,scp->SCp.Message); + scp->SCp.dma_handle = phys_addr; +#else + phys_addr = virt_to_bus(scp->request_buffer); +#endif if (ha->raw_feat & SCATTER_GATHER) { cmdp->u.raw.sdata = 0xffffffff; cmdp->u.raw.sg_ranz= 1; - cmdp->u.raw.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer); + cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr; cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen; cmdp->u.raw.sg_lst[1].sg_len = 0; } else { - cmdp->u.raw.sdata = virt_to_bus(scp->request_buffer); + cmdp->u.raw.sdata = phys_addr; cmdp->u.raw.sg_ranz= 0; } } @@ -3372,9 +3548,19 @@ if (rval == 2) { gdth_putq(hanum,scp,scp->SCp.this_residual); } else if (rval == 1) { +#if LINUX_VERSION_CODE >= 0x02053C GDTH_LOCK_SCSI_DONE(scp->device->host, flags); scp->scsi_done(scp); - GDTH_UNLOCK_SCSI_DONE(scp->host,flags); + GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags); +#elif LINUX_VERSION_CODE >= 0x020503 + GDTH_LOCK_SCSI_DONE(scp->host, flags); + scp->scsi_done(scp); + GDTH_UNLOCK_SCSI_DONE(scp->host, flags); +#else + GDTH_LOCK_SCSI_DONE(flags); + scp->scsi_done(scp); + GDTH_UNLOCK_SCSI_DONE(flags); +#endif } gdth_next(hanum); } @@ -3384,7 +3570,7 @@ register gdth_ha_str *ha; gdth_msg_str *msg; gdth_cmd_str *cmdp; - unchar b; + unchar b, t; ha = HADATA(gdth_ctr_tab[hanum]); cmdp = ha->pccb; @@ -3413,7 +3599,7 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= msg->msg_handle; - cmdp->u.screen.su.msg.msg_addr = virt_to_bus(msg); + cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; ha->scratch_busy = TRUE; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) @@ -3448,7 +3634,7 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= msg->msg_handle; - cmdp->u.screen.su.msg.msg_addr = virt_to_bus(msg); + cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; ha->scratch_busy = TRUE; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) @@ -3461,11 +3647,35 @@ printk("\n"); } else { +#if LINUX_VERSION_CODE >= 0x02053C b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; + t = scp->device->id; +#else + b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel; + t = scp->target; +#endif if (scp->SCp.sent_command == -1 && b != ha->virt_bus) { - ha->raw[BUS_L2P(ha,b)].io_cnt[scp->device->id]--; + ha->raw[BUS_L2P(ha,b)].io_cnt[t]--; } /* cache or raw service */ + if (ha->status == S_BSY) { + TRACE2(("Controller busy -> retry !\n")); + if (scp->SCp.sent_command == GDT_MOUNT) + scp->SCp.sent_command = GDT_CLUST_INFO; + /* retry */ + return 2; + } +#if LINUX_VERSION_CODE >= 0x020400 + if (scp->SCp.Status == GDTH_MAP_SG) + pci_unmap_sg(ha->pdev,scp->request_buffer, + scp->use_sg,scp->SCp.Message); + else if (scp->SCp.Status == GDTH_MAP_SINGLE) + pci_unmap_single(ha->pdev,scp->SCp.dma_handle, + scp->request_bufflen,scp->SCp.Message); + if (scp->SCp.buffer) + pci_unmap_single(ha->pdev,(dma_addr_t)scp->SCp.buffer, + 16,PCI_DMA_FROMDEVICE); +#endif if (ha->status == S_OK) { scp->SCp.Status = S_OK; scp->SCp.Message = ha->info; @@ -3474,12 +3684,12 @@ scp->SCp.sent_command)); /* special commands GDT_CLUST_INFO/GDT_MOUNT ? */ if (scp->SCp.sent_command == GDT_CLUST_INFO) { - ha->hdr[scp->device->id].cluster_type = (unchar)ha->info; - if (!(ha->hdr[scp->device->id].cluster_type & + ha->hdr[t].cluster_type = (unchar)ha->info; + if (!(ha->hdr[t].cluster_type & CLUSTER_MOUNTED)) { /* NOT MOUNTED -> MOUNT */ scp->SCp.sent_command = GDT_MOUNT; - if (ha->hdr[scp->device->id].cluster_type & + if (ha->hdr[t].cluster_type & CLUSTER_RESERVED) { /* cluster drive RESERVED (on the other node) */ scp->SCp.phase = -2; /* reservation conflict */ @@ -3489,11 +3699,11 @@ } } else { if (scp->SCp.sent_command == GDT_MOUNT) { - ha->hdr[scp->device->id].cluster_type |= CLUSTER_MOUNTED; - ha->hdr[scp->device->id].media_changed = TRUE; + ha->hdr[t].cluster_type |= CLUSTER_MOUNTED; + ha->hdr[t].media_changed = TRUE; } else if (scp->SCp.sent_command == GDT_UNMOUNT) { - ha->hdr[scp->device->id].cluster_type &= ~CLUSTER_MOUNTED; - ha->hdr[scp->device->id].media_changed = TRUE; + ha->hdr[t].cluster_type &= ~CLUSTER_MOUNTED; + ha->hdr[t].media_changed = TRUE; } scp->SCp.sent_command = -1; } @@ -3503,21 +3713,13 @@ } else { /* RESERVE/RELEASE ? */ if (scp->cmnd[0] == RESERVE) { - ha->hdr[scp->device->id].cluster_type |= CLUSTER_RESERVED; + ha->hdr[t].cluster_type |= CLUSTER_RESERVED; } else if (scp->cmnd[0] == RELEASE) { - ha->hdr[scp->device->id].cluster_type &= ~CLUSTER_RESERVED; + ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED; } scp->result = DID_OK << 16; scp->sense_buffer[0] = 0; } - } else if (ha->status == S_BSY) { - TRACE2(("Controller busy -> retry !\n")); - scp->SCp.Status = S_BSY; - scp->SCp.Message = ha->info; - if (scp->SCp.sent_command == GDT_MOUNT) - scp->SCp.sent_command = GDT_CLUST_INFO; - /* retry */ - return 2; } else { scp->SCp.Status = ha->status; scp->SCp.Message = ha->info; @@ -3538,10 +3740,10 @@ scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); } else if (service == CACHESERVICE) { if (ha->status == S_CACHE_UNKNOWN && - (ha->hdr[scp->device->id].cluster_type & + (ha->hdr[t].cluster_type & CLUSTER_RESERVE_STATE) == CLUSTER_RESERVE_STATE) { /* bus reset -> force GDT_CLUST_INFO */ - ha->hdr[scp->device->id].cluster_type &= ~CLUSTER_RESERVED; + ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED; } memset((char*)scp->sense_buffer,0,16); if (ha->status == (ushort)S_CACHE_RESERV) { @@ -3560,7 +3762,7 @@ ha->dvr.eu.sync.service = service; ha->dvr.eu.sync.status = ha->status; ha->dvr.eu.sync.info = ha->info; - ha->dvr.eu.sync.hostdrive = scp->device->id; + ha->dvr.eu.sync.hostdrive = t; if (ha->status >= 0x8000) gdth_store_event(ha, ES_SYNC, 0, &ha->dvr); else @@ -3765,7 +3967,7 @@ cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; cmdp->u.screen.su.msg.msg_handle= MSG_INV_HANDLE; - cmdp->u.screen.su.msg.msg_addr = virt_to_bus(msg); + cmdp->u.screen.su.msg.msg_addr = ha->scratch_phys; ha->scratch_busy = TRUE; ha->cmd_offs_dpmem = 0; ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) @@ -4028,8 +4230,8 @@ break; if (gdth_search_isa(isa_bios)) { /* controller found */ shp = scsi_register(shtp,sizeof(gdth_ext_str)); - if(shp == NULL) - continue; + if (shp == NULL) + continue; ha = HADATA(shp); if (!gdth_init_isa(isa_bios,ha)) { @@ -4076,11 +4278,15 @@ NUMDATA(shp)->busnum= 0; ha->pccb = CMDDATA(shp); -#if LINUX_VERSION_CODE >= 0x020322 - ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, - GDTH_SCRATCH_ORD); + ha->ccb_phys = 0L; +#if LINUX_VERSION_CODE >= 0x020400 + ha->pdev = NULL; + ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, + &ha->scratch_phys); #else ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); + if (ha->pscratch) + ha->scratch_phys = virt_to_bus(ha->pscratch); #endif ha->scratch_busy = FALSE; ha->req_first = NULL; @@ -4095,12 +4301,14 @@ printk("GDT-ISA: Error during device scan\n"); --gdth_ctr_count; --gdth_ctr_vcount; - if (ha->pscratch != NULL) -#if LINUX_VERSION_CODE >= 0x020322 - free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD); + if (ha->pscratch != NULL) { +#if LINUX_VERSION_CODE >= 0x020400 + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); #else scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); #endif + } #if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,ha); #else @@ -4145,8 +4353,8 @@ break; if (gdth_search_eisa(eisa_slot)) { /* controller found */ shp = scsi_register(shtp,sizeof(gdth_ext_str)); - if(shp == NULL) - continue; + if (shp == NULL) + continue; ha = HADATA(shp); if (!gdth_init_eisa(eisa_slot,ha)) { @@ -4180,11 +4388,19 @@ NUMDATA(shp)->hanum)); ha->pccb = CMDDATA(shp); -#if LINUX_VERSION_CODE >= 0x020322 - ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, - GDTH_SCRATCH_ORD); + ha->ccb_phys = 0L; +#if LINUX_VERSION_CODE >= 0x020400 + ha->pdev = NULL; + ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, + &ha->scratch_phys); + ha->ccb_phys = + pci_map_single(ha->pdev,ha->pccb, + sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); #else ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); + if (ha->pscratch) + ha->scratch_phys = virt_to_bus(ha->pscratch); + ha->ccb_phys = virt_to_bus(ha->pccb); #endif ha->scratch_busy = FALSE; ha->req_first = NULL; @@ -4199,12 +4415,16 @@ printk("GDT-EISA: Error during device scan\n"); --gdth_ctr_count; --gdth_ctr_vcount; - if (ha->pscratch != NULL) -#if LINUX_VERSION_CODE >= 0x020322 - free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD); + if (ha->pscratch != NULL) { +#if LINUX_VERSION_CODE >= 0x020400 + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); + pci_unmap_single(ha->pdev,ha->ccb_phys, + sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); #else scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); #endif + } #if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,ha); #else @@ -4252,14 +4472,14 @@ gdth_pci_str pcistr[MAXHA]; cnt = gdth_search_pci(pcistr); - printk("GDT: Found %d PCI Storage RAID Controllers\n",cnt); + printk("GDT: Found %d PCI Storage RAID Controllers\n",cnt); gdth_sort_pci(pcistr,cnt); for (ctr = 0; ctr < cnt; ++ctr) { if (gdth_ctr_count >= MAXHA) break; shp = scsi_register(shtp,sizeof(gdth_ext_str)); - if(shp == NULL) - continue; + if (shp == NULL) + continue; ha = HADATA(shp); if (!gdth_init_pci(&pcistr[ctr],ha)) { @@ -4293,11 +4513,14 @@ NUMDATA(shp)->busnum= 0; ha->pccb = CMDDATA(shp); -#if LINUX_VERSION_CODE >= 0x020322 - ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, - GDTH_SCRATCH_ORD); + ha->ccb_phys = 0L; +#if LINUX_VERSION_CODE >= 0x020400 + ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, + &ha->scratch_phys); #else ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); + if (ha->pscratch) + ha->scratch_phys = virt_to_bus(ha->pscratch); #endif ha->scratch_busy = FALSE; ha->req_first = NULL; @@ -4312,12 +4535,14 @@ printk("GDT-PCI: Error during device scan\n"); --gdth_ctr_count; --gdth_ctr_vcount; - if (ha->pscratch != NULL) -#if LINUX_VERSION_CODE >= 0x020322 - free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD); + if (ha->pscratch != NULL) { +#if LINUX_VERSION_CODE >= 0x020400 + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); #else scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); #endif + } #if LINUX_VERSION_CODE >= 0x010346 free_irq(ha->irq,ha); #else @@ -4365,6 +4590,9 @@ gdth_timer.function = gdth_timeout; add_timer(&gdth_timer); #endif +#ifdef GDTH_IOCTL_CHRDEV + major = register_chrdev(0,"gdth",&gdth_fops); +#endif #if LINUX_VERSION_CODE >= 0x020100 register_reboot_notifier(&gdth_notifier); #endif @@ -4399,8 +4627,12 @@ free_dma(shp->dma_channel); } #endif -#if LINUX_VERSION_CODE >= 0x020322 - free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD); +#if LINUX_VERSION_CODE >= 0x020400 + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); + if (ha->ccb_phys) + pci_unmap_single(ha->pdev,ha->ccb_phys, + sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); #else scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH); #endif @@ -4412,6 +4644,9 @@ #ifdef GDTH_STATISTICS del_timer(&gdth_timer); #endif +#ifdef GDTH_IOCTL_CHRDEV + unregister_chrdev(major,"gdth"); +#endif #if LINUX_VERSION_CODE >= 0x020100 unregister_reboot_notifier(&gdth_notifier); #endif @@ -4507,15 +4742,24 @@ unchar b; TRACE2(("gdth_eh_bus_reset()\n")); +#if LINUX_VERSION_CODE >= 0x02053C hanum = NUMDATA(scp->device->host)->hanum; b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; +#else + hanum = NUMDATA(scp->host)->hanum; + b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel; +#endif ha = HADATA(gdth_ctr_tab[hanum]); /* clear command tab */ GDTH_LOCK_HA(ha, flags); for (i = 0; i < GDTH_MAXCMDS; ++i) { cmnd = ha->cmd_tab[i].cmnd; +#if LINUX_VERSION_CODE >= 0x02053C if (!SPECIAL_SCP(cmnd) && cmnd->device->channel == b) +#else + if (!SPECIAL_SCP(cmnd) && cmnd->channel == b) +#endif ha->cmd_tab[i].cmnd = UNUSED_CMND; } GDTH_UNLOCK_HA(ha, flags); @@ -4558,16 +4802,31 @@ } #endif -int gdth_bios_param(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int *ip) + +#if LINUX_VERSION_CODE >= 0x020503 +int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip) +#elif LINUX_VERSION_CODE >= 0x010300 +int gdth_bios_param(Disk *disk,kdev_t dev,int *ip) +#else +int gdth_bios_param(Disk *disk,int dev,int *ip) +#endif { unchar b, t; int hanum; gdth_ha_str *ha; + struct scsi_device *sd; + unsigned capacity; - hanum = NUMDATA(sdev->host)->hanum; - b = virt_ctr ? NUMDATA(sdev->host)->busnum : sdev->channel; - t = sdev->id; +#if LINUX_VERSION_CODE >= 0x020503 + sd = sdev; + capacity = cap; +#else + sd = disk->device; + capacity = disk->capacity; +#endif + hanum = NUMDATA(sd->host)->hanum; + b = virt_ctr ? NUMDATA(sd->host)->busnum : sd->channel; + t = sd->id; TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t)); ha = HADATA(gdth_ctr_tab[hanum]); @@ -4592,14 +4851,19 @@ int hanum; int priority; - TRACE(("gdth_queuecommand() cmd 0x%x id %d lun %d\n", - scp->cmnd[0],scp->device->id,scp->lun)); + TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0])); scp->scsi_done = (void *)done; scp->SCp.have_data_in = 1; scp->SCp.phase = -1; scp->SCp.sent_command = -1; + scp->SCp.Status = GDTH_MAP_NONE; + scp->SCp.buffer = (struct scatterlist *)NULL; +#if LINUX_VERSION_CODE >= 0x02053C hanum = NUMDATA(scp->device->host)->hanum; +#else + hanum = NUMDATA(scp->host)->hanum; +#endif #ifdef GDTH_STATISTICS ++act_ios; #endif @@ -4615,6 +4879,667 @@ return 0; } +#ifdef GDTH_IOCTL_CHRDEV +static int gdth_open(struct inode *inode, struct file *filep) +{ + TRACE(("gdth_open()\n")); + return 0; +} + +static int gdth_close(struct inode *inode, struct file *filep) +{ + TRACE(("gdth_close()\n")); + return 0; +} + +static int gdth_ioctl(struct inode *inode, struct file *filep, + unsigned int cmd, unsigned long arg) +{ + gdth_ha_str *ha; +#if LINUX_VERSION_CODE >= 0x020503 + Scsi_Request *srp; + Scsi_Cmnd *scp; + Scsi_Device *sdev; +#elif LINUX_VERSION_CODE >= 0x020322 + Scsi_Cmnd *scp; + Scsi_Device *sdev; +#else + Scsi_Cmnd scp; + Scsi_Device sdev; +#endif + ulong flags; + char cmnd[MAX_COMMAND_SIZE]; + memset(cmnd, 0xff, 12); + + TRACE(("gdth_ioctl() cmd 0x%x\n", cmd)); + + switch (cmd) { + case GDTIOCTL_CTRCNT: + { + int cnt = gdth_ctr_count; + put_user(cnt, (int *)arg); + break; + } + + case GDTIOCTL_DRVERS: + { + int ver = (GDTH_VERSION<<8) | GDTH_SUBVERSION; + put_user(ver, (int *)arg); + break; + } + + case GDTIOCTL_OSVERS: + { + gdth_ioctl_osvers osv; + + osv.version = (unchar)(LINUX_VERSION_CODE >> 16); + osv.subversion = (unchar)(LINUX_VERSION_CODE >> 8); + osv.revision = (ushort)(LINUX_VERSION_CODE & 0xff); + copy_to_user((char *)arg, &osv, sizeof(gdth_ioctl_osvers)); + break; + } + + case GDTIOCTL_CTRTYPE: + { + gdth_ioctl_ctrtype ctrt; + + if (copy_from_user(&ctrt, (char *)arg, sizeof(gdth_ioctl_ctrtype)) || + ctrt.ionode >= gdth_ctr_count) + return -EFAULT; + ha = HADATA(gdth_ctr_tab[ctrt.ionode]); + if (ha->type == GDT_ISA || ha->type == GDT_EISA) { + ctrt.type = (unchar)((ha->stype>>20) - 0x10); + } else { + if (ha->type != GDT_PCIMPR) { + ctrt.type = (unchar)((ha->stype<<4) + 6); + } else { + ctrt.type = + (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe); + if (ha->stype >= 0x300) + ctrt.ext_type = 0x6000 | ha->subdevice_id; + else + ctrt.ext_type = 0x6000 | ha->stype; + } + ctrt.device_id = ha->stype; + ctrt.sub_device_id = ha->subdevice_id; + } + ctrt.info = ha->brd_phys; + ctrt.oem_id = ha->oem_id; + if (copy_to_user((char *)arg, &ctrt, sizeof(gdth_ioctl_ctrtype))) + return -EFAULT; + break; + } + + case GDTIOCTL_GENERAL: + { + gdth_ioctl_general gen; + char *buf = NULL; + ulong32 paddr; + int hanum; + + if (copy_from_user(&gen, (char *)arg, sizeof(gdth_ioctl_general)) || + gen.ionode >= gdth_ctr_count) + return -EFAULT; + hanum = gen.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); + if (gen.data_len + gen.sense_len != 0) { + if (!(buf = gdth_ioctl_alloc(hanum, gen.data_len + gen.sense_len, + FALSE, &paddr))) + return -EFAULT; + if (copy_from_user(buf, (char *)arg + sizeof(gdth_ioctl_general), + gen.data_len + gen.sense_len)) { + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + return -EFAULT; + } + + if (gen.command.OpCode == GDT_IOCTL) { + gen.command.u.ioctl.p_param = paddr; + } else if (gen.command.Service == CACHESERVICE) { + if (ha->cache_feat & SCATTER_GATHER) { + gen.command.u.cache.DestAddr = 0xffffffff; + gen.command.u.cache.sg_canz = 1; + gen.command.u.cache.sg_lst[0].sg_ptr = paddr; + gen.command.u.cache.sg_lst[0].sg_len = gen.data_len; + gen.command.u.cache.sg_lst[1].sg_len = 0; + } else { + gen.command.u.cache.DestAddr = paddr; + gen.command.u.cache.sg_canz = 0; + } + } else if (gen.command.Service == SCSIRAWSERVICE) { + if (ha->raw_feat & SCATTER_GATHER) { + gen.command.u.raw.sdata = 0xffffffff; + gen.command.u.raw.sg_ranz = 1; + gen.command.u.raw.sg_lst[0].sg_ptr = paddr; + gen.command.u.raw.sg_lst[0].sg_len = gen.data_len; + gen.command.u.raw.sg_lst[1].sg_len = 0; + } else { + gen.command.u.raw.sdata = paddr; + gen.command.u.raw.sg_ranz = 0; + } + gen.command.u.raw.sense_data = paddr + gen.data_len; + + } else { + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + return -EFAULT; + } + } + +#if LINUX_VERSION_CODE >= 0x020503 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + srp = scsi_allocate_request(sdev); + if (!srp) + return -ENOMEM; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; + gdth_do_req(srp, &gen.command, cmnd, gen.timeout); + gen.status = srp->sr_command->SCp.Status; + gen.info = srp->sr_command->SCp.Message; + scsi_release_request(srp); + scsi_free_host_dev(sdev); +#elif LINUX_VERSION_CODE >= 0x020322 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + scp = scsi_allocate_device(sdev, 1, FALSE); + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; + gdth_do_cmd(scp, &gen.command, cmnd, gen.timeout); + gen.status = scp->SCp.Status; + gen.info = scp->SCp.Message; + scsi_release_command(scp); + scsi_free_host_dev(sdev); +#else + memset(&sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + sdev.host = scp.host = gdth_ctr_tab[hanum]; + sdev.id = scp.target = sdev.host->this_id; + scp.device = &sdev; + gdth_do_cmd(&scp, &gen.command, cmnd, gen.timeout); + gen.status = scp.SCp.Status; + gen.info = scp.SCp.Message; +#endif + + if (copy_to_user((char *)arg + sizeof(gdth_ioctl_general), buf, + gen.data_len + gen.sense_len)) { + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + return -EFAULT; + } + if (copy_to_user((char *)arg, &gen, + sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) { + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + return -EFAULT; + } + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + break; + } + + case GDTIOCTL_EVENT: + { + gdth_ioctl_event evt; + gdth_ha_str *ha; + ulong flags; + + if (copy_from_user(&evt, (char *)arg, sizeof(gdth_ioctl_event)) || + evt.ionode >= gdth_ctr_count) + return -EFAULT; + ha = HADATA(gdth_ctr_tab[evt.ionode]); + + if (evt.erase == 0xff) { + if (evt.event.event_source == ES_TEST) + evt.event.event_data.size=sizeof(evt.event.event_data.eu.test); + else if (evt.event.event_source == ES_DRIVER) + evt.event.event_data.size=sizeof(evt.event.event_data.eu.driver); + else if (evt.event.event_source == ES_SYNC) + evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync); + else + evt.event.event_data.size=sizeof(evt.event.event_data.eu.async); + GDTH_LOCK_HA(ha, flags); + gdth_store_event(ha, evt.event.event_source, evt.event.event_idx, + &evt.event.event_data); + GDTH_UNLOCK_HA(ha, flags); + } else if (evt.erase == 0xfe) { + gdth_clear_events(); + } else if (evt.erase == 0) { + evt.handle = gdth_read_event(ha, evt.handle, &evt.event); + } else { + gdth_readapp_event(ha, evt.erase, &evt.event); + } + if (copy_to_user((char *)arg, &evt, sizeof(gdth_ioctl_event))) + return -EFAULT; + break; + } + + case GDTIOCTL_LOCKDRV: + { + gdth_ioctl_lockdrv ldrv; + unchar i, j; + + if (copy_from_user(&ldrv, (char *)arg, sizeof(gdth_ioctl_lockdrv)) || + ldrv.ionode >= gdth_ctr_count) + return -EFAULT; + ha = HADATA(gdth_ctr_tab[ldrv.ionode]); + + for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) { + j = ldrv.drives[i]; + if (j >= MAX_HDRIVES || !ha->hdr[j].present) + continue; + if (ldrv.lock) { + GDTH_LOCK_HA(ha, flags); + ha->hdr[j].lock = 1; + GDTH_UNLOCK_HA(ha, flags); + gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j); + gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j); + } else { + GDTH_LOCK_HA(ha, flags); + ha->hdr[j].lock = 0; + GDTH_UNLOCK_HA(ha, flags); + gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j); + gdth_next(ldrv.ionode); + } + } + break; + } + + case GDTIOCTL_LOCKCHN: + { + gdth_ioctl_lockchn lchn; + unchar i, j; + + if (copy_from_user(&lchn, (char *)arg, sizeof(gdth_ioctl_lockchn)) || + lchn.ionode >= gdth_ctr_count) + return -EFAULT; + ha = HADATA(gdth_ctr_tab[lchn.ionode]); + + i = lchn.channel; + if (i < ha->bus_cnt) { + if (lchn.lock) { + GDTH_LOCK_HA(ha, flags); + ha->raw[i].lock = 1; + GDTH_UNLOCK_HA(ha, flags); + for (j = 0; j < ha->tid_cnt; ++j) { + gdth_wait_completion(lchn.ionode, i, j); + gdth_stop_timeout(lchn.ionode, i, j); + } + } else { + GDTH_LOCK_HA(ha, flags); + ha->raw[i].lock = 0; + GDTH_UNLOCK_HA(ha, flags); + for (j = 0; j < ha->tid_cnt; ++j) { + gdth_start_timeout(lchn.ionode, i, j); + gdth_next(lchn.ionode); + } + } + } + break; + } + + case GDTIOCTL_RESCAN: + { + gdth_ioctl_rescan rsc; + gdth_cmd_str cmd; + ushort i, status, hdr_cnt; + ulong32 info; + int hanum, cyls, hds, secs; + + if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) || + rsc.ionode >= gdth_ctr_count) + return -EFAULT; + hanum = rsc.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); + +#if LINUX_VERSION_CODE >= 0x020503 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + srp = scsi_allocate_request(sdev); + if (!srp) + return -ENOMEM; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; +#elif LINUX_VERSION_CODE >= 0x020322 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + scp = scsi_allocate_device(sdev, 1, FALSE); + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; +#else + memset(&sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + sdev.host = scp.host = gdth_ctr_tab[hanum]; + sdev.id = scp.target = sdev.host->this_id; + scp.device = &sdev; +#endif + + if (rsc.flag == 0) { + /* old method: re-init. cache service */ + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_INIT; + cmd.u.cache.DeviceNo = LINUX_OS; +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(srp, &cmd, cmnd, 30); + status = (ushort)srp->sr_command->SCp.Status; + info = (ulong32)srp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= 0x020322 + gdth_do_cmd(scp, &cmd, cmnd, 30); + status = (ushort)scp->SCp.Status; + info = (ulong32)scp->SCp.Message; +#else + gdth_do_cmd(&scp, &cmd, cmnd, 30); + status = (ushort)scp.SCp.Status; + info = (ulong32)scp.SCp.Message; +#endif + i = 0; + hdr_cnt = (status == S_OK ? (ushort)info : 0); + } else { + i = rsc.hdr_no; + hdr_cnt = i + 1; + } + for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) { + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_INFO; + cmd.u.cache.DeviceNo = i; +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(srp, &cmd, cmnd, 30); + status = (ushort)srp->sr_command->SCp.Status; + info = (ulong32)srp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= 0x020322 + gdth_do_cmd(scp, &cmd, cmnd, 30); + status = (ushort)scp->SCp.Status; + info = (ulong32)scp->SCp.Message; +#else + gdth_do_cmd(&scp, &cmd, cmnd, 30); + status = (ushort)scp.SCp.Status; + info = (ulong32)scp.SCp.Message; +#endif + GDTH_LOCK_HA(ha, flags); + rsc.hdr_list[i].bus = ha->virt_bus; + rsc.hdr_list[i].target = i; + rsc.hdr_list[i].lun = 0; + if (status != S_OK) { + ha->hdr[i].present = FALSE; + } else { + ha->hdr[i].present = TRUE; + ha->hdr[i].size = info; + /* evaluate mapping */ + ha->hdr[i].size &= ~SECS32; + gdth_eval_mapping(ha->hdr[i].size,&cyls,&hds,&secs); + ha->hdr[i].heads = hds; + ha->hdr[i].secs = secs; + /* round size */ + ha->hdr[i].size = cyls * hds * secs; + } + GDTH_UNLOCK_HA(ha, flags); + if (status != S_OK) + continue; + + /* devtype, cluster info, R/W attribs */ + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_DEVTYPE; + cmd.u.cache.DeviceNo = i; +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(srp, &cmd, cmnd, 30); + status = (ushort)srp->sr_command->SCp.Status; + info = (ulong32)srp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= 0x020322 + gdth_do_cmd(scp, &cmd, cmnd, 30); + status = (ushort)scp->SCp.Status; + info = (ulong32)scp->SCp.Message; +#else + gdth_do_cmd(&scp, &cmd, cmnd, 30); + status = (ushort)scp.SCp.Status; + info = (ulong32)scp.SCp.Message; +#endif + GDTH_LOCK_HA(ha, flags); + ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0); + GDTH_UNLOCK_HA(ha, flags); + + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_CLUST_INFO; + cmd.u.cache.DeviceNo = i; +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(srp, &cmd, cmnd, 30); + status = (ushort)srp->sr_command->SCp.Status; + info = (ulong32)srp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= 0x020322 + gdth_do_cmd(scp, &cmd, cmnd, 30); + status = (ushort)scp->SCp.Status; + info = (ulong32)scp->SCp.Message; +#else + gdth_do_cmd(&scp, &cmd, cmnd, 30); + status = (ushort)scp.SCp.Status; + info = (ulong32)scp.SCp.Message; +#endif + GDTH_LOCK_HA(ha, flags); + ha->hdr[i].cluster_type = + ((status == S_OK && !shared_access) ? (ushort)info : 0); + GDTH_UNLOCK_HA(ha, flags); + rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type; + + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_RW_ATTRIBS; + cmd.u.cache.DeviceNo = i; +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(srp, &cmd, cmnd, 30); + status = (ushort)srp->sr_command->SCp.Status; + info = (ulong32)srp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= 0x020322 + gdth_do_cmd(scp, &cmd, cmnd, 30); + status = (ushort)scp->SCp.Status; + info = (ulong32)scp->SCp.Message; +#else + gdth_do_cmd(&scp, &cmd, cmnd, 30); + status = (ushort)scp.SCp.Status; + info = (ulong32)scp.SCp.Message; +#endif + GDTH_LOCK_HA(ha, flags); + ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0); + GDTH_UNLOCK_HA(ha, flags); + } +#if LINUX_VERSION_CODE >= 0x020503 + scsi_release_request(srp); + scsi_free_host_dev(sdev); +#elif LINUX_VERSION_CODE >= 0x020322 + scsi_release_command(scp); + scsi_free_host_dev(sdev); +#endif + + if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan))) + return -EFAULT; + break; + } + + case GDTIOCTL_HDRLIST: + { + gdth_ioctl_rescan rsc; + gdth_cmd_str cmd; + gdth_ha_str *ha; + unchar i; + int hanum; + + if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) || + rsc.ionode >= gdth_ctr_count) + return -EFAULT; + hanum = rsc.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); + +#if LINUX_VERSION_CODE >= 0x020503 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + srp = scsi_allocate_request(sdev); + if (!srp) + return -ENOMEM; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; +#elif LINUX_VERSION_CODE >= 0x020322 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + scp = scsi_allocate_device(sdev, 1, FALSE); + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; +#else + memset(&sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + sdev.host = scp.host = gdth_ctr_tab[hanum]; + sdev.id = scp.target = sdev.host->this_id; + scp.device = &sdev; +#endif + + for (i = 0; i < MAX_HDRIVES; ++i) { + if (!ha->hdr[i].present) { + rsc.hdr_list[i].bus = 0xff; + continue; + } + rsc.hdr_list[i].bus = ha->virt_bus; + rsc.hdr_list[i].target = i; + rsc.hdr_list[i].lun = 0; + rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type; + if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) { + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_CLUST_INFO; + cmd.u.cache.DeviceNo = i; +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(srp, &cmd, cmnd, 30); + if (srp->sr_command->SCp.Status == S_OK) + rsc.hdr_list[i].cluster_type = srp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= 0x020322 + gdth_do_cmd(scp, &cmd, cmnd, 30); + if (scp->SCp.Status == S_OK) + rsc.hdr_list[i].cluster_type = scp->SCp.Message; +#else + gdth_do_cmd(&scp, &cmd, cmnd, 30); + if (scp.SCp.Status == S_OK) + rsc.hdr_list[i].cluster_type = scp.SCp.Message; +#endif + } + } +#if LINUX_VERSION_CODE >= 0x020503 + scsi_release_request(srp); + scsi_free_host_dev(sdev); +#elif LINUX_VERSION_CODE >= 0x020322 + scsi_release_command(scp); + scsi_free_host_dev(sdev); +#endif + + if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan))) + return -EFAULT; + break; + } + + case GDTIOCTL_RESET_BUS: + { + gdth_ioctl_reset res; + int hanum, rval; + + if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) || + res.ionode >= gdth_ctr_count) + return -EFAULT; + hanum = res.ionode; + + /* Because we need a Scsi_Cmnd struct., we make a scsi_allocate device also for kernels >=2.5.x */ +#if LINUX_VERSION_CODE >= 0x02053C + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + scp = scsi_get_command(sdev, GFP_KERNEL); + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; + scp->device->channel = virt_ctr ? 0 : res.number; + rval = gdth_eh_bus_reset(scp); + res.status = (rval == SUCCESS ? S_OK : S_GENERR); + scsi_put_command(scp); + scsi_free_host_dev(sdev); +#elif LINUX_VERSION_CODE >= 0x020322 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); +#if LINUX_VERSION_CODE >= 0x020503 + scp = scsi_allocate_device(sdev, 1); +#else + scp = scsi_allocate_device(sdev, 1, FALSE); +#endif + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; + scp->channel = virt_ctr ? 0 : res.number; + rval = gdth_eh_bus_reset(scp); + res.status = (rval == SUCCESS ? S_OK : S_GENERR); + scsi_release_command(scp); + scsi_free_host_dev(sdev); +#elif LINUX_VERSION_CODE >= 0x02015F + memset(&sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + sdev.host = scp.host = gdth_ctr_tab[hanum]; + sdev.id = scp.target = sdev.host->this_id; + scp.device = &sdev; + scp.channel = virt_ctr ? 0 : res.number; + rval = gdth_eh_bus_reset(&scp); + res.status = (rval == SUCCESS ? S_OK : S_GENERR); +#else + res.status = S_OK; +#endif + if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset))) + return -EFAULT; + break; + } + + case GDTIOCTL_RESET_DRV: + { + gdth_ioctl_reset res; + gdth_cmd_str cmd; + int hanum; + + if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) || + res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES) + return -EFAULT; + hanum = res.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); + + if (!ha->hdr[res.number].present) + return 0; + cmd.Service = CACHESERVICE; + cmd.OpCode = GDT_CLUST_RESET; + cmd.u.cache.DeviceNo = res.number; +#if LINUX_VERSION_CODE >= 0x020503 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + srp = scsi_allocate_request(sdev); + if (!srp) + return -ENOMEM; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; + gdth_do_req(srp, &cmd, cmnd, 30); + res.status = (ushort)srp->sr_command->SCp.Status; + scsi_release_request(srp); + scsi_free_host_dev(sdev); +#elif LINUX_VERSION_CODE >= 0x020322 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + scp = scsi_allocate_device(sdev, 1, FALSE); + if (!scp) + return -ENOMEM; + scp->cmd_len = 12; + scp->use_sg = 0; + gdth_do_cmd(scp, &cmd, cmnd, 30); + res.status = (ushort)scp->SCp.Status; + scsi_release_command(scp); + scsi_free_host_dev(sdev); +#else + memset(&sdev,0,sizeof(Scsi_Device)); + memset(&scp, 0,sizeof(Scsi_Cmnd)); + sdev.host = scp.host = gdth_ctr_tab[hanum]; + sdev.id = scp.target = sdev.host->this_id; + scp.device = &sdev; + gdth_do_cmd(&scp, &cmd, cmnd, 30); + res.status = (ushort)scp.SCp.Status; +#endif + if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset))) + return -EFAULT; + break; + } + + default: + break; + } + return 0; +} +#endif + #if LINUX_VERSION_CODE >= 0x010300 /* flush routine */ static void gdth_flush(int hanum) @@ -4622,7 +5547,10 @@ int i; gdth_ha_str *ha; gdth_cmd_str gdtcmd; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + Scsi_Request *srp; + Scsi_Device *sdev; +#elif LINUX_VERSION_CODE >= 0x020322 Scsi_Cmnd *scp; Scsi_Device *sdev; #else @@ -4635,9 +5563,18 @@ TRACE2(("gdth_flush() hanum %d\n",hanum)); ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_get_command(sdev, GFP_KERNEL); + srp = scsi_allocate_request(sdev); + if (!srp) + return; + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; +#elif LINUX_VERSION_CODE >= 0x020322 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + scp = scsi_allocate_device(sdev, 1, FALSE); + if (!scp) + return; scp->cmd_len = 12; scp->use_sg = 0; #else @@ -4657,15 +5594,20 @@ gdtcmd.u.cache.BlockNo = 1; gdtcmd.u.cache.sg_canz = 0; TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i)); -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(srp, &gdtcmd, cmnd, 30); +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); #endif } } -#if LINUX_VERSION_CODE >= 0x020322 - scsi_put_command(scp); +#if LINUX_VERSION_CODE >= 0x020503 + scsi_release_request(srp); + scsi_free_host_dev(sdev); +#elif LINUX_VERSION_CODE >= 0x020322 + scsi_release_command(scp); scsi_free_host_dev(sdev); #endif } @@ -4680,7 +5622,10 @@ int hanum; #ifndef __alpha__ gdth_cmd_str gdtcmd; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + Scsi_Request *srp; + Scsi_Device *sdev; +#elif LINUX_VERSION_CODE >= 0x020322 Scsi_Cmnd *scp; Scsi_Device *sdev; #else @@ -4702,6 +5647,7 @@ } halt_called = TRUE; #endif + printk("GDT: Flushing all host drives .. "); for (hanum = 0; hanum < gdth_ctr_count; ++hanum) { gdth_flush(hanum); @@ -4709,28 +5655,48 @@ #ifndef __alpha__ /* controller reset */ memset(cmnd, 0xff, MAX_COMMAND_SIZE); -#if LINUX_VERSION_CODE >= 0x020322 + gdtcmd.BoardNode = LOCALBOARD; + gdtcmd.Service = CACHESERVICE; + gdtcmd.OpCode = GDT_RESET; + TRACE2(("gdth_halt(): reset controller %d\n", hanum)); +#if LINUX_VERSION_CODE >= 0x020503 sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_get_command(sdev, GFP_KERNEL); + srp = scsi_allocate_request(sdev); + if (!srp) { +#if LINUX_VERSION_CODE >= 0x020100 + unregister_reboot_notifier(&gdth_notifier); + return NOTIFY_OK; +#else + return; +#endif + } + srp->sr_cmd_len = 12; + srp->sr_use_sg = 0; + gdth_do_req(srp, &gdtcmd, cmnd, 10); + scsi_release_request(srp); + scsi_free_host_dev(sdev); +#elif LINUX_VERSION_CODE >= 0x020322 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + scp = scsi_allocate_device(sdev, 1, FALSE); + if (!scp) { +#if LINUX_VERSION_CODE >= 0x020100 + unregister_reboot_notifier(&gdth_notifier); + return NOTIFY_OK; +#else + return; +#endif + } scp->cmd_len = 12; scp->use_sg = 0; + gdth_do_cmd(scp, &gdtcmd, cmnd, 10); + scsi_release_command(scp); + scsi_free_host_dev(sdev); #else memset(&sdev,0,sizeof(Scsi_Device)); memset(&scp, 0,sizeof(Scsi_Cmnd)); sdev.host = scp.host = gdth_ctr_tab[hanum]; sdev.id = scp.target = sdev.host->this_id; scp.device = &sdev; -#endif - - gdtcmd.BoardNode = LOCALBOARD; - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_RESET; - TRACE2(("gdth_halt(): reset controller %d\n", hanum)); -#if LINUX_VERSION_CODE >= 0x020322 - gdth_do_cmd(scp, &gdtcmd, cmnd, 10); - scsi_put_command(scp); - scsi_free_host_dev(sdev); -#else gdth_do_cmd(&scp, &gdtcmd, cmnd, 10); #endif #endif diff -urN linux-2.5.65-bk2/drivers/scsi/gdth.h linux-2.5.65-bk3/drivers/scsi/gdth.h --- linux-2.5.65-bk2/drivers/scsi/gdth.h Mon Mar 17 13:44:03 2003 +++ linux-2.5.65-bk3/drivers/scsi/gdth.h Mon Mar 31 12:41:42 2003 @@ -10,7 +10,7 @@ * * * - * $Id: gdth.h,v 1.46 2002/02/05 09:39:53 achim Exp $ + * $Id: gdth.h,v 1.48 2003/02/27 14:58:22 achim Exp $ */ #include @@ -29,16 +29,16 @@ /* defines, macros */ /* driver version */ -#define GDTH_VERSION_STR "2.05" +#define GDTH_VERSION_STR "2.07" #define GDTH_VERSION 2 -#define GDTH_SUBVERSION 5 +#define GDTH_SUBVERSION 7 /* protocol version */ #define PROTOCOL_VERSION 1 /* OEM IDs */ -#define OEM_ID_ICP 0x941c -#define OEM_ID_INTEL 0x8000 +#define OEM_ID_ICP 0x941c +#define OEM_ID_INTEL 0x8000 /* controller classes */ #define GDT_ISA 0x01 /* ISA controller */ @@ -134,12 +134,17 @@ #ifndef PCI_DEVICE_ID_VORTEX_GDTNEWRX /* new GDT Rx Controller */ -#define PCI_DEVICE_ID_VORTEX_GDTNEWRX 0x300 +#define PCI_DEVICE_ID_VORTEX_GDTNEWRX 0x300 #endif - + #ifndef PCI_DEVICE_ID_INTEL_SRC /* Intel Storage RAID Controller */ -#define PCI_DEVICE_ID_INTEL_SRC 0x600 +#define PCI_DEVICE_ID_INTEL_SRC 0x600 +#endif + +#ifndef PCI_DEVICE_ID_INTEL_SRC_XSCALE +/* Intel Storage RAID Controller */ +#define PCI_DEVICE_ID_INTEL_SRC_XSCALE 0x601 #endif /* limits */ @@ -153,8 +158,6 @@ #define MAXID 127 #define MAXLUN 8 #define MAXBUS 6 -#define MAX_HDRIVES 100 /* max. host drive count */ -#define MAX_LDRIVES 255 /* max. log. drive count */ #define MAX_EVENTS 100 /* event buffer count */ #define MAX_RES_ARGS 40 /* device reservation, must be a multiple of 4 */ @@ -254,6 +257,7 @@ #define CACHE_DRV_INFO 0x07 /* cache drive info */ #define BOARD_FEATURES 0x15 /* controller features */ #define BOARD_INFO 0x28 /* controller info */ +#define CACHE_READ_OEM_STRING_RECORD 0x84 /* read OEM string record */ #define HOST_GET 0x10001L /* get host drive list */ #define IO_CHANNEL 0x00020000L /* default IO channel */ #define INVALID_CHANNEL 0x0000ffffL /* invalid channel */ @@ -265,7 +269,7 @@ #define S_CACHE_UNKNOWN 12 /* cache serv.: drive unknown */ #define S_RAW_SCSI 12 /* raw serv.: target error */ #define S_RAW_ILL 0xff /* raw serv.: illegal */ -#define S_CACHE_RESERV -24 /* cache: reserv. conflict */ +#define S_CACHE_RESERV -24 /* cache: reserv. conflict */ /* timeout values */ #define INIT_RETRIES 100000 /* 100000 * 1ms = 100s */ @@ -292,10 +296,15 @@ #define MAILBOXREG 0x0c90 /* mailbox reg. (16 bytes) */ #define EISAREG 0x0cc0 /* EISA configuration */ +/* DMA memory mappings */ +#define GDTH_MAP_NONE 0 +#define GDTH_MAP_SINGLE 1 +#define GDTH_MAP_SG 2 +#define GDTH_MAP_IOCTL 3 + /* other defines */ #define LINUX_OS 8 /* used for cache optim. */ #define SCATTER_GATHER 1 /* s/g feature */ -#define GDTH_MAXSG 32 /* max. s/g elements */ #define SECS32 0x1f /* round capacity */ #define BIOS_ID_OFFS 0x10 /* offset contr-ID in ISABIOS */ #define LOCALBOARD 0 /* board node always 0 */ @@ -303,10 +312,7 @@ #define SPEZINDEX 1 /* cmd index unknown service */ #define GDT_WR_THROUGH 0x100 /* WRITE_THROUGH supported */ - -/* typedefs */ -typedef u32 ulong32; -#define PACKED __attribute__((packed)) +#include "gdth_ioctl.h" /* screenservice message */ typedef struct { @@ -535,6 +541,50 @@ unchar ld_error; /* error */ } PACKED gdth_cdrinfo_str; +/* OEM string */ +typedef struct { + ulong32 ctl_version; + ulong32 file_major_version; + ulong32 file_minor_version; + ulong32 buffer_size; + ulong32 cpy_count; + ulong32 ext_error; + ulong32 oem_id; + ulong32 board_id; +} PACKED gdth_oem_str_params; + +typedef struct { + unchar product_0_1_name[16]; + unchar product_4_5_name[16]; + unchar product_cluster_name[16]; + unchar product_reserved[16]; + unchar scsi_cluster_target_vendor_id[16]; + unchar cluster_raid_fw_name[16]; + unchar oem_brand_name[16]; + unchar oem_raid_type[16]; + unchar bios_type[13]; + unchar bios_title[50]; + unchar oem_company_name[37]; + ulong32 pci_id_1; + ulong32 pci_id_2; + unchar validation_status[80]; + unchar reserved_1[4]; + unchar scsi_host_drive_inquiry_vendor_id[16]; + unchar library_file_template[16]; + unchar reserved_2[16]; + unchar tool_name_1[32]; + unchar tool_name_2[32]; + unchar tool_name_3[32]; + unchar oem_contact_1[84]; + unchar oem_contact_2[84]; + unchar oem_contact_3[84]; +} PACKED gdth_oem_str; + +typedef struct { + gdth_oem_str_params params; + gdth_oem_str text; +} PACKED gdth_oem_str_ioctl; + /* board features */ typedef struct { unchar chaining; /* Chaining supported */ @@ -594,118 +644,6 @@ gdth_hentry_str entry[MAX_HDRIVES]; /* entries */ } PACKED gdth_hget_str; -/* scatter/gather element */ -typedef struct { - ulong32 sg_ptr; /* address */ - ulong32 sg_len; /* length */ -} PACKED gdth_sg_str; - -/* command structure */ -typedef struct { - ulong32 BoardNode; /* board node (always 0) */ - ulong32 CommandIndex; /* command number */ - ushort OpCode; /* the command (READ,..) */ - union { - struct { - ushort DeviceNo; /* number of cache drive */ - ulong32 BlockNo; /* block number */ - ulong32 BlockCnt; /* block count */ - ulong32 DestAddr; /* dest. addr. (if s/g: -1) */ - ulong32 sg_canz; /* s/g element count */ - gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */ - } PACKED cache; /* cache service cmd. str. */ - struct { - ushort param_size; /* size of p_param buffer */ - ulong32 subfunc; /* IOCTL function */ - ulong32 channel; /* device */ - ulong32 p_param; /* buffer */ - } PACKED ioctl; /* IOCTL command structure */ - struct { - ushort reserved; - union { - struct { - ulong32 msg_handle; /* message handle */ - ulong32 msg_addr; /* message buffer address */ - } PACKED msg; - unchar data[12]; /* buffer for rtc data, ... */ - } su; - } PACKED screen; /* screen service cmd. str. */ - struct { - ushort reserved; - ulong32 direction; /* data direction */ - ulong32 mdisc_time; /* disc. time (0: no timeout)*/ - ulong32 mcon_time; /* connect time(0: no to.) */ - ulong32 sdata; /* dest. addr. (if s/g: -1) */ - ulong32 sdlen; /* data length (bytes) */ - ulong32 clen; /* SCSI cmd. length(6,10,12) */ - unchar cmd[12]; /* SCSI command */ - unchar target; /* target ID */ - unchar lun; /* LUN */ - unchar bus; /* SCSI bus number */ - unchar priority; /* only 0 used */ - ulong32 sense_len; /* sense data length */ - ulong32 sense_data; /* sense data addr. */ - ulong32 link_p; /* linked cmds (not supp.) */ - ulong32 sg_ranz; /* s/g element count */ - gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */ - } PACKED raw; /* raw service cmd. struct. */ - } u; - /* additional variables */ - unchar Service; /* controller service */ - ushort Status; /* command result */ - ulong32 Info; /* additional information */ - Scsi_Cmnd *RequestBuffer; /* request buffer */ -} PACKED gdth_cmd_str; - -/* controller event structure */ -#define ES_ASYNC 1 -#define ES_DRIVER 2 -#define ES_TEST 3 -#define ES_SYNC 4 -typedef struct { - ushort size; /* size of structure */ - union { - char stream[16]; - struct { - ushort ionode; - ushort service; - ulong32 index; - } PACKED driver; - struct { - ushort ionode; - ushort service; - ushort status; - ulong32 info; - unchar scsi_coord[3]; - } PACKED async; - struct { - ushort ionode; - ushort service; - ushort status; - ulong32 info; - ushort hostdrive; - unchar scsi_coord[3]; - unchar sense_key; - } PACKED sync; - struct { - ulong32 l1, l2, l3, l4; - } PACKED test; - } eu; - ulong32 severity; - unchar event_string[256]; -} PACKED gdth_evt_data; - -typedef struct { - ulong32 first_stamp; - ulong32 last_stamp; - ushort same_count; - ushort event_source; - ushort event_idx; - unchar application; - unchar reserved; - gdth_evt_data event_data; -} PACKED gdth_evt_str; - /* DPRAM structures */ @@ -889,7 +827,9 @@ ulong32 brd_phys; /* slot number/BIOS address */ gdt6c_plx_regs *plx; /* PLX regs (new PCI contr.) */ gdth_cmd_str *pccb; /* address command structure */ + ulong32 ccb_phys; /* phys. address */ char *pscratch; /* scratch (DMA) buffer */ + ulong32 scratch_phys; /* phys. address */ unchar scratch_busy; /* in use? */ unchar scan_mode; /* current scan mode */ unchar irq; /* IRQ */ @@ -946,6 +886,10 @@ #if LINUX_VERSION_CODE >= 0x02015F spinlock_t smp_lock; #endif +#if LINUX_VERSION_CODE >= 0x020400 + struct pci_dev *pdev; +#endif + char oem_name[8]; } gdth_ha_str; /* structure for scsi_register(), SCSI bus != 0 */ @@ -1032,34 +976,145 @@ #endif const char *gdth_info(struct Scsi_Host *); +#if LINUX_VERSION_CODE >= 0x020501 int gdth_bios_param(struct scsi_device *,struct block_device *,sector_t,int *); int gdth_proc_info(char *,char **,off_t,int,int,int); int gdth_eh_abort(Scsi_Cmnd *scp); int gdth_eh_device_reset(Scsi_Cmnd *scp); int gdth_eh_bus_reset(Scsi_Cmnd *scp); int gdth_eh_host_reset(Scsi_Cmnd *scp); -#define GDTH { .proc_name = "gdth", \ - .proc_info = gdth_proc_info, \ - .name = "GDT SCSI Disk Array Controller",\ - .detect = gdth_detect, \ - .release = gdth_release, \ - .info = gdth_info, \ - .command = NULL, \ - .queuecommand = gdth_queuecommand, \ - .eh_abort_handler = gdth_eh_abort, \ - .eh_device_reset_handler = gdth_eh_device_reset, \ - .eh_bus_reset_handler = gdth_eh_bus_reset, \ - .eh_host_reset_handler = gdth_eh_host_reset, \ - .abort = gdth_abort, \ - .reset = gdth_reset, \ - .bios_param = gdth_bios_param, \ - .can_queue = GDTH_MAXCMDS, \ - .this_id = -1, \ - .sg_tablesize = GDTH_MAXSG, \ - .cmd_per_lun = GDTH_MAXC_P_L, \ - .present = 0, \ - .unchecked_isa_dma = 1, \ - .use_clustering = ENABLE_CLUSTERING } +#define GDTH { .proc_name = "gdth", \ + .proc_info = gdth_proc_info, \ + .name = "GDT SCSI Disk Array Controller",\ + .detect = gdth_detect, \ + .release = gdth_release, \ + .info = gdth_info, \ + .command = NULL, \ + .queuecommand = gdth_queuecommand, \ + .eh_abort_handler = gdth_eh_abort, \ + .eh_device_reset_handler = gdth_eh_device_reset, \ + .eh_bus_reset_handler = gdth_eh_bus_reset, \ + .eh_host_reset_handler = gdth_eh_host_reset, \ + .abort = NULL, \ + .reset = NULL, \ + .bios_param = gdth_bios_param, \ + .can_queue = GDTH_MAXCMDS, \ + .this_id = -1, \ + .sg_tablesize = GDTH_MAXSG, \ + .cmd_per_lun = GDTH_MAXC_P_L, \ + .present = 0, \ + .unchecked_isa_dma = 1, \ + .use_clustering = ENABLE_CLUSTERING} + +#elif LINUX_VERSION_CODE >= 0x020322 +int gdth_bios_param(Disk *,kdev_t,int *); +int gdth_proc_info(char *,char **,off_t,int,int,int); +int gdth_eh_abort(Scsi_Cmnd *scp); +int gdth_eh_device_reset(Scsi_Cmnd *scp); +int gdth_eh_bus_reset(Scsi_Cmnd *scp); +int gdth_eh_host_reset(Scsi_Cmnd *scp); +#define GDTH { proc_name: "gdth", \ + proc_info: gdth_proc_info, \ + name: "GDT SCSI Disk Array Controller",\ + detect: gdth_detect, \ + release: gdth_release, \ + info: gdth_info, \ + command: NULL, \ + queuecommand: gdth_queuecommand, \ + eh_abort_handler: gdth_eh_abort, \ + eh_device_reset_handler: gdth_eh_device_reset, \ + eh_bus_reset_handler: gdth_eh_bus_reset, \ + eh_host_reset_handler: gdth_eh_host_reset, \ + abort: gdth_abort, \ + reset: gdth_reset, \ + bios_param: gdth_bios_param, \ + can_queue: GDTH_MAXCMDS, \ + this_id: -1, \ + sg_tablesize: GDTH_MAXSG, \ + cmd_per_lun: GDTH_MAXC_P_L, \ + present: 0, \ + unchecked_isa_dma: 1, \ + use_clustering: ENABLE_CLUSTERING, \ + use_new_eh_code: 1 /* use new error code */ } + +#elif LINUX_VERSION_CODE >= 0x02015F +int gdth_bios_param(Disk *,kdev_t,int *); +extern struct proc_dir_entry proc_scsi_gdth; +int gdth_proc_info(char *,char **,off_t,int,int,int); +int gdth_eh_abort(Scsi_Cmnd *scp); +int gdth_eh_device_reset(Scsi_Cmnd *scp); +int gdth_eh_bus_reset(Scsi_Cmnd *scp); +int gdth_eh_host_reset(Scsi_Cmnd *scp); +#define GDTH { proc_dir: &proc_scsi_gdth, \ + proc_info: gdth_proc_info, \ + name: "GDT SCSI Disk Array Controller",\ + detect: gdth_detect, \ + release: gdth_release, \ + info: gdth_info, \ + command: NULL, \ + queuecommand: gdth_queuecommand, \ + eh_abort_handler: gdth_eh_abort, \ + eh_device_reset_handler: gdth_eh_device_reset, \ + eh_bus_reset_handler: gdth_eh_bus_reset, \ + eh_host_reset_handler: gdth_eh_host_reset, \ + abort: gdth_abort, \ + reset: gdth_reset, \ + bios_param: gdth_bios_param, \ + can_queue: GDTH_MAXCMDS, \ + this_id: -1, \ + sg_tablesize: GDTH_MAXSG, \ + cmd_per_lun: GDTH_MAXC_P_L, \ + present: 0, \ + unchecked_isa_dma: 1, \ + use_clustering: ENABLE_CLUSTERING, \ + use_new_eh_code: 1 /* use new error code */ } + +#elif LINUX_VERSION_CODE >= 0x010300 +int gdth_bios_param(Disk *,kdev_t,int *); +extern struct proc_dir_entry proc_scsi_gdth; +int gdth_proc_info(char *,char **,off_t,int,int,int); +#define GDTH { NULL, NULL, \ + &proc_scsi_gdth, \ + gdth_proc_info, \ + "GDT SCSI Disk Array Controller", \ + gdth_detect, \ + gdth_release, \ + gdth_info, \ + NULL, \ + gdth_queuecommand, \ + gdth_abort, \ + gdth_reset, \ + NULL, \ + gdth_bios_param, \ + GDTH_MAXCMDS, \ + -1, \ + GDTH_MAXSG, \ + GDTH_MAXC_P_L, \ + 0, \ + 1, \ + ENABLE_CLUSTERING} + +#else +int gdth_bios_param(Disk *,int,int *); +#define GDTH { NULL, NULL, \ + "GDT SCSI Disk Array Controller", \ + gdth_detect, \ + gdth_release, \ + gdth_info, \ + NULL, \ + gdth_queuecommand, \ + gdth_abort, \ + gdth_reset, \ + NULL, \ + gdth_bios_param, \ + GDTH_MAXCMDS, \ + -1, \ + GDTH_MAXSG, \ + GDTH_MAXC_P_L, \ + 0, \ + 1, \ + ENABLE_CLUSTERING} +#endif #endif diff -urN linux-2.5.65-bk2/drivers/scsi/gdth_ioctl.h linux-2.5.65-bk3/drivers/scsi/gdth_ioctl.h --- linux-2.5.65-bk2/drivers/scsi/gdth_ioctl.h Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/drivers/scsi/gdth_ioctl.h Mon Mar 31 12:41:42 2003 @@ -2,7 +2,7 @@ #define _GDTH_IOCTL_H /* gdth_ioctl.h - * $Id: gdth_ioctl.h,v 1.10 2001/05/22 06:28:59 achim Exp $ + * $Id: gdth_ioctl.h,v 1.11 2003/02/27 14:59:03 achim Exp $ */ /* IOCTLs */ @@ -23,8 +23,136 @@ #define GDTIOCTL_MAGIC 0xaffe0004 #define EVENT_SIZE 294 -#define MAX_HDRIVES 100 +#define GDTH_MAXSG 32 /* max. s/g elements */ +#define MAX_LDRIVES 255 /* max. log. drive count */ +#ifdef GDTH_IOCTL_PROC +#define MAX_HDRIVES 100 /* max. host drive count */ +#else +#define MAX_HDRIVES MAX_LDRIVES /* max. host drive count */ +#endif + +/* typedefs */ +#ifdef __KERNEL__ +typedef u32 ulong32; +#endif +#define PACKED __attribute__((packed)) + +/* scatter/gather element */ +typedef struct { + ulong32 sg_ptr; /* address */ + ulong32 sg_len; /* length */ +} PACKED gdth_sg_str; + +/* command structure */ +typedef struct { + ulong32 BoardNode; /* board node (always 0) */ + ulong32 CommandIndex; /* command number */ + ushort OpCode; /* the command (READ,..) */ + union { + struct { + ushort DeviceNo; /* number of cache drive */ + ulong32 BlockNo; /* block number */ + ulong32 BlockCnt; /* block count */ + ulong32 DestAddr; /* dest. addr. (if s/g: -1) */ + ulong32 sg_canz; /* s/g element count */ + gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */ + } PACKED cache; /* cache service cmd. str. */ + struct { + ushort param_size; /* size of p_param buffer */ + ulong32 subfunc; /* IOCTL function */ + ulong32 channel; /* device */ + ulong32 p_param; /* buffer */ + } PACKED ioctl; /* IOCTL command structure */ + struct { + ushort reserved; + union { + struct { + ulong32 msg_handle; /* message handle */ + ulong32 msg_addr; /* message buffer address */ + } PACKED msg; + unchar data[12]; /* buffer for rtc data, ... */ + } su; + } PACKED screen; /* screen service cmd. str. */ + struct { + ushort reserved; + ulong32 direction; /* data direction */ + ulong32 mdisc_time; /* disc. time (0: no timeout)*/ + ulong32 mcon_time; /* connect time(0: no to.) */ + ulong32 sdata; /* dest. addr. (if s/g: -1) */ + ulong32 sdlen; /* data length (bytes) */ + ulong32 clen; /* SCSI cmd. length(6,10,12) */ + unchar cmd[12]; /* SCSI command */ + unchar target; /* target ID */ + unchar lun; /* LUN */ + unchar bus; /* SCSI bus number */ + unchar priority; /* only 0 used */ + ulong32 sense_len; /* sense data length */ + ulong32 sense_data; /* sense data addr. */ + ulong32 link_p; /* linked cmds (not supp.) */ + ulong32 sg_ranz; /* s/g element count */ + gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */ + } PACKED raw; /* raw service cmd. struct. */ + } u; + /* additional variables */ + unchar Service; /* controller service */ + unchar reserved; + ushort Status; /* command result */ + ulong32 Info; /* additional information */ + void *RequestBuffer; /* request buffer */ +} PACKED gdth_cmd_str; + +/* controller event structure */ +#define ES_ASYNC 1 +#define ES_DRIVER 2 +#define ES_TEST 3 +#define ES_SYNC 4 +typedef struct { + ushort size; /* size of structure */ + union { + char stream[16]; + struct { + ushort ionode; + ushort service; + ulong32 index; + } PACKED driver; + struct { + ushort ionode; + ushort service; + ushort status; + ulong32 info; + unchar scsi_coord[3]; + } PACKED async; + struct { + ushort ionode; + ushort service; + ushort status; + ulong32 info; + ushort hostdrive; + unchar scsi_coord[3]; + unchar sense_key; + } PACKED sync; + struct { + ulong32 l1, l2, l3, l4; + } PACKED test; + } eu; + ulong32 severity; + unchar event_string[256]; +} PACKED gdth_evt_data; + +typedef struct { + ulong32 first_stamp; + ulong32 last_stamp; + ushort same_count; + ushort event_source; + ushort event_idx; + unchar application; + unchar reserved; + gdth_evt_data event_data; +} PACKED gdth_evt_str; + + +#ifdef GDTH_IOCTL_PROC /* IOCTL structure (write) */ typedef struct { ulong32 magic; /* IOCTL magic */ @@ -106,7 +234,82 @@ } hdr_list[MAX_HDRIVES]; /* index is host drive number */ } iu; } gdth_iord_str; +#endif + +#ifdef GDTH_IOCTL_CHRDEV +/* GDTIOCTL_GENERAL */ +typedef struct { + ushort ionode; /* controller number */ + ushort timeout; /* timeout */ + ulong32 info; /* error info */ + ushort status; /* status */ + ulong data_len; /* data buffer size */ + ulong sense_len; /* sense buffer size */ + gdth_cmd_str command; /* command */ +} gdth_ioctl_general; + +/* GDTIOCTL_LOCKDRV */ +typedef struct { + ushort ionode; /* controller number */ + unchar lock; /* lock/unlock */ + unchar drive_cnt; /* drive count */ + ushort drives[MAX_HDRIVES]; /* drives */ +} gdth_ioctl_lockdrv; + +/* GDTIOCTL_LOCKCHN */ +typedef struct { + ushort ionode; /* controller number */ + unchar lock; /* lock/unlock */ + unchar channel; /* channel */ +} gdth_ioctl_lockchn; + +/* GDTIOCTL_OSVERS */ +typedef struct { + unchar version; /* OS version */ + unchar subversion; /* OS subversion */ + ushort revision; /* revision */ +} gdth_ioctl_osvers; + +/* GDTIOCTL_CTRTYPE */ +typedef struct { + ushort ionode; /* controller number */ + unchar type; /* controller type */ + ushort info; /* slot etc. */ + ushort oem_id; /* OEM ID */ + ushort bios_ver; /* not used */ + ushort access; /* not used */ + ushort ext_type; /* extended type */ + ushort device_id; /* device ID */ + ushort sub_device_id; /* sub device ID */ +} gdth_ioctl_ctrtype; + +/* GDTIOCTL_EVENT */ +typedef struct { + ushort ionode; + int erase; /* erase event? */ + int handle; /* event handle */ + gdth_evt_str event; +} gdth_ioctl_event; +/* GDTIOCTL_RESCAN/GDTIOCTL_HDRLIST */ +typedef struct { + ushort ionode; /* controller number */ + unchar flag; /* add/remove */ + ushort hdr_no; /* drive no. */ + struct { + unchar bus; /* SCSI bus */ + unchar target; /* target ID */ + unchar lun; /* LUN */ + unchar cluster_type; /* cluster properties */ + } hdr_list[MAX_HDRIVES]; /* index is host drive number */ +} gdth_ioctl_rescan; +/* GDTIOCTL_RESET_BUS/GDTIOCTL_RESET_DRV */ +typedef struct { + ushort ionode; /* controller number */ + ushort number; /* bus/host drive number */ + ushort status; /* status */ +} gdth_ioctl_reset; #endif +#endif diff -urN linux-2.5.65-bk2/drivers/scsi/gdth_proc.c linux-2.5.65-bk3/drivers/scsi/gdth_proc.c --- linux-2.5.65-bk2/drivers/scsi/gdth_proc.c Mon Mar 17 13:44:05 2003 +++ linux-2.5.65-bk3/drivers/scsi/gdth_proc.c Mon Mar 31 12:41:42 2003 @@ -1,8 +1,7 @@ /* gdth_proc.c - * $Id: gdth_proc.c,v 1.33 2001/08/10 07:54:39 achim Exp $ + * $Id: gdth_proc.c,v 1.35 2003/02/27 15:00:44 achim Exp $ */ -#include "gdth_ioctl.h" #if LINUX_VERSION_CODE >= 0x020407 #include #endif @@ -33,22 +32,33 @@ static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum) { - int ret_val; -#if LINUX_VERSION_CODE >= 0x020322 + int ret_val = -EINVAL; +#if LINUX_VERSION_CODE >= 0x020503 + Scsi_Request *scp; + Scsi_Device *sdev; +#elif LINUX_VERSION_CODE >= 0x020322 Scsi_Cmnd *scp; Scsi_Device *sdev; #else Scsi_Cmnd scp; Scsi_Device sdev; #endif +#ifdef GDTH_IOCTL_PROC gdth_iowr_str *piowr; - - TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum)); piowr = (gdth_iowr_str *)buffer; +#endif + TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum)); -#if LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]); - scp = scsi_get_command(sdev, GFP_KERNEL); +#if LINUX_VERSION_CODE >= 0x020503 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + scp = scsi_allocate_request(sdev); + if (!scp) + return -ENOMEM; + scp->sr_cmd_len = 12; + scp->sr_use_sg = 0; +#elif LINUX_VERSION_CODE >= 0x020322 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + scp = scsi_allocate_device(sdev, 1, FALSE); if (!scp) return -ENOMEM; scp->cmd_len = 12; @@ -56,7 +66,7 @@ #else memset(&sdev,0,sizeof(Scsi_Device)); memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_vtab[vh]; + sdev.host = scp.host = gdth_ctr_tab[hanum]; sdev.id = scp.target = sdev.host->this_id; scp.device = &sdev; #endif @@ -66,6 +76,7 @@ buffer += 5; length -= 5; ret_val = gdth_set_asc_info( buffer, length, hanum, scp ); +#ifdef GDTH_IOCTL_PROC } else if (piowr->magic == GDTIOCTL_MAGIC) { ret_val = gdth_set_bin_info( buffer, length, hanum, scp ); } else { @@ -75,19 +86,22 @@ printk("GDT: Please update your driver.\n"); else printk("GDT: Please update your tool.\n"); - ret_val = -EINVAL; +#endif } - } else { - ret_val = -EINVAL; } -#if LINUX_VERSION_CODE >= 0x020322 - scsi_put_command(scp); +#if LINUX_VERSION_CODE >= 0x020503 + scsi_release_request(scp); + scsi_free_host_dev(sdev); +#elif LINUX_VERSION_CODE >= 0x020322 + scsi_release_command(scp); scsi_free_host_dev(sdev); #endif return ret_val; } -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 +static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp) +#elif LINUX_VERSION_CODE >= 0x020322 static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp) #else static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp) @@ -98,6 +112,7 @@ gdth_ha_str *ha; gdth_cmd_str gdtcmd; gdth_cpar_str *pcpar; + ulong32 paddr; char cmnd[MAX_COMMAND_SIZE]; memset(cmnd, 0xff, 12); @@ -133,7 +148,9 @@ gdtcmd.OpCode = GDT_FLUSH; gdtcmd.u.cache.DeviceNo = i; gdtcmd.u.cache.BlockNo = 1; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); @@ -178,23 +195,25 @@ } if (wb_mode) { - if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE)) + if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE, &paddr)) return(-EBUSY); pcpar = (gdth_cpar_str *)ha->pscratch; memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) ); gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; - gdtcmd.u.ioctl.p_param = virt_to_bus(pcpar); + gdtcmd.u.ioctl.p_param = paddr; gdtcmd.u.ioctl.param_size = sizeof(gdth_cpar_str); gdtcmd.u.ioctl.subfunc = CACHE_CONFIG; gdtcmd.u.ioctl.channel = INVALID_CHANNEL; pcpar->write_back = wb_mode==1 ? 0:1; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); #else gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); #endif - gdth_ioctl_free(hanum, ha->pscratch); + gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr); printk("Done.\n"); return(orig_length); } @@ -203,7 +222,10 @@ return(-EINVAL); } -#if LINUX_VERSION_CODE >= 0x020322 +#ifdef GDTH_IOCTL_PROC +#if LINUX_VERSION_CODE >= 0x020503 +static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Request *scp) +#elif LINUX_VERSION_CODE >= 0x020322 static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp) #else static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp) @@ -216,7 +238,7 @@ gdth_iord_str *piord; gdth_cmd_str *pcmd; gdth_evt_str *pevt; - ulong32 *ppadd, add_size, *ppadd2, add_size2, info; + ulong32 *ppadd, add_size, *ppadd2, add_size2, info, paddr; ulong flags; gdth_cmd_str gdtcmd; int drv_cyls, drv_hds, drv_secs; @@ -273,21 +295,25 @@ return(-EINVAL); } if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str)+add_size+add_size2, - TRUE )) + TRUE, &paddr )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; - piord->size = sizeof(gdth_iord_str) + add_size + add_size2; if (add_size > 0) { memcpy(piord->iu.general.data, piowr->iu.general.data, add_size); - *ppadd = virt_to_bus(piord->iu.general.data); + *ppadd = paddr + GDTOFFSOF(gdth_iord_str, iu.general.data[0]); } if (add_size2 > 0) { memcpy(piord->iu.general.data+add_size, piowr->iu.general.data, add_size2); - *ppadd2 = virt_to_bus(piord->iu.general.data+add_size); + *ppadd2 = paddr + GDTOFFSOF(gdth_iord_str, iu.general.data[0]) + add_size2; } + /* do IOCTL */ -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, pcmd, cmnd, piowr->timeout); + piord->status = (scp->sr_command->SCp.Message << 16) | + scp->sr_command->SCp.Status; +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout); piord->status = (scp->SCp.Message<<16)|scp->SCp.Status; #else @@ -297,7 +323,7 @@ break; case GDTIOCTL_DRVERS: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -306,7 +332,7 @@ break; case GDTIOCTL_CTRTYPE: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -332,7 +358,7 @@ break; case GDTIOCTL_CTRCNT: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -341,7 +367,7 @@ break; case GDTIOCTL_OSVERS: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -352,7 +378,7 @@ break; case GDTIOCTL_LOCKDRV: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; for (i = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) { @@ -378,7 +404,7 @@ break; case GDTIOCTL_LOCKCHN: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) return(-EBUSY); i = piowr->iu.lockchn.channel; if (i < ha->bus_cnt) { @@ -406,7 +432,7 @@ break; case GDTIOCTL_EVENT: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; if (piowr->iu.event.erase == 0xff) { @@ -439,16 +465,19 @@ piord->size = sizeof(gdth_iord_str); piord->status = S_OK; break; - + case GDTIOCTL_SCSI: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) +#if LINUX_VERSION_CODE >= 0x020503 + return(-EINVAL); +#else + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); memcpy(cmnd, piowr->iu.scsi.cmd, 12); #if LINUX_VERSION_CODE >= 0x020322 - scp->device->id = piowr->iu.scsi.target; - scp->device->channel = virt_ctr ? 0 : piowr->iu.scsi.bus; + scp->target = piowr->iu.scsi.target; + scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus; scp->cmd_len = piowr->iu.scsi.cmd_len; gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout); piord->status = (scp->SCp.Message<<16)|scp->SCp.Status; @@ -459,15 +488,47 @@ gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout); piord->status = (scp.SCp.Message<<16)|scp.SCp.Status; #endif +#endif break; case GDTIOCTL_RESET_BUS: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); -#if LINUX_VERSION_CODE >= 0x020322 - scp->device->channel = virt_ctr ? 0 : piowr->iu.scsi.bus; +#if LINUX_VERSION_CODE >= 0x02053C + { + Scsi_Device *sdev; + Scsi_Cmnd *scmnd; + + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + scmnd= scsi_get_command(sdev, GFP_KERNEL); + if (!scmnd) + return(-ENOMEM); + scmnd->device->host = scp->sr_host; + scmnd->device->channel = virt_ctr ? 0 : piowr->iu.scsi.bus; + piord->status = (ulong32)gdth_eh_bus_reset( scmnd ); + if (piord->status == SUCCESS) + piord->status = S_OK; + else + piord->status = S_GENERR; + scsi_put_command(scmnd); + scsi_free_host_dev(sdev); + } +#elif LINUX_VERSION_CODE >= 0x020503 + { + Scsi_Cmnd scmnd; + + scmnd.host = scp->sr_host; + scmnd.channel = virt_ctr ? 0 : piowr->iu.scsi.bus; + piord->status = (ulong32)gdth_eh_bus_reset( &scmnd ); + if (piord->status == SUCCESS) + piord->status = S_OK; + else + piord->status = S_GENERR; + } +#elif LINUX_VERSION_CODE >= 0x020322 + scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus; piord->status = (ulong32)gdth_eh_bus_reset( scp ); if (piord->status == SUCCESS) piord->status = S_OK; @@ -486,7 +547,7 @@ break; case GDTIOCTL_HDRLIST: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -501,7 +562,12 @@ gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_CLUST_INFO; gdtcmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status == S_OK) + piord->iu.hdr_list[i].cluster_type = + (unchar)scp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); if (scp->SCp.Status == S_OK) piord->iu.hdr_list[i].cluster_type = @@ -520,7 +586,7 @@ break; case GDTIOCTL_RESCAN: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -532,7 +598,11 @@ gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_INIT; gdtcmd.u.cache.DeviceNo = LINUX_OS; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + status = (ushort)scp->sr_command->SCp.Status; + info = (ulong32)scp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); status = (ushort)scp->SCp.Status; info = (ulong32)scp->SCp.Message; @@ -557,7 +627,11 @@ gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_INFO; gdtcmd.u.cache.DeviceNo = k; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + status = (ushort)scp->sr_command->SCp.Status; + info = (ulong32)scp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); status = (ushort)scp->SCp.Status; info = (ulong32)scp->SCp.Message; @@ -591,7 +665,11 @@ gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_DEVTYPE; gdtcmd.u.cache.DeviceNo = k; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + status = (ushort)scp->sr_command->SCp.Status; + info = (ulong32)scp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); status = (ushort)scp->SCp.Status; info = (ulong32)scp->SCp.Message; @@ -609,7 +687,11 @@ gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_CLUST_INFO; gdtcmd.u.cache.DeviceNo = k; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + status = (ushort)scp->sr_command->SCp.Status; + info = (ulong32)scp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); status = (ushort)scp->SCp.Status; info = (ulong32)scp->SCp.Message; @@ -628,7 +710,11 @@ gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_RW_ATTRIBS; gdtcmd.u.cache.DeviceNo = k; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + status = (ushort)scp->sr_command->SCp.Status; + info = (ulong32)scp->sr_command->SCp.Message; +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); status = (ushort)scp->SCp.Status; info = (ulong32)scp->SCp.Message; @@ -646,7 +732,7 @@ break; case GDTIOCTL_RESET_DRV: - if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE )) + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE, &paddr )) return(-EBUSY); piord = (gdth_iord_str *)ha->pscratch; piord->size = sizeof(gdth_iord_str); @@ -656,7 +742,10 @@ gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_CLUST_RESET; gdtcmd.u.cache.DeviceNo = i; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + piord->status = (ushort)scp->sr_command->SCp.Status; +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); piord->status = (scp->SCp.Message<<16)|scp->SCp.Status; #else @@ -671,6 +760,7 @@ } return length; } +#endif static int gdth_get_info(char *buffer,char **start,off_t offset, int length,int vh,int hanum,int busnum) @@ -678,14 +768,16 @@ int size = 0,len = 0; off_t begin = 0,pos = 0; gdth_ha_str *ha; - gdth_iord_str *piord; int id, i, j, k, sec, flag; int no_mdrv = 0, drv_no, is_mirr; - ulong32 cnt; + ulong32 cnt, paddr; gdth_cmd_str gdtcmd; gdth_evt_str estr; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + Scsi_Request *scp; + Scsi_Device *sdev; +#elif LINUX_VERSION_CODE >= 0x020322 Scsi_Cmnd *scp; Scsi_Device *sdev; #else @@ -710,9 +802,16 @@ TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum)); ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= 0x020322 - sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]); - scp = scsi_get_command(sdev, GFP_KERNEL); +#if LINUX_VERSION_CODE >= 0x020503 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + scp = scsi_allocate_request(sdev); + if (!scp) + return -ENOMEM; + scp->sr_cmd_len = 12; + scp->sr_use_sg = 0; +#elif LINUX_VERSION_CODE >= 0x020322 + sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); + scp = scsi_allocate_device(sdev, 1, FALSE); if (!scp) return -ENOMEM; scp->cmd_len = 12; @@ -720,13 +819,15 @@ #else memset(&sdev,0,sizeof(Scsi_Device)); memset(&scp, 0,sizeof(Scsi_Cmnd)); - sdev.host = scp.host = gdth_ctr_vtab[vh]; + sdev.host = scp.host = gdth_ctr_tab[hanum]; sdev.id = scp.target = sdev.host->this_id; scp.device = &sdev; #endif +#ifdef GDTH_IOCTL_PROC /* ioctl from tool? */ if (!gdth_ioctl_check_bin(hanum, (ushort)length)) { +#endif /* request is i.e. "cat /proc/scsi/gdth/0" */ /* format: %-15s\t%-10s\t%-15s\t%s */ /* driver parameters */ @@ -798,7 +899,7 @@ len += size; pos = begin + len; flag = FALSE; - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE); + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); if (!buf) goto stop_output; for (i = 0; i < ha->bus_cnt; ++i) { @@ -807,7 +908,7 @@ pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4); gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; - gdtcmd.u.ioctl.p_param = virt_to_bus(pds); + gdtcmd.u.ioctl.p_param = paddr + GDTH_SCRATCH/4; gdtcmd.u.ioctl.param_size = 3*GDTH_SCRATCH/4; gdtcmd.u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN; gdtcmd.u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL; @@ -818,7 +919,10 @@ sizeof(pds->list[0]); if (pds->entries > cnt) pds->entries = cnt; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status != S_OK) +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); if (scp->SCp.Status != S_OK) #else @@ -837,12 +941,15 @@ pdi = (gdth_diskinfo_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; - gdtcmd.u.ioctl.p_param = virt_to_bus(pdi); + gdtcmd.u.ioctl.p_param = paddr; gdtcmd.u.ioctl.param_size = sizeof(gdth_diskinfo_str); gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN; gdtcmd.u.ioctl.channel = ha->raw[i].address | ha->raw[i].id_list[j]; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status == S_OK) +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); if (scp->SCp.Status == S_OK) #else @@ -892,13 +999,16 @@ pdef = (gdth_defcnt_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; - gdtcmd.u.ioctl.p_param = virt_to_bus(pdef); + gdtcmd.u.ioctl.p_param = paddr; gdtcmd.u.ioctl.param_size = sizeof(gdth_defcnt_str); gdtcmd.u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN; gdtcmd.u.ioctl.channel = ha->raw[i].address | ha->raw[i].id_list[j]; pdef->sddc_type = 0x08; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status == S_OK) +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); if (scp->SCp.Status == S_OK) #else @@ -920,7 +1030,7 @@ goto stop_output; } } - gdth_ioctl_free(hanum, buf); + gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); if (!flag) { size = sprintf(buffer+len, "\n --\n"); @@ -932,7 +1042,7 @@ len += size; pos = begin + len; flag = FALSE; - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE); + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); if (!buf) goto stop_output; for (i = 0; i < MAX_LDRIVES; ++i) { @@ -947,11 +1057,14 @@ pcdi = (gdth_cdrinfo_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; - gdtcmd.u.ioctl.p_param = virt_to_bus(pcdi); + gdtcmd.u.ioctl.p_param = paddr; gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str); gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO; gdtcmd.u.ioctl.channel = drv_no; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status != S_OK) +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); if (scp->SCp.Status != S_OK) #else @@ -1034,7 +1147,7 @@ if (pos > offset + length) goto stop_output; } - gdth_ioctl_free(hanum, buf); + gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); if (!flag) { size = sprintf(buffer+len, "\n --\n"); @@ -1046,7 +1159,7 @@ len += size; pos = begin + len; flag = FALSE; - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE); + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); if (!buf) goto stop_output; for (i = 0; i < MAX_LDRIVES; ++i) { @@ -1057,11 +1170,14 @@ pai = (gdth_arrayinf_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; - gdtcmd.u.ioctl.p_param = virt_to_bus(pai); + gdtcmd.u.ioctl.p_param = paddr; gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str); gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN; gdtcmd.u.ioctl.channel = i; -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status == S_OK) +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); if (scp->SCp.Status == S_OK) #else @@ -1112,7 +1228,7 @@ goto stop_output; } } - gdth_ioctl_free(hanum, buf); + gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); if (!flag) { size = sprintf(buffer+len, "\n --\n"); @@ -1124,7 +1240,7 @@ len += size; pos = begin + len; flag = FALSE; - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE); + buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr); if (!buf) goto stop_output; for (i = 0; i < MAX_LDRIVES; ++i) { @@ -1136,13 +1252,16 @@ phg = (gdth_hget_str *)buf; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; - gdtcmd.u.ioctl.p_param = virt_to_bus(phg); + gdtcmd.u.ioctl.p_param = paddr; gdtcmd.u.ioctl.param_size = sizeof(gdth_hget_str); gdtcmd.u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN; gdtcmd.u.ioctl.channel = i; phg->entries = MAX_HDRIVES; phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 + gdth_do_req(scp, &gdtcmd, cmnd, 30); + if (scp->sr_command->SCp.Status != S_OK) +#elif LINUX_VERSION_CODE >= 0x020322 gdth_do_cmd(scp, &gdtcmd, cmnd, 30); if (scp->SCp.Status != S_OK) #else @@ -1164,7 +1283,7 @@ } } } - gdth_ioctl_free(hanum, buf); + gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr); for (i = 0; i < MAX_HDRIVES; ++i) { if (!(ha->hdr[i].present)) @@ -1221,20 +1340,27 @@ if (id == -1) break; } +#ifdef GDTH_IOCTL_PROC } else { + gdth_iord_str *piord; + /* request from tool (GDTMON,..) */ piord = (gdth_iord_str *)ha->pscratch; if (piord == NULL) goto stop_output; length = piord->size; memcpy(buffer+len, (char *)piord, length); - gdth_ioctl_free(hanum, ha->pscratch); + gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr); len = length; } +#endif stop_output: -#if LINUX_VERSION_CODE >= 0x020322 - scsi_put_command(scp); +#if LINUX_VERSION_CODE >= 0x020503 + scsi_release_request(scp); + scsi_free_host_dev(sdev); +#elif LINUX_VERSION_CODE >= 0x020322 + scsi_release_command(scp); scsi_free_host_dev(sdev); #endif *start = buffer +(offset-begin); @@ -1246,6 +1372,26 @@ return(len); } +#if LINUX_VERSION_CODE >= 0x020503 +static void gdth_do_req(Scsi_Request *scp, gdth_cmd_str *gdtcmd, + char *cmnd, int timeout) +{ + unsigned bufflen; + DECLARE_COMPLETION(wait); + + TRACE2(("gdth_do_req()\n")); + if (gdtcmd != NULL) { + bufflen = sizeof(gdth_cmd_str); + } else { + bufflen = 0; + } + scp->sr_request->rq_status = RQ_SCSI_BUSY; + scp->sr_request->waiting = &wait; + scsi_do_req(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); + wait_for_completion(&wait); +} + +#else static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd, char *cmnd, int timeout) { @@ -1266,8 +1412,8 @@ scp->SCp.this_residual = DEFAULT_PRI; bufflen = 0; } - scp->request.rq_status = RQ_SCSI_BUSY; #if LINUX_VERSION_CODE >= 0x020407 + scp->request.rq_status = RQ_SCSI_BUSY; scp->request.waiting = &wait; scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); wait_for_completion(&wait); @@ -1283,46 +1429,53 @@ down(&sem); #endif } +#endif void gdth_scsi_done(Scsi_Cmnd *scp) { TRACE2(("gdth_scsi_done()\n")); +#if LINUX_VERSION_CODE >= 0x020503 + scp->request->rq_status = RQ_SCSI_DONE; + if (scp->request->waiting != NULL) + complete(scp->request->waiting); +#elif LINUX_VERSION_CODE >= 0x020407 scp->request.rq_status = RQ_SCSI_DONE; - -#if LINUX_VERSION_CODE >= 0x020407 if (scp->request.waiting != NULL) complete(scp->request.waiting); #else + scp->request.rq_status = RQ_SCSI_DONE; if (scp->request.sem != NULL) up(scp->request.sem); #endif } -static char *gdth_ioctl_alloc(int hanum, ushort size, int scratch) +static char *gdth_ioctl_alloc(int hanum, int size, int scratch, + ulong32 *paddr) { gdth_ha_str *ha; ulong flags; char *ret_val; - if (size == 0 || size > GDTH_SCRATCH) - return FALSE; + if (size == 0) + return NULL; ha = HADATA(gdth_ctr_tab[hanum]); GDTH_LOCK_HA(ha, flags); - if (scratch) { - if (!ha->scratch_busy) { - ha->scratch_busy = TRUE; - ret_val = ha->pscratch; - } else - ret_val = NULL; + if (!ha->scratch_busy && size <= GDTH_SCRATCH) { + ha->scratch_busy = TRUE; + ret_val = ha->pscratch; + *paddr = ha->scratch_phys; + } else if (scratch) { + ret_val = NULL; } else { -#if LINUX_VERSION_CODE >= 0x020322 - ret_val = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, - GDTH_SCRATCH_ORD); +#if LINUX_VERSION_CODE >= 0x020400 + ret_val = pci_alloc_consistent(ha->pdev, size, paddr); #else - ret_val = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA); + ret_val = scsi_init_malloc(size, GFP_ATOMIC | GFP_DMA); + if (ret_val) + *paddr = virt_to_bus(ret_val); #endif } @@ -1330,7 +1483,7 @@ return ret_val; } -static void gdth_ioctl_free(int hanum, char *buf) +static void gdth_ioctl_free(int hanum, int size, char *buf, ulong32 paddr) { gdth_ha_str *ha; ulong flags; @@ -1341,16 +1494,17 @@ if (buf == ha->pscratch) { ha->scratch_busy = FALSE; } else { -#if LINUX_VERSION_CODE >= 0x020322 - free_pages((unsigned long)buf, GDTH_SCRATCH_ORD); +#if LINUX_VERSION_CODE >= 0x020400 + pci_free_consistent(ha->pdev, size, buf, paddr); #else - scsi_init_free((void *)buf, GDTH_SCRATCH); + scsi_init_free((void *)buf, size); #endif } GDTH_UNLOCK_HA(ha, flags); } +#ifdef GDTH_IOCTL_PROC static int gdth_ioctl_check_bin(int hanum, ushort size) { gdth_ha_str *ha; @@ -1368,7 +1522,7 @@ GDTH_UNLOCK_HA(ha, flags); return ret_val; } - +#endif static void gdth_wait_completion(int hanum, int busnum, int id) { @@ -1376,23 +1530,39 @@ ulong flags; int i; Scsi_Cmnd *scp; - unchar b; + unchar b, t; ha = HADATA(gdth_ctr_tab[hanum]); GDTH_LOCK_HA(ha, flags); for (i = 0; i < GDTH_MAXCMDS; ++i) { scp = ha->cmd_tab[i].cmnd; +#if LINUX_VERSION_CODE >= 0x02053C b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; - if (!SPECIAL_SCP(scp) && scp->device->id == (unchar)id && + t = scp->device->id; +#else + b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel; + t = scp->target; +#endif + if (!SPECIAL_SCP(scp) && t == (unchar)id && b == (unchar)busnum) { scp->SCp.have_data_in = 0; GDTH_UNLOCK_HA(ha, flags); while (!scp->SCp.have_data_in) barrier(); +#if LINUX_VERSION_CODE >= 0x02053C + GDTH_LOCK_SCSI_DONE(scp->device->host, flags); + scp->scsi_done(scp); + GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags); +#elif LINUX_VERSION_CODE >= 0x020503 + GDTH_LOCK_SCSI_DONE(scp->host, flags); + scp->scsi_done(scp); + GDTH_UNLOCK_SCSI_DONE(scp->host, flags); +#else GDTH_LOCK_SCSI_DONE(flags); scp->scsi_done(scp); GDTH_UNLOCK_SCSI_DONE(flags); +#endif GDTH_LOCK_HA(ha, flags); } } @@ -1404,14 +1574,20 @@ gdth_ha_str *ha; ulong flags; Scsi_Cmnd *scp; - unchar b; + unchar b, t; ha = HADATA(gdth_ctr_tab[hanum]); GDTH_LOCK_HA(ha, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { +#if LINUX_VERSION_CODE >= 0x02053C b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; - if (scp->device->id == (unchar)id && b == (unchar)busnum) { + t = scp->device->id; +#else + b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel; + t = scp->target; +#endif + if (t == (unchar)id && b == (unchar)busnum) { TRACE2(("gdth_stop_timeout(): update_timeout()\n")); scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); } @@ -1424,14 +1600,20 @@ gdth_ha_str *ha; ulong flags; Scsi_Cmnd *scp; - unchar b; + unchar b, t; ha = HADATA(gdth_ctr_tab[hanum]); GDTH_LOCK_HA(ha, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { +#if LINUX_VERSION_CODE >= 0x02053C b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; - if (scp->device->id == (unchar)id && b == (unchar)busnum) { + t = scp->device->id; +#else + b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel; + t = scp->target; +#endif + if (t == (unchar)id && b == (unchar)busnum) { TRACE2(("gdth_start_timeout(): update_timeout()\n")); gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual); } @@ -1464,7 +1646,7 @@ timer_table[SCSI_TIMER].expires = jiffies + timeout; timer_active |= 1 << SCSI_TIMER; } else { - if (time_before(jiffies + timeout, timer_table[SCSI_TIMER].expires)) + if (jiffies + timeout < timer_table[SCSI_TIMER].expires) timer_table[SCSI_TIMER].expires = jiffies + timeout; } } diff -urN linux-2.5.65-bk2/drivers/scsi/gdth_proc.h linux-2.5.65-bk3/drivers/scsi/gdth_proc.h --- linux-2.5.65-bk2/drivers/scsi/gdth_proc.h Mon Mar 17 13:44:20 2003 +++ linux-2.5.65-bk3/drivers/scsi/gdth_proc.h Mon Mar 31 12:41:42 2003 @@ -2,26 +2,42 @@ #define _GDTH_PROC_H /* gdth_proc.h - * $Id: gdth_proc.h,v 1.11 2001/07/25 15:37:40 achim Exp $ + * $Id: gdth_proc.h,v 1.13 2003/02/27 14:59:25 achim Exp $ */ static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum); static int gdth_get_info(char *buffer,char **start,off_t offset, int length,int vh,int hanum,int busnum); -#if LINUX_VERSION_CODE >= 0x020322 +#if LINUX_VERSION_CODE >= 0x020503 +static void gdth_do_req(Scsi_Request *srp, gdth_cmd_str *cmd, + char *cmnd, int timeout); +static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp); +#ifdef GDTH_IOCTL_PROC +static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Request *scp); +#endif +#elif LINUX_VERSION_CODE >= 0x020322 +static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, + char *cmnd, int timeout); static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp); +#ifdef GDTH_IOCTL_PROC static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp); +#endif #else +static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, + char *cmnd, int timeout); static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp); +#ifdef GDTH_IOCTL_PROC static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp); #endif -static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, - char *cmnd, int timeout); +#endif -static char *gdth_ioctl_alloc(int hanum, ushort size, int scratch); -static void gdth_ioctl_free(int hanum, char *buf); +static char *gdth_ioctl_alloc(int hanum, int size, int scratch, + ulong32 *paddr); +static void gdth_ioctl_free(int hanum, int size, char *buf, ulong32 paddr); +#ifdef GDTH_IOCTL_PROC static int gdth_ioctl_check_bin(int hanum, ushort size); +#endif static void gdth_wait_completion(int hanum, int busnum, int id); static void gdth_stop_timeout(int hanum, int busnum, int id); static void gdth_start_timeout(int hanum, int busnum, int id); diff -urN linux-2.5.65-bk2/drivers/scsi/sym53c416.h linux-2.5.65-bk3/drivers/scsi/sym53c416.h --- linux-2.5.65-bk2/drivers/scsi/sym53c416.h Mon Mar 17 13:44:22 2003 +++ linux-2.5.65-bk3/drivers/scsi/sym53c416.h Mon Mar 31 12:41:42 2003 @@ -18,14 +18,6 @@ #ifndef _SYM53C416_H #define _SYM53C416_H -#if !defined(LINUX_VERSION_CODE) -#include -#endif - -#ifndef LinuxVersionCode -#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) -#endif - #include #define SYM53C416_SCSI_ID 7 diff -urN linux-2.5.65-bk2/drivers/serial/8250_pnp.c linux-2.5.65-bk3/drivers/serial/8250_pnp.c --- linux-2.5.65-bk2/drivers/serial/8250_pnp.c Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/drivers/serial/8250_pnp.c Mon Mar 31 12:41:42 2003 @@ -188,6 +188,8 @@ { "MVX00A1", 0 }, /* PC Rider K56 Phone System PnP */ { "MVX00F2", 0 }, + /* NEC 98NOTE SPEAKER PHONE FAX MODEM(33600bps) */ + { "nEC8241", 0 }, /* Pace 56 Voice Internal Plug & Play Modem */ { "PMC2430", 0 }, /* Generic */ @@ -373,6 +375,9 @@ ((port->min == 0x2f8) || (port->min == 0x3f8) || (port->min == 0x2e8) || +#ifdef CONFIG_X86_PC9800 + (port->min == 0x8b0) || +#endif (port->min == 0x3e8))) return 0; } diff -urN linux-2.5.65-bk2/drivers/serial/serial98.c linux-2.5.65-bk3/drivers/serial/serial98.c --- linux-2.5.65-bk2/drivers/serial/serial98.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/drivers/serial/serial98.c Mon Mar 31 12:41:42 2003 @@ -0,0 +1,1124 @@ +/* + * linux/drivers/serial/serial98.c + * + * Driver for NEC PC-9801/PC-9821 standard serial ports + * + * Based on drivers/serial/8250.c, by Russell King. + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * Copyright (C) 2002 Osamu Tomita + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if defined(CONFIG_SERIAL98_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include + +#define SERIAL98_NR 1 +#define SERIAL98_ISR_PASS_LIMIT 256 +#define SERIAL98_EXT 0x434 + +//#define RX_8251F 0x130 /* In: Receive buffer */ +//#define TX_8251F 0x130 /* Out: Transmit buffer */ +//#define LSR_8251F 0x132 /* In: Line Status Register */ +//#define MSR_8251F 0x134 /* In: Modem Status Register */ +#define IIR_8251F 0x136 /* In: Interrupt ID Register */ +#define FCR_8251F 0x138 /* I/O: FIFO Control Register */ +#define VFAST_8251F 0x13a /* I/O: VFAST mode Register */ + +#define CMD_8251F 0x32 /* Out: 8251 Command Resister */ +#define IER2_8251F 0x34 /* I/O: Interrupt Enable Register */ +#define IER1_8251F 0x35 /* I/O: Interrupt Enable Register */ +#define IER1_CTL 0x37 /* Out: Interrupt Enable Register */ +#define DIS_RXR_INT 0x00 /* disable RxRDY Interrupt */ +#define ENA_RXR_INT 0x01 /* enable RxRDY Interrupt */ +#define DIS_TXE_INT 0x02 /* disable TxEMPTY Interrupt */ +#define ENA_TXE_INT 0x03 /* enable TxEMPTY Interrupt */ +#define DIS_TXR_INT 0x04 /* disable TxRDY Interrupt */ +#define ENA_TXR_INT 0x05 /* enable TxRDY Interrupt */ + +#define CMD_RESET 0x40 /* Reset Command */ +#define CMD_RTS 0x20 /* Set RTS line */ +#define CMD_CLR_ERR 0x10 /* Clear error flag */ +#define CMD_BREAK 0x08 /* Send Break */ +#define CMD_RXE 0x04 /* Enable receive */ +#define CMD_DTR 0x02 /* Set DTR line */ +#define CMD_TXE 0x01 /* Enable send */ +#define CMD_DUMMY 0x00 /* Dummy Command */ + +#define VFAST_ENABLE 0x80 /* V.Fast mode Enable */ + +/* Interrupt masks */ +#define INTR_8251_TXRE 0x04 +#define INTR_8251_TXEE 0x02 +#define INTR_8251_RXRE 0x01 +/* I/O Port */ +//#define PORT_8251_DATA 0 +//#define PORT_8251_CMD 2 +//#define PORT_8251_MOD 2 +//#define PORT_8251_STS 2 +/* status read */ +#define STAT_8251_TXRDY 0x01 +#define STAT_8251_RXRDY 0x02 +#define STAT_8251_TXEMP 0x04 +#define STAT_8251_PER 0x08 +#define STAT_8251_OER 0x10 +#define STAT_8251_FER 0x20 +#define STAT_8251_BRK 0x40 +#define STAT_8251_DSR 0x80 +#if 1 +#define STAT_8251F_TXEMP 0x01 +#define STAT_8251F_TXRDY 0x02 +#define STAT_8251F_RXRDY 0x04 +#define STAT_8251F_DSR 0x08 +#define STAT_8251F_OER 0x10 +#define STAT_8251F_PER 0x20 +#define STAT_8251F_FER 0x40 +#define STAT_8251F_BRK 0x80 +#else +#define STAT_8251F_TXEMP 0x01 +#define STAT_8251F_TEMT 0x01 +#define STAT_8251F_TXRDY 0x02 +#define STAT_8251F_THRE 0x02 +#define STAT_8251F_RXRDY 0x04 +#define STAT_8251F_DSR 0x04 +#define STAT_8251F_PER 0x08 +#define STAT_8251F_OER 0x10 +#define STAT_8251F_FER 0x20 +#define STAT_8251F_BRK 0x40 +#endif + +/* + * We wrap our port structure around the generic uart_port. + */ +struct serial98_port { + struct uart_port port; + unsigned int type; + unsigned int ext; + unsigned int lsr_break_flag; + unsigned char cmd; + unsigned char mode; + unsigned char msr; + unsigned char ier; + unsigned char rxchk; + unsigned char txemp; + unsigned char txrdy; + unsigned char rxrdy; + unsigned char brk; + unsigned char fe; + unsigned char oe; + unsigned char pe; + unsigned char dr; +}; + +#ifdef CONFIG_SERIAL98_CONSOLE +static void +serial98_console_write(struct console *co, const char *s, unsigned int count); +static kdev_t serial98_console_device(struct console *co); +static int __init serial98_console_setup(struct console *co, char *options); + +static struct console serial98_console = { + .name = "ttyS", + .write = serial98_console_write, + .device = serial98_console_device, + .setup = serial98_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +#define SERIAL98_CONSOLE &serial98_console +#else +#define SERIAL98_CONSOLE NULL +#endif + +static struct uart_driver serial98_reg = { + .owner = THIS_MODULE, + .driver_name = "serial98", + .dev_name = "ttyS%d", + .major = TTY_MAJOR, + .minor = 64, + .nr = SERIAL98_NR, + .cons = SERIAL98_CONSOLE, +}; + +static int serial98_clk; +static char type_str[48]; + +#define PORT98 ((struct serial98_port *)port) +#define PORT (PORT98->port) + +static void serial98_fifo_enable(struct uart_port *port, int enable) +{ + unsigned char fcr; + + if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { + fcr = inb(FCR_8251F); + if (enable) + fcr |= UART_FCR_ENABLE_FIFO; + else + fcr &= ~UART_FCR_ENABLE_FIFO; + outb(fcr, FCR_8251F); + } + + if (!enable) + return; + + outb(0, 0x5f); /* wait */ + outb(0, 0x5f); + outb(0, 0x5f); + outb(0, 0x5f); +} + +static void serial98_cmd_out(struct uart_port *port, unsigned char cmd) +{ + serial98_fifo_enable(port, 0); + outb(cmd, CMD_8251F); + serial98_fifo_enable(port, 1); +} + +static void serial98_mode_set(struct uart_port *port) +{ + serial98_cmd_out(port, CMD_DUMMY); + serial98_cmd_out(port, CMD_DUMMY); + serial98_cmd_out(port, CMD_DUMMY); + serial98_cmd_out(port, CMD_RESET); + serial98_cmd_out(port, PORT98->mode); +} + +static unsigned char serial98_msr_in(struct uart_port *port) +{ + unsigned long flags; + unsigned int ms, st; + unsigned int tmp; + + spin_lock_irqsave(&PORT.lock, flags); + if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { + PORT98->msr = inb(PORT.iobase + 4); + } else { + ms = inb(0x33); + st = inb(0x32); + tmp = 0; + if(!(ms & 0x20)) + tmp |= UART_MSR_DCD; + if(!(ms & 0x80)) { + tmp |= UART_MSR_RI; + PORT98->msr |= UART_MSR_RI; + } + if(!(ms & 0x40)) + tmp |= UART_MSR_CTS; + if(st & 0x80) + tmp |= UART_MSR_DSR; + PORT98->msr = ((PORT98->msr ^ tmp) >> 4) | tmp; + } + + spin_unlock_irqrestore(&PORT.lock, flags); + return PORT98->msr; +} + +static void serial98_stop_tx(struct uart_port *port, unsigned int tty_stop) +{ + unsigned int ier = inb(IER1_8251F); + + ier &= ~(INTR_8251_TXRE | INTR_8251_TXEE); + outb(ier, IER1_8251F); +} + +static void serial98_start_tx(struct uart_port *port, unsigned int tty_start) +{ + unsigned int ier = inb(IER1_8251F); + + ier |= INTR_8251_TXRE | INTR_8251_TXEE; + outb(ier, IER1_8251F); +} + +static void serial98_stop_rx(struct uart_port *port) +{ + PORT.read_status_mask &= ~PORT98->dr; + outb(DIS_RXR_INT, IER1_CTL); +} + +static void serial98_enable_ms(struct uart_port *port) +{ + outb(PORT98->ier | 0x80, IER2_8251F); +} + +static void serial98_rx_chars(struct uart_port *port, int *status, + struct pt_regs *regs) +{ + struct tty_struct *tty = PORT.info->tty; + unsigned char ch; + int max_count = 256; + + do { + if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) { + tty->flip.work.func((void *)tty); + if (tty->flip.count >= TTY_FLIPBUF_SIZE) + return; // if TTY_DONT_FLIP is set + } + ch = inb(PORT.iobase); + *tty->flip.char_buf_ptr = ch; + *tty->flip.flag_buf_ptr = TTY_NORMAL; + PORT.icount.rx++; + + if (unlikely(*status & (PORT98->brk | PORT98->pe | + PORT98->fe | PORT98->oe))) { + /* + * For statistics only + */ + if (*status & PORT98->brk) { + *status &= ~(PORT98->fe | PORT98->pe); + PORT.icount.brk++; + /* + * We do the SysRQ and SAK checking + * here because otherwise the break + * may get masked by ignore_status_mask + * or read_status_mask. + */ + if (uart_handle_break(&PORT)) + goto ignore_char; + } else if (*status & PORT98->pe) + PORT.icount.parity++; + else if (*status & PORT98->fe) + PORT.icount.frame++; + if (*status & PORT98->oe) + PORT.icount.overrun++; + + /* + * Mask off conditions which should be ingored. + */ + *status &= PORT.read_status_mask; + +#ifdef CONFIG_SERIAL98_CONSOLE + if (PORT.line == PORT.cons->index) { + /* Recover the break flag from console xmit */ + *status |= PORT98->lsr_break_flag; + PORT98->lsr_break_flag = 0; + } +#endif + if (*status & PORT98->brk) { + *tty->flip.flag_buf_ptr = TTY_BREAK; + } else if (*status & PORT98->pe) + *tty->flip.flag_buf_ptr = TTY_PARITY; + else if (*status & PORT98->fe) + *tty->flip.flag_buf_ptr = TTY_FRAME; + } + if (uart_handle_sysrq_char(&PORT, ch, regs)) + goto ignore_char; + if ((*status & PORT.ignore_status_mask) == 0) { + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + if ((*status & PORT98->oe) && + tty->flip.count < TTY_FLIPBUF_SIZE) { + /* + * Overrun is special, since it's reported + * immediately, and doesn't affect the current + * character. + */ + *tty->flip.flag_buf_ptr = TTY_OVERRUN; + tty->flip.flag_buf_ptr++; + tty->flip.char_buf_ptr++; + tty->flip.count++; + } + ignore_char: + *status = inb(PORT.iobase + 2); + } while ((*status & PORT98->rxchk) && (max_count-- > 0)); + tty_flip_buffer_push(tty); +} + +static void serial98_tx_chars(struct uart_port *port) +{ + struct circ_buf *xmit = &PORT.info->xmit; + int count; + + if (PORT.x_char) { + outb(PORT.x_char, PORT.iobase); + PORT.icount.tx++; + PORT.x_char = 0; + return; + } + if (uart_circ_empty(xmit) || uart_tx_stopped(&PORT)) { + serial98_stop_tx(port, 0); + return; + } + + count = PORT.fifosize; + do { + outb(xmit->buf[xmit->tail], PORT.iobase); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + PORT.icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (--count > 0); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(&PORT); + + if (uart_circ_empty(xmit)) + serial98_stop_tx(&PORT, 0); +} + +static void serial98_modem_status(struct uart_port *port) +{ + int status; + + status = serial98_msr_in(port); + + if ((status & UART_MSR_ANY_DELTA) == 0) + return; + + if (status & UART_MSR_TERI) + PORT.icount.rng++; + if (status & UART_MSR_DDSR) + PORT.icount.dsr++; + if (status & UART_MSR_DDCD) + uart_handle_dcd_change(&PORT, status & UART_MSR_DCD); + if (status & UART_MSR_DCTS) + uart_handle_cts_change(&PORT, status & UART_MSR_CTS); + + wake_up_interruptible(&PORT.info->delta_msr_wait); +} + +static void serial98_int(int irq, void *port, struct pt_regs *regs) +{ + unsigned int status; + + spin_lock(&PORT.lock); + status = inb(PORT.iobase + 2); + if (status & PORT98->rxrdy) { + serial98_rx_chars(port, &status, regs); + } + serial98_modem_status(port); + if (status & PORT98->txrdy) { + serial98_tx_chars(port); + } + spin_unlock(&PORT.lock); +} + +static unsigned int serial98_tx_empty(struct uart_port *port) +{ + unsigned long flags; + unsigned int ret = 0; + + spin_lock_irqsave(&PORT.lock, flags); + if (inb(PORT.iobase + 2) & PORT98->txemp) + ret = TIOCSER_TEMT; + + spin_unlock_irqrestore(&PORT.lock, flags); + return ret; +} + +static unsigned int serial98_get_mctrl(struct uart_port *port) +{ + unsigned char status; + unsigned int ret = 0; + + status = serial98_msr_in(port); + if (status & UART_MSR_DCD) + ret |= TIOCM_CAR; + if (status & UART_MSR_RI) + ret |= TIOCM_RNG; + if (status & UART_MSR_DSR) + ret |= TIOCM_DSR; + if (status & UART_MSR_CTS) + ret |= TIOCM_CTS; + return ret; +} + +static void serial98_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + PORT98->cmd &= 0xdd; + if (mctrl & TIOCM_RTS) + PORT98->cmd |= CMD_RTS; + + if (mctrl & TIOCM_DTR) + PORT98->cmd |= CMD_DTR; + + serial98_cmd_out(port, PORT98->cmd); +} + +static void serial98_break_ctl(struct uart_port *port, int break_state) +{ + unsigned long flags; + + spin_lock_irqsave(&PORT.lock, flags); + if (break_state == -1) + PORT98->cmd |= CMD_BREAK; + else + PORT98->cmd &= ~CMD_BREAK; + + serial98_cmd_out(port, PORT98->cmd); + spin_unlock_irqrestore(&PORT.lock, flags); +} + +static int serial98_startup(struct uart_port *port) +{ + int retval; + + if (PORT.type == PORT_8251_PC98) { + /* Wake up UART */ + PORT98->mode = 0xfc; + serial98_mode_set(port); + outb(DIS_RXR_INT, IER1_CTL); + outb(DIS_TXE_INT, IER1_CTL); + outb(DIS_TXR_INT, IER1_CTL); + PORT98->mode = 0; + serial98_mode_set(port); + } + + /* + * Clear the FIFO buffers and disable them. + * (they will be reeanbled in set_termios()) + */ + if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { + outb(UART_FCR_ENABLE_FIFO, FCR_8251F); + outb((UART_FCR_ENABLE_FIFO + | UART_FCR_CLEAR_RCVR + | UART_FCR_CLEAR_XMIT), FCR_8251F); + outb(0, FCR_8251F); + } + + /* Clear the interrupt registers. */ + inb(0x30); + inb(0x32); + if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { + inb(PORT.iobase); + inb(PORT.iobase + 2); + inb(PORT.iobase + 4); + inb(PORT.iobase + 6); + } + + /* Allocate the IRQ */ + retval = request_irq(PORT.irq, serial98_int, 0, + serial98_reg.driver_name, port); + if (retval) + return retval; + + /* + * Now, initialize the UART + */ + PORT98->mode = 0x4e; + serial98_mode_set(port); + PORT98->cmd = 0x15; + serial98_cmd_out(port, PORT98->cmd); + PORT98->cmd = 0x05; + + /* + * Finally, enable interrupts + */ + outb(0x00, IER2_8251F); + outb(ENA_RXR_INT, IER1_CTL); + + /* + * And clear the interrupt registers again for luck. + */ + inb(0x30); + inb(0x32); + if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { + inb(PORT.iobase); + inb(PORT.iobase + 2); + inb(PORT.iobase + 4); + inb(PORT.iobase + 6); + } + + return 0; +} + +static void serial98_shutdown(struct uart_port *port) +{ + unsigned long flags; + + /* + * disable all interrupts + */ + spin_lock_irqsave(&PORT.lock, flags); + if (PORT.type == PORT_VFAST_PC98) + outb(0, VFAST_8251F); /* V.FAST mode off */ + + /* disnable all modem status interrupt */ + outb(0x80, IER2_8251F); + + /* disnable TX/RX interrupt */ + outb(0x00, IER2_8251F); + outb(DIS_RXR_INT, IER1_CTL); + outb(DIS_TXE_INT, IER1_CTL); + outb(DIS_TXR_INT, IER1_CTL); + PORT98->ier = 0; + + spin_unlock_irqrestore(&PORT.lock, flags); + + /* + * Free the interrupt + */ + free_irq(PORT.irq, port); + + /* disable break condition and disable the port */ + serial98_mode_set(port); + + /* disable FIFO's */ + if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { + outb((UART_FCR_ENABLE_FIFO + | UART_FCR_CLEAR_RCVR + | UART_FCR_CLEAR_XMIT), FCR_8251F); + outb(0, FCR_8251F); + } + + inb(PORT.iobase); +} + +static void +serial98_set_termios(struct uart_port *port, struct termios *termios, + struct termios *old) +{ + unsigned char stopbit, cval, fcr = 0, ier = 0; + unsigned long flags; + unsigned int baud, quot; + + stopbit = 0x80; + switch (termios->c_cflag & CSIZE) { + case CS5: + cval = 0x42; + stopbit = 0xc0; + break; + case CS6: + cval = 0x46; + break; + case CS7: + cval = 0x4a; + break; + default: + case CS8: + cval = 0x4e; + break; + } + + if (termios->c_cflag & CSTOPB) + cval ^= stopbit; + if (termios->c_cflag & PARENB) + cval |= 0x10; + if (!(termios->c_cflag & PARODD)) + cval |= 0x20; + + /* + * Ask the core to calculate the divisor for us. + */ + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + quot = uart_get_divisor(port, baud); + + if (PORT.type == PORT_FIFO_PC98 || PORT.type == PORT_VFAST_PC98) { + if ((PORT.uartclk / quot) < (2400 * 16)) + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; + else + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8; + } + + /* + * Ok, we're now changing the port state. Do it with + * interrupts disabled. + */ + spin_lock_irqsave(&PORT.lock, flags); + + /* + * Update the per-port timeout. + */ + uart_update_timeout(port, termios->c_cflag, baud); + + PORT.read_status_mask = PORT98->oe | PORT98->txemp | PORT98->dr; + if (termios->c_iflag & INPCK) + PORT.read_status_mask |= PORT98->fe | PORT98->pe; + + if (termios->c_iflag & (BRKINT | PARMRK)) + PORT.read_status_mask |= PORT98->brk; + /* + * Characters to ignore + */ + PORT.ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + PORT.ignore_status_mask |= PORT98->fe | PORT98->pe; + + if (termios->c_iflag & IGNBRK) { + PORT.ignore_status_mask |= PORT98->brk; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + PORT.ignore_status_mask |= PORT98->oe; + } + + /* + * ignore all characters if CREAD is not set + */ + if ((termios->c_cflag & CREAD) == 0) + PORT.ignore_status_mask |= PORT98->dr; + + /* + * CTS flow control flag and modem status interrupts + */ + if (PORT.flags & UPF_HARDPPS_CD) + ier |= 0x80; /* enable modem status interrupt */ + if (termios->c_cflag & CRTSCTS) { + ier |= 0x08; /* enable CTS interrupt */ + ier |= 0x80; /* enable modem status interrupt */ + } + if (!(termios->c_cflag & CLOCAL)) { + ier |= 0x20; /* enable CD interrupt */ + ier |= 0x80; /* enable modem status interrupt */ + } + PORT98->ier = ier; + + PORT98->mode = cval; + serial98_mode_set(port); + if (PORT.type == PORT_VFAST_PC98 && quot <= 48) { + quot /= 4; + if (quot < 1) + quot = 1; + outb(quot | VFAST_ENABLE, VFAST_8251F); + } else { + quot /= 3; + if (quot < 1) + quot = 1; + if (PORT.type == PORT_VFAST_PC98) + outb(0, VFAST_8251F); /* V.FAST mode off */ + outb(0xb6, 0x77); + outb(quot & 0xff, 0x75); /* LS of divisor */ + outb(quot >> 8, 0x75); /* MS of divisor */ + } + + if (fcr & UART_FCR_ENABLE_FIFO) { + outb(UART_FCR_ENABLE_FIFO, FCR_8251F); + outb(fcr, FCR_8251F); + } + + /* enable RX/TX */ + PORT98->cmd = 0x15; + serial98_cmd_out(port, PORT98->cmd); + PORT98->cmd = 0x05; + /* enable interrupts */ + outb(0x00, IER2_8251F); + outb(ENA_RXR_INT, IER1_CTL); + spin_unlock_irqrestore(&PORT.lock, flags); +} + +static const char *serial98_type(struct uart_port *port) +{ + char *p; + + switch (PORT.type) { + case PORT_8251_PC98: + p = "PC98 onboard legacy 8251"; + break; + case PORT_19K_PC98: + p = "PC98 onboard max 19200bps"; + break; + case PORT_FIFO_PC98: + p = "PC98 onboard with FIFO"; + break; + case PORT_VFAST_PC98: + p = "PC98 onboard V.FAST"; + break; + case PORT_PC9861: + p = "PC-9861K RS-232C ext. board"; + break; + case PORT_PC9801_101: + p = "PC-9801-101 RS-232C ext. board"; + break; + default: + return NULL; + } + + sprintf(type_str, "%s Clock %dMHz", p, serial98_clk); + return type_str; +} + +/* Release the region(s) being used by 'port' */ +static void serial98_release_port(struct uart_port *port) +{ + switch (PORT.type) { + case PORT_VFAST_PC98: + release_region(PORT.iobase + 0xa, 1); + case PORT_FIFO_PC98: + release_region(PORT.iobase + 8, 1); + release_region(PORT.iobase + 6, 1); + release_region(PORT.iobase + 4, 1); + release_region(PORT.iobase + 2, 1); + release_region(PORT.iobase, 1); + case PORT_19K_PC98: + release_region(SERIAL98_EXT, 1); + release_region(0x34, 1); + case PORT_8251_PC98: + release_region(0x32, 1); + release_region(0x30, 1); + } +} + +/* Request the region(s) being used by 'port' */ +#define REQ_REGION98(base) (request_region((base), 1, serial98_reg.driver_name)) +static int serial98_request_region(unsigned int type) +{ + if (!REQ_REGION98(0x30)) + return -EBUSY; + if (REQ_REGION98(0x32)) { + if (type == PORT_8251_PC98) + return 0; + if (REQ_REGION98(0x34)) { + if (REQ_REGION98(SERIAL98_EXT)) { + unsigned long base; + + if (type == PORT_19K_PC98) + return 0; + for (base = 0x130; base <= 0x138; base += 2) { + if (!REQ_REGION98(base)) { + base -= 2; + goto err; + } + } + if (type == PORT_FIFO_PC98) + return 0; + if (type == PORT_VFAST_PC98) { + if (REQ_REGION98(0x13a)) + return 0; + } + err: + while (base >= 0x130) { + release_region(base, 1); + base -= 2; + } + release_region(SERIAL98_EXT, 1); + } + release_region(0x34, 1); + } + release_region(0x32, 1); + } + release_region(0x30, 1); + return -EBUSY; +} + +static int serial98_request_port(struct uart_port *port) +{ + return serial98_request_region(PORT.type); +} + +/* + * Configure/autoconfigure the port. + */ +static void serial98_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE) + PORT.type = PORT98->type; +} + +/* + * verify the new serial_struct (for TIOCSSERIAL). + */ +static int serial98_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + switch (ser->type) { + case PORT_VFAST_PC98: + case PORT_FIFO_PC98: + case PORT_19K_PC98: + case PORT_8251_PC98: + /* not implemented yet + case PORT_PC9861: + case PORT_PC9801_101: + */ + case PORT_UNKNOWN: + break; + default: + return -EINVAL; + } + if (ser->irq < 0 || ser->irq >= NR_IRQS) + return -EINVAL; + if (ser->baud_base < 9600) + return -EINVAL; + return 0; +} + +static struct uart_ops serial98_ops = { + .tx_empty = serial98_tx_empty, + .set_mctrl = serial98_set_mctrl, + .get_mctrl = serial98_get_mctrl, + .stop_tx = serial98_stop_tx, + .start_tx = serial98_start_tx, + .stop_rx = serial98_stop_rx, + .enable_ms = serial98_enable_ms, + .break_ctl = serial98_break_ctl, + .startup = serial98_startup, + .shutdown = serial98_shutdown, + .set_termios = serial98_set_termios, + .type = serial98_type, + .release_port = serial98_release_port, + .request_port = serial98_request_port, + .config_port = serial98_config_port, + .verify_port = serial98_verify_port, +}; + +static struct serial98_port serial98_ports[SERIAL98_NR] = { + { + .port = { + .iobase = 0x30, + .iotype = SERIAL_IO_PORT, + .irq = 4, + .fifosize = 1, + .ops = &serial98_ops, + .flags = ASYNC_BOOT_AUTOCONF, + .line = 0, + }, + .rxchk = STAT_8251_RXRDY, + .txemp = STAT_8251_TXEMP, + .txrdy = STAT_8251_TXRDY, + .rxrdy = STAT_8251_RXRDY, + .brk = STAT_8251_BRK, + .fe = STAT_8251_FER, + .oe = STAT_8251_OER, + .pe = STAT_8251_PER, + .dr = STAT_8251_DSR, + }, +}; + +#ifdef CONFIG_SERIAL98_CONSOLE + +#define BOTH_EMPTY (PORT98->txemp | PORT98->txrdy) + +/* + * Wait for transmitter & holding register to empty + */ +static inline void wait_for_xmitr(struct uart_port *port) +{ + unsigned int status, tmout = 10000; + + /* Wait up to 10ms for the character(s) to be sent. */ + do { + status = inb(PORT.iobase + 2); + + if (status & PORT98->brk) + PORT98->lsr_break_flag = PORT98->brk; + + if (--tmout == 0) + break; + udelay(1); + } while ((status & BOTH_EMPTY) != BOTH_EMPTY); + + /* Wait up to 1s for flow control if necessary */ + if (PORT.flags & UPF_CONS_FLOW) { + tmout = 1000000; + while (--tmout && + ((serial98_msr_in(port) & UART_MSR_CTS) == 0)) + udelay(1); + } +} + +/* + * Print a string to the serial port trying not to disturb + * any possible real use of the port... + * + * The console_lock must be held when we get here. + */ +static void +serial98_console_write(struct console *co, const char *s, unsigned int count) +{ + struct uart_port *port = (struct uart_port *)&serial98_ports[co->index]; + unsigned int ier1, ier2; + int i; + + /* + * First save the UER then disable the interrupts + */ + ier1 = inb(IER1_8251F); + ier2 = inb(IER2_8251F); + /* disnable all modem status interrupt */ + outb(0x80, IER2_8251F); + + /* disnable TX/RX interrupt */ + outb(0x00, IER2_8251F); + outb(DIS_RXR_INT, IER1_CTL); + outb(DIS_TXE_INT, IER1_CTL); + outb(DIS_TXR_INT, IER1_CTL); + + /* + * Now, do each character + */ + for (i = 0; i < count; i++, s++) { + wait_for_xmitr(port); + + /* + * Send the character out. + * If a LF, also do CR... + */ + outb(*s, PORT.iobase); + if (*s == 10) { + wait_for_xmitr(port); + outb(13, PORT.iobase); + } + } + + /* + * Finally, wait for transmitter to become empty + * and restore the IER + */ + wait_for_xmitr(port); + + /* restore TX/RX interrupt */ + outb(0x00, IER2_8251F); + if (ier1 & 0x01) + outb(ENA_RXR_INT, IER1_CTL); + if (ier1 & 0x02) + outb(ENA_TXE_INT, IER1_CTL); + if (ier1 & 0x04) + outb(ENA_TXR_INT, IER1_CTL); + + /* restore modem status interrupt */ + outb(ier2, IER2_8251F); +} + +static kdev_t serial98_console_device(struct console *co) +{ + return mk_kdev(TTY_MAJOR, 64 + co->index); +} + +static int __init serial98_console_setup(struct console *co, char *options) +{ + struct uart_port *port; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + /* + * Check whether an invalid uart number has been specified, and + * if so, search for the first available port that does have + * console support. + */ + if (co->index >= SERIAL98_NR) + co->index = 0; + port = &serial98_ports[co->index].port; + + /* + * Temporary fix. + */ + spin_lock_init(&port->lock); + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + + return uart_set_options(port, co, baud, parity, bits, flow); +} + +void __init serial98_console_init(void) +{ + register_console(&serial98_console); +} + +#endif /* CONFIG_SERIAL98_CONSOLE */ + + +static int __init serial98_init(void) +{ + int ret; + unsigned char iir1, iir2; + + if (PC9800_8MHz_P()) { + serial98_clk = 8; + serial98_ports[0].port.uartclk = 374400 * 16; + } else { + serial98_clk = 5; + serial98_ports[0].port.uartclk = 460800 * 16; + } + + printk(KERN_INFO "serial98: PC-9801 standard serial port driver Version 0.1alpha\n"); + serial98_ports[0].type = PORT_8251_PC98; + /* Check FIFO exist */ + iir1 = inb(IIR_8251F); + iir2 = inb(IIR_8251F); + if ((iir1 & 0x40) != (iir2 & 0x40) && (iir1 & 0x20) == (iir2 & 0x20)) { + serial98_ports[0].port.iobase = 0x130; + serial98_ports[0].port.fifosize = 16; + serial98_ports[0].rxchk = STAT_8251F_DSR; + serial98_ports[0].txemp = STAT_8251F_TXEMP; + serial98_ports[0].txrdy = STAT_8251F_TXRDY; + serial98_ports[0].rxrdy = STAT_8251F_RXRDY; + serial98_ports[0].brk = STAT_8251F_BRK; + serial98_ports[0].fe = STAT_8251F_FER; + serial98_ports[0].oe = STAT_8251F_OER; + serial98_ports[0].pe = STAT_8251F_PER; + serial98_ports[0].dr = STAT_8251F_DSR; + + if (*(unsigned char*)__va(PC9821SCA_RSFLAGS) & 0x10) + serial98_ports[0].type = PORT_VFAST_PC98; + else { + outb(serial98_ports[0].ext | 0x40, SERIAL98_EXT); + serial98_ports[0].port.uartclk *= 4; + serial98_ports[0].type = PORT_FIFO_PC98; + } + } else if ((serial98_ports[0].ext = inb(SERIAL98_EXT)) != 0xff) { + outb(serial98_ports[0].ext | 0x40, SERIAL98_EXT); + if (inb(SERIAL98_EXT) == (serial98_ports[0].ext | 0x40)) { + serial98_ports[0].port.uartclk *= 4; + serial98_ports[0].type = PORT_19K_PC98; + } else { + serial98_ops.enable_ms = NULL; + outb(serial98_ports[0].ext, SERIAL98_EXT); + } + } + + if (serial98_request_region(serial98_ports[0].type)) + return -EBUSY; + + ret = uart_register_driver(&serial98_reg); + if (ret == 0) { + int i; + + for (i = 0; i < SERIAL98_NR; i++) { + uart_add_one_port(&serial98_reg, + (struct uart_port *)&serial98_ports[i]); + } + } + + return ret; +} + +static void __exit serial98_exit(void) +{ + int i; + + if (serial98_ports[0].type == PORT_19K_PC98 + || serial98_ports[0].type == PORT_FIFO_PC98) + outb(serial98_ports[0].ext, SERIAL98_EXT); + + for (i = 0; i < SERIAL98_NR; i++) { + uart_remove_one_port(&serial98_reg, + (struct uart_port *)&serial98_ports[i]); + } + + uart_unregister_driver(&serial98_reg); +} + +module_init(serial98_init); +module_exit(serial98_exit); + +MODULE_AUTHOR("Osamu Tomita "); +MODULE_DESCRIPTION("PC-9801 standard serial port driver Version 0.1alpha"); +MODULE_LICENSE("GPL"); diff -urN linux-2.5.65-bk2/drivers/telephony/ixj.c linux-2.5.65-bk3/drivers/telephony/ixj.c --- linux-2.5.65-bk2/drivers/telephony/ixj.c Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/drivers/telephony/ixj.c Mon Mar 31 12:41:43 2003 @@ -5999,12 +5999,14 @@ if(ixjdebug & 0x0001) { printk(KERN_INFO "Could not copy cadence to kernel\n"); } + kfree(lcp); return -EFAULT; } if (lcp->filter > 5) { if(ixjdebug & 0x0001) { printk(KERN_INFO "Cadence out of range\n"); } + kfree(lcp); return -1; } j->cadence_f[lcp->filter].state = 0; diff -urN linux-2.5.65-bk2/fs/Kconfig linux-2.5.65-bk3/fs/Kconfig --- linux-2.5.65-bk2/fs/Kconfig Mon Mar 17 13:44:08 2003 +++ linux-2.5.65-bk3/fs/Kconfig Mon Mar 31 12:41:43 2003 @@ -1357,6 +1357,35 @@ tristate default NFSD +config SUNRPC + tristate + default m if NFS_FS!=y && NFSD!=y && (NFS_FS=m || NFSD=m) + default y if NFS_FS=y || NFSD=y + +config SUNRPC_GSS + tristate "Provide RPCSEC_GSS authentication (EXPERIMENTAL)" + depends on SUNRPC && EXPERIMENTAL + default SUNRPC if NFS_V4=y + help + Provides cryptographic authentication for NFS rpc requests. To + make this useful, you must also select at least one rpcsec_gss + mechanism. + Note: You should always select this option if you wish to use + NFSv4. + +config RPCSEC_GSS_KRB5 + tristate "Kerberos V mechanism for RPCSEC_GSS (EXPERIMENTAL)" + depends on SUNRPC_GSS && CRYPTO_DES && CRYPTO_MD5 + default SUNRPC_GSS if NFS_V4=y + help + Provides a gss-api mechanism based on Kerberos V5 (this is + mandatory for RFC3010-compliant NFSv4 implementations). + Requires a userspace daemon; + see http://www.citi.umich.edu/projects/nfsv4/. + + Note: If you select this option, please ensure that you also + enable the MD5 and DES crypto ciphers. + config SMB_FS tristate "SMB file system support (to mount Windows shares etc.)" depends on INET @@ -1460,6 +1489,8 @@ will be called ncpfs. Say N unless you are connected to a Novell network. +source "fs/ncpfs/Kconfig" + config CODA_FS tristate "Coda file system support (advanced network fs)" depends on INET @@ -1497,37 +1528,6 @@ support. You will also need a file server daemon, which you can get from . -config SUNRPC - tristate - default m if NFS_FS!=y && NFSD!=y && (NFS_FS=m || NFSD=m) - default y if NFS_FS=y || NFSD=y - -config SUNRPC_GSS - tristate "Provide RPCSEC_GSS authentication (EXPERIMENTAL)" - depends on SUNRPC && EXPERIMENTAL - default SUNRPC if NFS_V4=y - help - Provides cryptographic authentication for NFS rpc requests. To - make this useful, you must also select at least one rpcsec_gss - mechanism. - Note: You should always select this option if you wish to use - NFSv4. - -config RPCSEC_GSS_KRB5 - tristate "Kerberos V mechanism for RPCSEC_GSS (EXPERIMENTAL)" - depends on SUNRPC_GSS && CRYPTO_DES && CRYPTO_MD5 - default SUNRPC_GSS if NFS_V4=y - help - Provides a gss-api mechanism based on Kerberos V5 (this is - mandatory for RFC3010-compliant NFSv4 implementations). - Requires a userspace daemon; - see http://www.citi.umich.edu/projects/nfsv4/. - - Note: If you select this option, please ensure that you also - enable the MD5 and DES crypto ciphers. - -source "fs/ncpfs/Kconfig" - config AFS_FS # for fs/nls/Config.in tristate "Andrew File System support (AFS) (Experimental)" diff -urN linux-2.5.65-bk2/fs/autofs/inode.c linux-2.5.65-bk3/fs/autofs/inode.c --- linux-2.5.65-bk2/fs/autofs/inode.c Mon Mar 17 13:44:22 2003 +++ linux-2.5.65-bk3/fs/autofs/inode.c Mon Mar 31 12:41:43 2003 @@ -16,7 +16,6 @@ #include #include #include "autofs_i.h" -#define __NO_VERSION__ #include static void autofs_put_super(struct super_block *sb) diff -urN linux-2.5.65-bk2/fs/autofs4/inode.c linux-2.5.65-bk3/fs/autofs4/inode.c --- linux-2.5.65-bk2/fs/autofs4/inode.c Mon Mar 17 13:44:22 2003 +++ linux-2.5.65-bk3/fs/autofs4/inode.c Mon Mar 31 12:41:43 2003 @@ -16,7 +16,6 @@ #include #include #include "autofs_i.h" -#define __NO_VERSION__ #include static void ino_lnkfree(struct autofs_info *ino) diff -urN linux-2.5.65-bk2/fs/befs/debug.c linux-2.5.65-bk3/fs/befs/debug.c --- linux-2.5.65-bk2/fs/befs/debug.c Mon Mar 17 13:44:51 2003 +++ linux-2.5.65-bk3/fs/befs/debug.c Mon Mar 31 12:41:43 2003 @@ -80,7 +80,7 @@ befs_block_run tmp_run; - befs_debug(sb, "befs_inode infomation"); + befs_debug(sb, "befs_inode information"); befs_debug(sb, " magic1 %08x", fs32_to_cpu(sb, inode->magic1)); diff -urN linux-2.5.65-bk2/fs/buffer.c linux-2.5.65-bk3/fs/buffer.c --- linux-2.5.65-bk2/fs/buffer.c Mon Mar 17 13:44:08 2003 +++ linux-2.5.65-bk3/fs/buffer.c Mon Mar 31 12:41:44 2003 @@ -532,7 +532,7 @@ * Completion handler for block_write_full_page() - pages which are unlocked * during I/O, and which have PageWriteback cleared upon I/O completion. */ -static void end_buffer_async_write(struct buffer_head *bh, int uptodate) +void end_buffer_async_write(struct buffer_head *bh, int uptodate) { static spinlock_t page_uptodate_lock = SPIN_LOCK_UNLOCKED; unsigned long flags; diff -urN linux-2.5.65-bk2/fs/cifs/cifs_debug.c linux-2.5.65-bk3/fs/cifs/cifs_debug.c --- linux-2.5.65-bk2/fs/cifs/cifs_debug.c Mon Mar 17 13:44:05 2003 +++ linux-2.5.65-bk3/fs/cifs/cifs_debug.c Mon Mar 31 12:41:44 2003 @@ -22,7 +22,6 @@ #include #include #include -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/fs/devfs/base.c linux-2.5.65-bk3/fs/devfs/base.c --- linux-2.5.65-bk2/fs/devfs/base.c Mon Mar 17 13:43:44 2003 +++ linux-2.5.65-bk3/fs/devfs/base.c Mon Mar 31 12:41:44 2003 @@ -758,7 +758,6 @@ rwlock_t lock; /* Lock for searching(R)/updating(W) */ struct devfs_entry *first; struct devfs_entry *last; - unsigned short num_removable; /* Lock for writing but not reading */ unsigned char no_more_additions:1; }; @@ -766,7 +765,6 @@ { struct block_device_operations *ops; dev_t dev; - unsigned char removable:1; }; struct cdev_type @@ -916,7 +914,7 @@ * @de: The handle to the devfs entry. */ -void devfs_put (devfs_handle_t de) +static void devfs_put (devfs_handle_t de) { if (!de) return; VERIFY_ENTRY (de); @@ -1017,7 +1015,6 @@ * _devfs_append_entry - Append a devfs entry to a directory's child list. * @dir: The directory to add to. * @de: The devfs entry to append. - * @removable: If TRUE, increment the count of removable devices for %dir. * @old_de: If an existing entry exists, it will be written here. This may * be %NULL. An implicit devfs_get() is performed on this entry. * @@ -1028,7 +1025,7 @@ */ static int _devfs_append_entry (devfs_handle_t dir, devfs_handle_t de, - int removable, devfs_handle_t *old_de) + devfs_handle_t *old_de) { int retval; @@ -1056,7 +1053,6 @@ if (dir->u.dir.first == NULL) dir->u.dir.first = de; else dir->u.dir.last->next = de; dir->u.dir.last = de; - if (removable) ++dir->u.dir.num_removable; retval = 0; } else retval = -EEXIST; @@ -1095,13 +1091,13 @@ == NULL ) return NULL; new->u.cdev.dev = devfs_alloc_devnum (S_IFCHR |S_IRUSR |S_IWUSR); new->u.cdev.ops = &devfsd_fops; - _devfs_append_entry (root_entry, new, FALSE, NULL); + _devfs_append_entry (root_entry, new, NULL); #ifdef CONFIG_DEVFS_DEBUG if ( ( new = _devfs_alloc_entry (".stat", 0, S_IFCHR | S_IRUGO | S_IWUGO) ) == NULL ) return NULL; new->u.cdev.dev = devfs_alloc_devnum (S_IFCHR | S_IRUGO | S_IWUGO); new->u.cdev.ops = &stat_fops; - _devfs_append_entry (root_entry, new, FALSE, NULL); + _devfs_append_entry (root_entry, new, NULL); #endif return root_entry; } /* End Function _devfs_get_root_entry */ @@ -1164,7 +1160,7 @@ { de = _devfs_alloc_entry (name, next_pos, MODE_DIR); devfs_get (de); - if ( !de || _devfs_append_entry (dir, de, FALSE, &old) ) + if ( !de || _devfs_append_entry (dir, de, &old) ) { devfs_put (de); if ( !old || !S_ISDIR (old->mode) ) @@ -1498,7 +1494,6 @@ de->u.bdev.dev = dev; de->u.cdev.autogen = devnum != 0; de->u.bdev.ops = ops; - if (flags & DEVFS_FL_REMOVABLE) de->u.bdev.removable = TRUE; } else { PRINTK ("(%s): illegal mode: %x\n", name, mode); devfs_put (de); @@ -1516,7 +1511,7 @@ de->inode.uid = 0; de->inode.gid = 0; } - err = _devfs_append_entry(dir, de, flags & DEVFS_FL_REMOVABLE, NULL); + err = _devfs_append_entry(dir, de, NULL); if (err) { PRINTK ("(%s): could not append to parent, err: %d\n", name, err); @@ -1553,8 +1548,6 @@ else de->next->prev = de->prev; de->prev = de; /* Indicate we're unhooked */ de->next = NULL; /* Force early termination for */ - if (S_ISBLK (de->mode) && de->u.bdev.removable ) - --parent->u.dir.num_removable; return TRUE; } /* End Function _devfs_unhook */ @@ -1648,7 +1641,7 @@ de->info = info; de->u.symlink.linkname = newlink; de->u.symlink.length = linklength; - if ( ( err = _devfs_append_entry (dir, de, FALSE, NULL) ) != 0 ) + if ( ( err = _devfs_append_entry (dir, de, NULL) ) != 0 ) { PRINTK ("(%s): could not append to parent, err: %d\n", name, err); devfs_put (dir); @@ -1725,7 +1718,7 @@ return NULL; } de->info = info; - if ( ( err = _devfs_append_entry (dir, de, FALSE, &old) ) != 0 ) + if ( ( err = _devfs_append_entry (dir, de, &old) ) != 0 ) { PRINTK ("(%s): could not append to dir: %p \"%s\", err: %d\n", name, dir, dir->name, err); @@ -1924,102 +1917,6 @@ } /* End Function try_modload */ -/** - * check_disc_changed - Check if a removable disc was changed. - * @de: The device. - * - * Returns 1 if the media was changed, else 0. - * - * This function may block, and may indirectly cause the parent directory - * contents to be changed due to partition re-reading. - */ - -static int check_disc_changed (struct devfs_entry *de) -{ - int tmp; - int retval = 0; - dev_t dev = de->u.bdev.dev; - extern int warn_no_part; - - if (!S_ISBLK(de->mode)) - return 0; - /* Ugly hack to disable messages about unable to read partition table */ - tmp = warn_no_part; - warn_no_part = 0; - retval = __check_disk_change(dev); - warn_no_part = tmp; - return retval; -} /* End Function check_disc_changed */ - -/** - * scan_dir_for_removable - Scan a directory for removable media devices and check media. - * @dir: The directory. - * - * This function may block, and may indirectly cause the directory - * contents to be changed due to partition re-reading. The directory will - * be locked for reading. - */ - -static void scan_dir_for_removable (struct devfs_entry *dir) -{ - struct devfs_entry *de; - - read_lock (&dir->u.dir.lock); - if (dir->u.dir.num_removable < 1) de = NULL; - else - { - for (de = dir->u.dir.first; de != NULL; de = de->next) - { - if (S_ISBLK (de->mode) && de->u.bdev.removable) break; - } - devfs_get (de); - } - read_unlock (&dir->u.dir.lock); - if (de) check_disc_changed (de); - devfs_put (de); -} /* End Function scan_dir_for_removable */ - -/** - * get_removable_partition - Get removable media partition. - * @dir: The parent directory. - * @name: The name of the entry. - * @namelen: The number of characters in <>. - * - * Returns 1 if the media was changed, else 0. - * - * This function may block, and may indirectly cause the directory - * contents to be changed due to partition re-reading. The directory must - * be locked for reading upon entry, and will be unlocked upon exit. - */ - -static int get_removable_partition (struct devfs_entry *dir, const char *name, - unsigned int namelen) -{ - int retval; - struct devfs_entry *de; - - if (dir->u.dir.num_removable < 1) - { - read_unlock (&dir->u.dir.lock); - return 0; - } - for (de = dir->u.dir.first; de != NULL; de = de->next) - { - if (!S_ISBLK (de->mode) || !de->u.bdev.removable) continue; - if (strcmp (de->name, "disc") == 0) break; - /* Support for names where the partition is appended to the disc name - */ - if (de->namelen >= namelen) continue; - if (strncmp (de->name, name, de->namelen) == 0) break; - } - devfs_get (de); - read_unlock (&dir->u.dir.lock); - retval = de ? check_disc_changed (de) : 0; - devfs_put (de); - return retval; -} /* End Function get_removable_partition */ - - /* Superblock operations follow */ static struct inode_operations devfs_iops; @@ -2169,7 +2066,6 @@ switch ( (long) file->f_pos ) { case 0: - scan_dir_for_removable (parent); err = (*filldir) (dirent, "..", 2, file->f_pos, parent_ino (file->f_dentry), DT_DIR); if (err == -EINVAL) break; @@ -2336,6 +2232,8 @@ wait_queue_head_t wait_queue; }; +/* XXX: this doesn't handle the case where we got a negative dentry + but a devfs entry has been registered in the meanwhile */ static int devfs_d_revalidate_wait (struct dentry *dentry, int flags) { struct inode *dir = dentry->d_parent->d_inode; @@ -2380,6 +2278,7 @@ add_wait_queue (&lookup_info->wait_queue, &wait); read_unlock (&parent->u.dir.lock); schedule (); + remove_wait_queue (&lookup_info->wait_queue, &wait); } else read_unlock (&parent->u.dir.lock); return 1; @@ -2407,18 +2306,7 @@ if (parent == NULL) return ERR_PTR (-ENOENT); read_lock (&parent->u.dir.lock); de = _devfs_search_dir (parent, dentry->d_name.name, dentry->d_name.len); - if (de) read_unlock (&parent->u.dir.lock); - else - { /* Try re-reading the partition (media may have changed) */ - if ( get_removable_partition (parent, dentry->d_name.name, - dentry->d_name.len) ) /* Unlocks */ - { /* Media did change */ - read_lock (&parent->u.dir.lock); - de = _devfs_search_dir (parent, dentry->d_name.name, - dentry->d_name.len); - read_unlock (&parent->u.dir.lock); - } - } + read_unlock (&parent->u.dir.lock); lookup_info.de = de; init_waitqueue_head (&lookup_info.wait_queue); dentry->d_fsdata = &lookup_info; @@ -2545,7 +2433,7 @@ de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode); if (!de) return -ENOMEM; de->vfs_deletable = TRUE; - if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 ) + if ( ( err = _devfs_append_entry (parent, de, NULL) ) != 0 ) return err; de->inode.uid = current->euid; de->inode.gid = current->egid; @@ -2613,7 +2501,7 @@ de->u.cdev.dev = rdev; else if (S_ISBLK (mode)) de->u.bdev.dev = rdev; - if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 ) + if ( ( err = _devfs_append_entry (parent, de, NULL) ) != 0 ) return err; de->inode.uid = current->euid; de->inode.gid = current->egid; diff -urN linux-2.5.65-bk2/fs/exportfs/expfs.c linux-2.5.65-bk3/fs/exportfs/expfs.c --- linux-2.5.65-bk2/fs/exportfs/expfs.c Mon Mar 17 13:44:41 2003 +++ linux-2.5.65-bk3/fs/exportfs/expfs.c Mon Mar 31 12:41:44 2003 @@ -447,7 +447,7 @@ * @dentry: the dentry to encode * @fh: where to store the file handle fragment * @max_len: maximum length to store there - * @connectable: whether to store parent infomation + * @connectable: whether to store parent information * * This default encode_fh function assumes that the 32 inode number * is suitable for locating an inode, and that the generation number diff -urN linux-2.5.65-bk2/fs/fat/inode.c linux-2.5.65-bk3/fs/fat/inode.c --- linux-2.5.65-bk2/fs/fat/inode.c Mon Mar 17 13:44:05 2003 +++ linux-2.5.65-bk3/fs/fat/inode.c Mon Mar 31 12:41:44 2003 @@ -939,7 +939,8 @@ error = first; goto out_fail; } - if (FAT_FIRST_ENT(sb, media) != first) { + if (FAT_FIRST_ENT(sb, media) != first + && (media != 0xf8 || FAT_FIRST_ENT(sb, 0xfe) != first)) { if (!silent) { printk(KERN_ERR "FAT: invalid first entry of FAT " "(0x%x != 0x%x)\n", diff -urN linux-2.5.65-bk2/fs/intermezzo/cache.c linux-2.5.65-bk3/fs/intermezzo/cache.c --- linux-2.5.65-bk2/fs/intermezzo/cache.c Mon Mar 17 13:44:04 2003 +++ linux-2.5.65-bk3/fs/intermezzo/cache.c Mon Mar 31 12:41:44 2003 @@ -20,7 +20,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/fs/intermezzo/dcache.c linux-2.5.65-bk3/fs/intermezzo/dcache.c --- linux-2.5.65-bk2/fs/intermezzo/dcache.c Mon Mar 17 13:44:42 2003 +++ linux-2.5.65-bk3/fs/intermezzo/dcache.c Mon Mar 31 12:41:44 2003 @@ -31,7 +31,6 @@ * with heavy changes by Linus Torvalds */ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/fs/intermezzo/dir.c linux-2.5.65-bk3/fs/intermezzo/dir.c --- linux-2.5.65-bk2/fs/intermezzo/dir.c Mon Mar 17 13:43:49 2003 +++ linux-2.5.65-bk3/fs/intermezzo/dir.c Mon Mar 31 12:41:44 2003 @@ -40,7 +40,6 @@ #include #include #include -#define __NO_VERSION__ #include #include "intermezzo_fs.h" diff -urN linux-2.5.65-bk2/fs/intermezzo/ext_attr.c linux-2.5.65-bk3/fs/intermezzo/ext_attr.c --- linux-2.5.65-bk2/fs/intermezzo/ext_attr.c Mon Mar 17 13:44:12 2003 +++ linux-2.5.65-bk3/fs/intermezzo/ext_attr.c Mon Mar 31 12:41:44 2003 @@ -22,7 +22,6 @@ * Extended attribute handling for presto. */ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/fs/intermezzo/file.c linux-2.5.65-bk3/fs/intermezzo/file.c --- linux-2.5.65-bk2/fs/intermezzo/file.c Mon Mar 17 13:44:16 2003 +++ linux-2.5.65-bk3/fs/intermezzo/file.c Mon Mar 31 12:41:44 2003 @@ -45,7 +45,6 @@ #include #include #include -#define __NO_VERSION__ #include #include diff -urN linux-2.5.65-bk2/fs/intermezzo/inode.c linux-2.5.65-bk3/fs/intermezzo/inode.c --- linux-2.5.65-bk2/fs/intermezzo/inode.c Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/fs/intermezzo/inode.c Mon Mar 31 12:41:44 2003 @@ -24,7 +24,6 @@ * Super block/filesystem wide operations */ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/fs/intermezzo/kml.c linux-2.5.65-bk3/fs/intermezzo/kml.c --- linux-2.5.65-bk2/fs/intermezzo/kml.c Mon Mar 17 13:43:37 2003 +++ linux-2.5.65-bk3/fs/intermezzo/kml.c Mon Mar 31 12:41:44 2003 @@ -1,7 +1,6 @@ #include #include #include -#define __NO_VERSION__ #include #include diff -urN linux-2.5.65-bk2/fs/intermezzo/kml_decode.c linux-2.5.65-bk3/fs/intermezzo/kml_decode.c --- linux-2.5.65-bk2/fs/intermezzo/kml_decode.c Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/fs/intermezzo/kml_decode.c Mon Mar 31 12:41:44 2003 @@ -5,7 +5,6 @@ * * Copyright (C) 2001 Mountainview Data, Inc. */ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/fs/intermezzo/kml_reint.c linux-2.5.65-bk3/fs/intermezzo/kml_reint.c --- linux-2.5.65-bk2/fs/intermezzo/kml_reint.c Mon Mar 17 13:44:42 2003 +++ linux-2.5.65-bk3/fs/intermezzo/kml_reint.c Mon Mar 31 12:41:44 2003 @@ -22,7 +22,6 @@ * */ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/fs/intermezzo/kml_setup.c linux-2.5.65-bk3/fs/intermezzo/kml_setup.c --- linux-2.5.65-bk2/fs/intermezzo/kml_setup.c Mon Mar 17 13:44:06 2003 +++ linux-2.5.65-bk3/fs/intermezzo/kml_setup.c Mon Mar 31 12:41:44 2003 @@ -1,7 +1,6 @@ #include #include #include -#define __NO_VERSION__ #include #include diff -urN linux-2.5.65-bk2/fs/intermezzo/methods.c linux-2.5.65-bk3/fs/intermezzo/methods.c --- linux-2.5.65-bk2/fs/intermezzo/methods.c Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/fs/intermezzo/methods.c Mon Mar 31 12:41:44 2003 @@ -40,7 +40,6 @@ #include #include #include -#define __NO_VERSION__ #include #include diff -urN linux-2.5.65-bk2/fs/intermezzo/replicator.c linux-2.5.65-bk3/fs/intermezzo/replicator.c --- linux-2.5.65-bk2/fs/intermezzo/replicator.c Mon Mar 17 13:44:08 2003 +++ linux-2.5.65-bk3/fs/intermezzo/replicator.c Mon Mar 31 12:41:44 2003 @@ -23,7 +23,6 @@ * */ -#define __NO_VERSION__ #include #include diff -urN linux-2.5.65-bk2/fs/intermezzo/super.c linux-2.5.65-bk3/fs/intermezzo/super.c --- linux-2.5.65-bk2/fs/intermezzo/super.c Mon Mar 17 13:44:50 2003 +++ linux-2.5.65-bk3/fs/intermezzo/super.c Mon Mar 31 12:41:44 2003 @@ -42,7 +42,6 @@ #include #include #include -#define __NO_VERSION__ #include #include "intermezzo_fs.h" diff -urN linux-2.5.65-bk2/fs/intermezzo/sysctl.c linux-2.5.65-bk3/fs/intermezzo/sysctl.c --- linux-2.5.65-bk2/fs/intermezzo/sysctl.c Mon Mar 17 13:43:44 2003 +++ linux-2.5.65-bk3/fs/intermezzo/sysctl.c Mon Mar 31 12:41:44 2003 @@ -21,7 +21,6 @@ * Sysctrl entries for Intermezzo! */ -#define __NO_VERSION__ #include /* for CONFIG_PROC_FS */ #include #include diff -urN linux-2.5.65-bk2/fs/jffs/intrep.c linux-2.5.65-bk3/fs/jffs/intrep.c --- linux-2.5.65-bk2/fs/jffs/intrep.c Mon Mar 17 13:44:08 2003 +++ linux-2.5.65-bk3/fs/jffs/intrep.c Mon Mar 31 12:41:44 2003 @@ -55,7 +55,6 @@ * */ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/fs/jffs/jffs_fm.c linux-2.5.65-bk3/fs/jffs/jffs_fm.c --- linux-2.5.65-bk2/fs/jffs/jffs_fm.c Mon Mar 17 13:44:07 2003 +++ linux-2.5.65-bk3/fs/jffs/jffs_fm.c Mon Mar 31 12:41:44 2003 @@ -16,7 +16,6 @@ * Copyright (C) 2000 Alexander Larsson (alex@cendio.se), Cendio Systems AB * */ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/fs/lockd/lockd_syms.c linux-2.5.65-bk3/fs/lockd/lockd_syms.c --- linux-2.5.65-bk2/fs/lockd/lockd_syms.c Mon Mar 17 13:44:08 2003 +++ linux-2.5.65-bk3/fs/lockd/lockd_syms.c Mon Mar 31 12:41:44 2003 @@ -8,7 +8,6 @@ * Copyright (C) 1997 Olaf Kirch */ -#define __NO_VERSION__ #include #include diff -urN linux-2.5.65-bk2/fs/partitions/Kconfig linux-2.5.65-bk3/fs/partitions/Kconfig --- linux-2.5.65-bk2/fs/partitions/Kconfig Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/fs/partitions/Kconfig Mon Mar 31 12:41:44 2003 @@ -177,6 +177,13 @@ If unsure, say N. +config NEC98_PARTITION + bool "NEC PC-9800 partition table support" if PARTITION_ADVANCED + default y if !PARTITION_ADVANCED && X86_PC9800 + help + Say Y here if you would like to be able to read the hard disk + partition table format used by NEC PC-9800 machines. + config SGI_PARTITION bool "SGI partition support" if PARTITION_ADVANCED default y if !PARTITION_ADVANCED && (SGI_IP22 || SGI_IP27) diff -urN linux-2.5.65-bk2/fs/partitions/Makefile linux-2.5.65-bk3/fs/partitions/Makefile --- linux-2.5.65-bk2/fs/partitions/Makefile Mon Mar 17 13:44:04 2003 +++ linux-2.5.65-bk3/fs/partitions/Makefile Mon Mar 31 12:41:44 2003 @@ -16,3 +16,4 @@ obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o obj-$(CONFIG_IBM_PARTITION) += ibm.o obj-$(CONFIG_EFI_PARTITION) += efi.o +obj-$(CONFIG_NEC98_PARTITION) += nec98.o msdos.o diff -urN linux-2.5.65-bk2/fs/partitions/check.c linux-2.5.65-bk3/fs/partitions/check.c --- linux-2.5.65-bk2/fs/partitions/check.c Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/fs/partitions/check.c Mon Mar 31 12:41:44 2003 @@ -28,6 +28,7 @@ #include "ldm.h" #include "mac.h" #include "msdos.h" +#include "nec98.h" #include "osf.h" #include "sgi.h" #include "sun.h" @@ -51,6 +52,9 @@ #ifdef CONFIG_LDM_PARTITION ldm_partition, /* this must come before msdos */ #endif +#ifdef CONFIG_NEC98_PARTITION + nec98_partition, /* must be come before `msdos_partition' */ +#endif #ifdef CONFIG_MSDOS_PARTITION msdos_partition, #endif @@ -156,7 +160,6 @@ { #ifdef CONFIG_DEVFS_FS devfs_handle_t dir; - unsigned int devfs_flags = DEVFS_FL_DEFAULT; struct hd_struct *p = dev->part; char devname[16]; @@ -165,10 +168,8 @@ dir = dev->de; if (!dir) return; - if (dev->flags & GENHD_FL_REMOVABLE) - devfs_flags |= DEVFS_FL_REMOVABLE; sprintf(devname, "part%d", part); - p[part-1].de = devfs_register (dir, devname, devfs_flags, + p[part-1].de = devfs_register (dir, devname, 0, dev->major, dev->first_minor + part, S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); @@ -185,11 +186,8 @@ #ifdef CONFIG_DEVFS_FS int pos = 0; devfs_handle_t dir, slave; - unsigned int devfs_flags = DEVFS_FL_DEFAULT; char dirname[64], symlink[16]; - if (dev->flags & GENHD_FL_REMOVABLE) - devfs_flags |= DEVFS_FL_REMOVABLE; if (dev->flags & GENHD_FL_DEVFS) { dir = dev->de; if (!dir) /* Aware driver wants to block disc management */ @@ -209,7 +207,7 @@ sprintf(symlink, "discs/disc%d", dev->number); devfs_mk_symlink(NULL, symlink, DEVFS_FL_DEFAULT, dirname + pos, &slave, NULL); - dev->disk_de = devfs_register(dir, "disc", devfs_flags, + dev->disk_de = devfs_register(dir, "disc", 0, dev->major, dev->first_minor, S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL); #endif diff -urN linux-2.5.65-bk2/fs/partitions/nec98.c linux-2.5.65-bk3/fs/partitions/nec98.c --- linux-2.5.65-bk2/fs/partitions/nec98.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/fs/partitions/nec98.c Mon Mar 31 12:41:44 2003 @@ -0,0 +1,197 @@ +/* + * NEC PC-9800 series partition supports + * + * Copyright (C) 1999 Kyoto University Microcomputer Club + */ + +#include +#include +#include +#include +#include +#include + +#include "check.h" +#include "nec98.h" + +struct nec98_partition { + __u8 mid; /* 0x80 - active */ + __u8 sid; /* 0x80 - bootable */ + __u16 pad1; /* dummy for padding */ + __u8 ipl_sector; /* IPL sector */ + __u8 ipl_head; /* IPL head */ + __u16 ipl_cyl; /* IPL cylinder */ + __u8 sector; /* starting sector */ + __u8 head; /* starting head */ + __u16 cyl; /* starting cylinder */ + __u8 end_sector; /* end sector */ + __u8 end_head; /* end head */ + __u16 end_cyl; /* end cylinder */ + unsigned char name[16]; +} __attribute__((__packed__)); + +#define NEC98_BSD_PARTITION_MID 0x14 +#define NEC98_BSD_PARTITION_SID 0x44 +#define MID_SID_16(mid, sid) (((mid) & 0xFF) | (((sid) & 0xFF) << 8)) +#define NEC98_BSD_PARTITION_MID_SID \ + MID_SID_16(NEC98_BSD_PARTITION_MID, NEC98_BSD_PARTITION_SID) +#define NEC98_VALID_PTABLE_ENTRY(P) \ + (!(P)->pad1 && (P)->cyl <= (P)->end_cyl) + +extern int pc98_bios_param(struct block_device *bdev, int *ip); + +static inline int +is_valid_nec98_partition_table(const struct nec98_partition *ptable, + __u8 nsectors, __u8 nheads) +{ + int i; + int valid = 0; + + for (i = 0; i < 16; i++) { + if (!*(__u16 *)&ptable[i]) + continue; /* empty slot */ + if (ptable[i].pad1 /* `pad1' contains junk */ + || ptable[i].ipl_sector >= nsectors + || ptable[i].sector >= nsectors + || ptable[i].end_sector >= nsectors + || ptable[i].ipl_head >= nheads + || ptable[i].head >= nheads + || ptable[i].end_head >= nheads + || ptable[i].cyl > ptable[i].end_cyl) + return 0; + valid = 1; /* We have a valid partition. */ + } + /* If no valid PC-9800-style partitions found, + the disk may have other type of partition table. */ + return valid; +} + +#ifdef CONFIG_BSD_DISKLABEL +extern void parse_bsd(struct parsed_partitions *state, + struct block_device *bdev, + u32 offset, u32 size, int origin, char *flavour, + int max_partitions); +#endif + +int nec98_partition(struct parsed_partitions *state, struct block_device *bdev) +{ + unsigned int nr; + struct hd_geometry geo; + Sector sect; + const struct nec98_partition *part; + unsigned char *data; + int sector_size = bdev_hardsect_size(bdev); + int major = MAJOR(bdev->bd_dev); + + if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)&geo) != 0) { + printk(" unsupported disk (major = %u)\n", major); + return 0; + } + +#ifdef NEC98_PARTITION_DEBUG + printk("ioctl_by_bdev head=%d sect=%d\n", geo.heads, geo.sectors); +#endif + data = read_dev_sector(bdev, 0, §); + if (!data) { + if (warn_no_part) + printk(" unable to read partition table\n"); + return -1; + } + + /* magic(?) check */ + if (*(__u16 *)(data + sector_size - 2) != NEC98_PTABLE_MAGIC) { + put_dev_sector(sect); + return 0; + } + + put_dev_sector(sect); + data = read_dev_sector(bdev, 1, §); + if (!data) { + if (warn_no_part) + printk(" unable to read partition table\n"); + return -1; + } + + if (!is_valid_nec98_partition_table((struct nec98_partition *)data, + geo.sectors, geo.heads)) { +#ifdef NEC98_PARTITION_DEBUG + if (warn_no_part) + printk(" partition table consistency check failed" + " (not PC-9800 disk?)\n"); +#endif + put_dev_sector(sect); + return 0; + } + + part = (const struct nec98_partition *)data; + for (nr = 0; nr < 16; nr++, part++) { + unsigned int start_sect, end_sect; + + if (part->mid == 0 || part->sid == 0) + continue; + + if (nr) + printk(" "); + + { /* Print partition name. Fdisk98 might put NUL + characters in partition name... */ + + int j; + unsigned char *p; + unsigned char buf[sizeof (part->name) * 2 + 1]; + + for (p = buf, j = 0; j < sizeof (part->name); j++, p++) + if ((*p = part->name[j]) < ' ') { + *p++ = '^'; + *p = part->name[j] + '@'; + } + + *p = 0; + printk(" <%s>", buf); + } + start_sect = (part->cyl * geo.heads + part->head) * geo.sectors + + part->sector; + end_sect = (part->end_cyl + 1) * geo.heads * geo.sectors; + if (end_sect <= start_sect) { + printk(" (invalid partition info)\n"); + continue; + } + + put_partition(state, nr + 1, start_sect, end_sect - start_sect); +#ifdef CONFIG_BSD_DISKLABEL + if ((*(__u16 *)&part->mid & 0x7F7F) + == NEC98_BSD_PARTITION_MID_SID) { + printk("!"); + /* NEC98_BSD_PARTITION_MID_SID is not valid SYSIND for + IBM PC's MS-DOS partition table, so we simply pass + it to bsd_disklabel_partition; + it will just print `'. */ + parse_bsd(state, bdev, start_sect, + end_sect - start_sect, nr + 1, + "bsd98", BSD_MAXPARTITIONS); + } +#endif + { /* Pretty size printing. */ + /* XXX sector size? */ + unsigned int psize = (end_sect - start_sect) / 2; + int unit_char = 'K'; + + if (psize > 99999) { + psize >>= 10; + unit_char = 'M'; + } + printk(" %5d%cB (%5d-%5d)\n", + psize, unit_char, part->cyl, part->end_cyl); + } + } + + put_dev_sector(sect); + + return nr ? 1 : 0; +} + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff -urN linux-2.5.65-bk2/fs/partitions/nec98.h linux-2.5.65-bk3/fs/partitions/nec98.h --- linux-2.5.65-bk2/fs/partitions/nec98.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/fs/partitions/nec98.h Mon Mar 31 12:41:44 2003 @@ -0,0 +1,10 @@ +/* + * NEC PC-9800 series partition supports + * + * Copyright (C) 1998-2000 Kyoto University Microcomputer Club + */ + +#define NEC98_PTABLE_MAGIC 0xAA55 + +extern int nec98_partition(struct parsed_partitions *state, + struct block_device *bdev); diff -urN linux-2.5.65-bk2/fs/proc/inode.c linux-2.5.65-bk3/fs/proc/inode.c --- linux-2.5.65-bk2/fs/proc/inode.c Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/fs/proc/inode.c Mon Mar 31 12:41:44 2003 @@ -13,7 +13,6 @@ #include #include #include -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_aops.c linux-2.5.65-bk3/fs/xfs/linux/xfs_aops.c --- linux-2.5.65-bk2/fs/xfs/linux/xfs_aops.c Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_aops.c Mon Mar 31 12:41:44 2003 @@ -31,11 +31,55 @@ */ #include -#include -#include #include +STATIC void convert_page(struct inode *, struct page *, + page_buf_bmap_t *, void *, int, int); +void +linvfs_unwritten_done( + struct buffer_head *bh, + int uptodate) +{ + page_buf_t *pb = (page_buf_t *)bh->b_private; + + ASSERT(buffer_unwritten(bh)); + bh->b_end_io = NULL; + clear_buffer_unwritten(bh); + if (!uptodate) + pagebuf_ioerror(pb, -EIO); + if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) + pagebuf_iodone(pb, 1, 1); + end_buffer_async_write(bh, uptodate); +} + +/* + * Issue transactions to convert a buffer range from unwritten + * to written extents. + */ +STATIC void +xfs_unwritten_conv( + xfs_buf_t *bp) +{ + bhv_desc_t *bdp = XFS_BUF_FSPRIVATE(bp, bhv_desc_t *); + xfs_mount_t *mp; + xfs_inode_t *ip; + + ip = XFS_BHVTOI(bdp); + mp = ip->i_mount; + + if (XFS_TEST_ERROR(XFS_BUF_GETERROR(bp), mp, + XFS_ERRTAG_STRATCMPL_IOERR, + XFS_RANDOM_STRATCMPL_IOERR)) { + xfs_ioerror_alert(__FUNCTION__, mp, bp, XFS_BUF_ADDR(bp)); + } + + XFS_IOMAP_WRITE_UNWRITTEN(mp, &ip->i_iocore, + XFS_BUF_OFFSET(bp), XFS_BUF_SIZE(bp)); + XFS_BUF_SET_FSPRIVATE(bp, NULL); + XFS_BUF_CLR_IODONE_FUNC(bp); + xfs_biodone(bp); +} STATIC int map_blocks( @@ -128,6 +172,58 @@ } /* + * Look for a page at index which is unlocked and contains our + * unwritten extent flagged buffers at its head. Returns page + * locked and with an extra reference count, and length of the + * unwritten extent component on this page that we can write, + * in units of filesystem blocks. + */ +STATIC struct page * +probe_unwritten_page( + struct address_space *mapping, + unsigned long index, + page_buf_bmap_t *mp, + page_buf_t *pb, + unsigned long max_offset, + unsigned long *fsbs) +{ + struct page *page; + + page = find_trylock_page(mapping, index); + if (!page) + return 0; + if (PageWriteback(page)) + goto out; + + if (page->mapping && page_has_buffers(page)) { + struct buffer_head *bh, *head; + unsigned long p_offset = 0; + + *fsbs = 0; + bh = head = page_buffers(page); + do { + if (!buffer_unwritten(bh)) + break; + if (!match_offset_to_mapping(page, mp, p_offset)) + break; + if (p_offset >= max_offset) + break; + set_buffer_unwritten_io(bh); + bh->b_private = pb; + p_offset += bh->b_size; + (*fsbs)++; + } while ((bh = bh->b_this_page) != head); + + if (p_offset) + return page; + } + +out: + unlock_page(page); + return NULL; +} + +/* * Look for a page at index which is unlocked and not mapped * yet - clustering for mmap write case. */ @@ -149,6 +245,7 @@ if (page->mapping && PageDirty(page)) { if (page_has_buffers(page)) { struct buffer_head *bh, *head; + bh = head = page_buffers(page); do { if (buffer_mapped(bh) || !buffer_uptodate(bh)) @@ -189,6 +286,8 @@ */ if (bh == head) { tlast = inode->i_size >> PAGE_CACHE_SHIFT; + /* Prune this back to avoid pathological behavior */ + tlast = min(tlast, startpage->index + 64); for (tindex = startpage->index + 1; tindex < tlast; tindex++) { len = probe_unmapped_page(mapping, tindex, PAGE_CACHE_SIZE); @@ -206,11 +305,12 @@ } /* - * Probe for a given page (index) in the inode & test if it is delayed. - * Returns page locked and with an extra reference count. + * Probe for a given page (index) in the inode and test if it is delayed + * and without unwritten buffers. Returns page locked and with an extra + * reference count. */ STATIC struct page * -probe_page( +probe_delalloc_page( struct inode *inode, unsigned long index) { @@ -224,12 +324,20 @@ if (page->mapping && page_has_buffers(page)) { struct buffer_head *bh, *head; + int acceptable = 0; bh = head = page_buffers(page); do { - if (buffer_delay(bh)) - return page; + if (buffer_unwritten(bh)) { + acceptable = 0; + break; + } else if (buffer_delay(bh)) { + acceptable = 1; + } } while ((bh = bh->b_this_page) != head); + + if (acceptable) + return page; } out: @@ -237,6 +345,103 @@ return NULL; } +STATIC int +map_unwritten( + struct inode *inode, + struct page *start_page, + struct buffer_head *head, + struct buffer_head *curr, + unsigned long p_offset, + int block_bits, + page_buf_bmap_t *mp, + int all_bh) +{ + struct buffer_head *bh = curr; + page_buf_bmap_t *tmp; + page_buf_t *pb; + loff_t offset, size; + unsigned long nblocks = 0; + + offset = start_page->index; + offset <<= PAGE_CACHE_SHIFT; + offset += p_offset; + + pb = pagebuf_lookup(mp->pbm_target, + mp->pbm_offset, mp->pbm_bsize, _PBF_LOCKABLE); + if (!pb) + return -ENOMEM; + + /* Set the count to 1 initially, this will stop an I/O + * completion callout which happens before we have started + * all the I/O from calling pagebuf_iodone too early. + */ + atomic_set(&pb->pb_io_remaining, 1); + + /* First map forwards in the page consecutive buffers + * covering this unwritten extent + */ + do { + if (!buffer_unwritten(bh)) + break; + tmp = match_offset_to_mapping(start_page, mp, p_offset); + if (!tmp) + break; + BUG_ON(!(tmp->pbm_flags & PBMF_UNWRITTEN)); + map_buffer_at_offset(start_page, bh, p_offset, block_bits, mp); + set_buffer_unwritten_io(bh); + bh->b_private = pb; + p_offset += bh->b_size; + nblocks++; + } while ((bh = bh->b_this_page) != head); + + atomic_add(nblocks, &pb->pb_io_remaining); + + /* If we reached the end of the page, map forwards in any + * following pages which are also covered by this extent. + */ + if (bh == head) { + struct address_space *mapping = inode->i_mapping; + unsigned long tindex, tlast, bs; + struct page *page; + + tlast = inode->i_size >> PAGE_CACHE_SHIFT; + tlast = min(tlast, start_page->index + pb->pb_page_count - 1); + for (tindex = start_page->index + 1; tindex < tlast; tindex++) { + page = probe_unwritten_page(mapping, tindex, mp, pb, + PAGE_CACHE_SIZE, &bs); + if (!page) + break; + nblocks += bs; + atomic_add(bs, &pb->pb_io_remaining); + convert_page(inode, page, mp, pb, 1, all_bh); + } + + if ((tindex == tlast) && (inode->i_size & ~PAGE_CACHE_MASK)) { + page = probe_unwritten_page(mapping, tindex, mp, pb, + inode->i_size & ~PAGE_CACHE_MASK, &bs); + if (page) { + nblocks += bs; + atomic_add(bs, &pb->pb_io_remaining); + convert_page(inode, page, + mp, pb, 1, all_bh); + } + } + } + + size = nblocks; /* NB: using 64bit number here */ + size <<= block_bits; /* convert fsb's to byte range */ + + XFS_BUF_SET_SIZE(pb, size); + XFS_BUF_SET_OFFSET(pb, offset); + XFS_BUF_SET_FSPRIVATE(pb, LINVFS_GET_VP(inode)->v_fbhv); + XFS_BUF_SET_IODONE_FUNC(pb, xfs_unwritten_conv); + + if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) + pagebuf_iodone(pb, 1, 1); + + return 0; +} + STATIC void submit_page( struct page *page, @@ -255,6 +460,8 @@ for (i = 0; i < cnt; i++) { bh = bh_arr[i]; mark_buffer_async_write(bh); + if (buffer_unwritten(bh)) + set_buffer_unwritten_io(bh); set_buffer_uptodate(bh); clear_buffer_dirty(bh); } @@ -268,14 +475,15 @@ /* * Allocate & map buffers for page given the extent map. Write it out. * except for the original page of a writepage, this is called on - * delalloc pages only, for the original page it is possible that - * the page has no mapping at all. + * delalloc/unwritten pages only, for the original page it is possible + * that the page has no mapping at all. */ STATIC void convert_page( struct inode *inode, struct page *page, page_buf_bmap_t *maps, + void *private, int startio, int all_bh) { @@ -308,7 +516,23 @@ continue; ASSERT(!(tmp->pbm_flags & PBMF_HOLE)); ASSERT(!(tmp->pbm_flags & PBMF_DELAY)); - map_buffer_at_offset(page, bh, offset, bbits, tmp); + + /* If this is a new unwritten extent buffer (i.e. one + * that we haven't passed in private data for, we must + * now map this buffer too. + */ + if (buffer_unwritten(bh) && !bh->b_end_io) { + ASSERT(tmp->pbm_flags & PBMF_UNWRITTEN); + map_unwritten(inode, page, head, bh, + offset, bbits, tmp, all_bh); + } else { + map_buffer_at_offset(page, bh, offset, bbits, tmp); + if (buffer_unwritten(bh)) { + set_buffer_unwritten_io(bh); + bh->b_private = private; + ASSERT(private); + } + } if (startio && (offset < end)) { bh_arr[index++] = bh; } else { @@ -341,10 +565,10 @@ tlast = (mp->pbm_offset + mp->pbm_bsize) >> PAGE_CACHE_SHIFT; for (; tindex < tlast; tindex++) { - page = probe_page(inode, tindex); + page = probe_delalloc_page(inode, tindex); if (!page) break; - convert_page(inode, page, mp, startio, all_bh); + convert_page(inode, page, mp, NULL, startio, all_bh); } } @@ -368,7 +592,7 @@ */ STATIC int -delalloc_convert( +page_state_convert( struct page *page, int startio, int unmapped) /* also implies page uptodate */ @@ -411,10 +635,42 @@ } /* - * First case, allocate space for delalloc buffer head - * we can return EAGAIN here in the release page case. + * First case, map an unwritten extent and prepare for + * extent state conversion transaction on completion. */ - if (buffer_delay(bh)) { + if (buffer_unwritten(bh)) { + if (!mp) { + err = map_blocks(inode, offset, len, &map, + PBF_FILE_UNWRITTEN); + if (err) { + goto error; + } + mp = match_offset_to_mapping(page, &map, + p_offset); + } + if (mp) { + if (!bh->b_end_io) { + err = map_unwritten(inode, page, + head, bh, p_offset, + inode->i_blkbits, + mp, unmapped); + if (err) { + goto error; + } + } + if (startio) { + bh_arr[cnt++] = bh; + } else { + set_buffer_dirty(bh); + unlock_buffer(bh); + } + page_dirty = 0; + } + /* + * Second case, allocate space for a delalloc buffer. + * We can return EAGAIN here in the release page case. + */ + } else if (buffer_delay(bh)) { if (!mp) { err = map_blocks(inode, offset, len, &map, PBF_FILE_ALLOCATE | flags); @@ -574,6 +830,12 @@ bh_result->b_bdev = pbmap.pbm_target->pbr_bdev; set_buffer_mapped(bh_result); } + if (pbmap.pbm_flags & PBMF_UNWRITTEN) { + if (create) + set_buffer_mapped(bh_result); + set_buffer_unwritten(bh_result); + set_buffer_delay(bh_result); + } } /* If we previously allocated a block out beyond eof and @@ -695,21 +957,23 @@ return mpage_readpages(mapping, pages, nr_pages, linvfs_get_block); } - STATIC void count_page_state( struct page *page, int *delalloc, - int *unmapped) + int *unmapped, + int *unwritten) { struct buffer_head *bh, *head; - *delalloc = *unmapped = 0; + *delalloc = *unmapped = *unwritten = 0; bh = head = page_buffers(page); do { if (buffer_uptodate(bh) && !buffer_mapped(bh)) (*unmapped) = 1; + else if (buffer_unwritten(bh)) + (*unwritten) = 1; else if (buffer_delay(bh)) (*delalloc) = 1; } while ((bh = bh->b_this_page) != head); @@ -736,6 +1000,7 @@ * is off, we need to fail the writepage and redirty the page. * We also need to set PF_NOIO ourselves. */ + STATIC int linvfs_writepage( struct page *page, @@ -743,7 +1008,7 @@ { int error; int need_trans; - int delalloc, unmapped; + int delalloc, unmapped, unwritten; struct inode *inode = page->mapping->host; /* @@ -751,15 +1016,16 @@ * 1. There are delalloc buffers on the page * 2. The page is upto date and we have unmapped buffers * 3. The page is upto date and we have no buffers + * 4. There are unwritten buffers on the page */ if (!page_has_buffers(page)) { unmapped = 1; need_trans = 1; } else { - count_page_state(page, &delalloc, &unmapped); + count_page_state(page, &delalloc, &unmapped, &unwritten); if (!PageUptodate(page)) unmapped = 0; - need_trans = delalloc + unmapped; + need_trans = delalloc + unmapped + unwritten; } /* @@ -775,15 +1041,14 @@ * Delay hooking up buffer heads until we have * made our go/no-go decision. */ - if (!page_has_buffers(page)) { + if (!page_has_buffers(page)) create_empty_buffers(page, 1 << inode->i_blkbits, 0); - } /* - * Convert delalloc or unmapped space to real space and flush out - * to disk. + * Convert delayed allocate, unwritten or unmapped space + * to real space and flush out to disk. */ - error = delalloc_convert(page, 1, unmapped); + error = page_state_convert(page, 1, unmapped); if (error == -EAGAIN) goto out_fail; if (unlikely(error < 0)) @@ -824,10 +1089,10 @@ struct page *page, int gfp_mask) { - int delalloc, unmapped; + int delalloc, unmapped, unwritten; - count_page_state(page, &delalloc, &unmapped); - if (!delalloc) + count_page_state(page, &delalloc, &unmapped, &unwritten); + if (!delalloc && !unwritten) goto free_buffers; if (!(gfp_mask & __GFP_FS)) @@ -839,7 +1104,7 @@ * Never need to allocate space here - we will always * come back to writepage in that case. */ - if (delalloc_convert(page, 0, 0) == 0) + if (page_state_convert(page, 0, 0) == 0) goto free_buffers; return 0; diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_behavior.c linux-2.5.65-bk3/fs/xfs/linux/xfs_behavior.c --- linux-2.5.65-bk2/fs/xfs/linux/xfs_behavior.c Mon Mar 17 13:44:46 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_behavior.c Mon Mar 31 12:41:44 2003 @@ -121,9 +121,7 @@ { bhv_desc_t *bdp; - BHV_READ_LOCK(bhp); bdp = bhv_lookup(bhp, ops); - BHV_READ_UNLOCK(bhp); return bdp; } @@ -140,18 +138,12 @@ { bhv_desc_t *curdesc; - BHV_READ_LOCK(bhp); for (curdesc = bhp->bh_first; curdesc != NULL; curdesc = curdesc->bd_next) { - - if (curdesc->bd_next == NULL) { - BHV_READ_UNLOCK(bhp); + if (curdesc->bd_next == NULL) return curdesc; - } } - - BHV_READ_UNLOCK(bhp); return NULL; } diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_behavior.h linux-2.5.65-bk3/fs/xfs/linux/xfs_behavior.h --- linux-2.5.65-bk2/fs/xfs/linux/xfs_behavior.h Mon Mar 17 13:44:08 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_behavior.h Mon Mar 31 12:41:44 2003 @@ -152,13 +152,6 @@ #define BHV_IDENTITY(bdp) ((bhv_identity_t *)(bdp)->bd_ops) #define BHV_POSITION(bdp) (BHV_IDENTITY(bdp)->bi_position) - -#define BHV_READ_LOCK(bhp) -#define BHV_READ_UNLOCK(bhp) -#define BHV_NOT_READ_LOCKED(bhp) 1 -#define BHV_IS_WRITE_LOCKED(bhp) 1 -#define BHV_NOT_WRITE_LOCKED(bhp) 1 - extern void bhv_head_init(bhv_head_t *, char *); extern void bhv_head_destroy(bhv_head_t *); extern void bhv_head_reinit(bhv_head_t *); @@ -180,8 +173,6 @@ (bdp)->bd_next = NULL; \ } -#define BHV_DESC_INIT(so,A,B) bhv_desc_init(&(so->so_bhv),so,A,B) - /* * Remove a behavior descriptor from a behavior chain. */ diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_file.c linux-2.5.65-bk3/fs/xfs/linux/xfs_file.c --- linux-2.5.65-bk2/fs/xfs/linux/xfs_file.c Mon Mar 17 13:44:07 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_file.c Mon Mar 31 12:41:44 2003 @@ -32,8 +32,6 @@ #include #include -#include -#include #include /* for PROT_WRITE */ static struct vm_operations_struct linvfs_file_vm_ops; @@ -227,8 +225,8 @@ int eof = 0; caddr_t read_buf; int namelen, size = 0; - size_t rlen = PAGE_CACHE_SIZE << 2; - xfs_off_t start_offset; + size_t rlen = PAGE_CACHE_SIZE; + xfs_off_t start_offset, curr_offset; xfs_dirent_t *dbp = NULL; vp = LINVFS_GET_VP(filp->f_dentry->d_inode); @@ -247,7 +245,7 @@ uio.uio_iov = &iov; uio.uio_fmode = filp->f_mode; uio.uio_segflg = UIO_SYSSPACE; - uio.uio_offset = filp->f_pos; + curr_offset = uio.uio_offset = filp->f_pos; while (!eof) { uio.uio_resid = iov.iov_len = rlen; @@ -268,21 +266,22 @@ namelen = strlen(dbp->d_name); if (filldir(dirent, dbp->d_name, namelen, - (loff_t) dbp->d_off, + (loff_t) curr_offset, (ino_t) dbp->d_ino, DT_UNKNOWN)) { goto done; } size -= dbp->d_reclen; + curr_offset = (loff_t)dbp->d_off & 0x7fffffff; dbp = nextdp(dbp); } } done: if (!error) { if (size == 0) - filp->f_pos = uio.uio_offset; + filp->f_pos = uio.uio_offset & 0x7fffffff; else if (dbp) - filp->f_pos = dbp->d_off; + filp->f_pos = curr_offset; } kfree(read_buf); @@ -308,7 +307,6 @@ vma->vm_ops = &linvfs_file_vm_ops; VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error); - UPDATE_ATIME(ip); return 0; } diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_fs_subr.c linux-2.5.65-bk3/fs/xfs/linux/xfs_fs_subr.c --- linux-2.5.65-bk2/fs/xfs/linux/xfs_fs_subr.c Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_fs_subr.c Mon Mar 31 12:41:44 2003 @@ -33,48 +33,6 @@ #include /* - * Implementation for VFS_DOUNMOUNT. - */ -int -fs_dounmount( - bhv_desc_t *bdp, - int flags, - vnode_t *rootvp, - cred_t *cr) -{ - struct vfs *vfsp = bhvtovfs(bdp); - bhv_desc_t *fbdp = vfsp->vfs_fbhv; - int error; - - /* - * Wait for sync to finish and lock vfsp. This also sets the - * VFS_OFFLINE flag. Once we do this we can give up reference - * the root vnode which we hold to avoid the another unmount - * ripping the vfs out from under us before we get to lock it. - * The VFS_DOUNMOUNT calling convention is that the reference - * on the rot vnode is released whether the call succeeds or - * fails. - */ - if (rootvp) - VN_RELE(rootvp); - - /* - * Now invoke SYNC and UNMOUNT ops, using the PVFS versions is - * OK since we already have a behavior lock as a result of - * being in VFS_DOUNMOUNT. It is necessary to do things this - * way since using the VFS versions would cause us to get the - * behavior lock twice which can cause deadlock as well as - * making the coding of vfs relocation unnecessarilty difficult - * by making relocations invoked by unmount occur in a different - * environment than those invoked by mount-update. - */ - PVFS_SYNC(fbdp, SYNC_ATTR|SYNC_DELWRI, cr, error); - if (error == 0) - PVFS_UNMOUNT(fbdp, flags, cr, error); - return error; -} - -/* * Stub for no-op vnode operations that return error status. */ int diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_fs_subr.h linux-2.5.65-bk3/fs/xfs/linux/xfs_fs_subr.h --- linux-2.5.65-bk2/fs/xfs/linux/xfs_fs_subr.h Mon Mar 17 13:44:19 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_fs_subr.h Mon Mar 31 12:41:44 2003 @@ -42,7 +42,6 @@ extern int fs_nosys(void); extern int fs_nodev(void); extern void fs_noval(void); -extern int fs_dounmount(bhv_desc_t *, int, vnode_t *, struct cred *); extern void fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int); extern void fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int); extern int fs_flush_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, uint64_t, int); diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_globals.c linux-2.5.65-bk3/fs/xfs/linux/xfs_globals.c --- linux-2.5.65-bk2/fs/xfs/linux/xfs_globals.c Mon Mar 17 13:44:14 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_globals.c Mon Mar 31 12:41:44 2003 @@ -46,7 +46,7 @@ * Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n, * other XFS code uses these values. */ -xfs_param_t xfs_params = { 0, 1, 0, 0, 0 }; +xfs_param_t xfs_params = { 0, 1, 0, 0, 0, 3 }; /* * Used to serialize atomicIncWithWrap. diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_ioctl.c linux-2.5.65-bk3/fs/xfs/linux/xfs_ioctl.c --- linux-2.5.65-bk2/fs/xfs/linux/xfs_ioctl.c Mon Mar 17 13:44:38 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_ioctl.c Mon Mar 31 12:41:44 2003 @@ -130,7 +130,6 @@ int lock_mode; /* need to get access to the xfs_inode to read the generation */ - VN_BHV_READ_LOCK(&(vp)->v_bh); bhv = VNODE_TO_FIRST_BHV(vp); ASSERT(bhv); ip = XFS_BHVTOI(bhv); @@ -145,7 +144,6 @@ handle.ha_fid.xfs_fid_ino = ip->i_ino; xfs_iunlock_map_shared(ip, lock_mode); - VN_BHV_READ_UNLOCK(&(vp)->v_bh); hsize = XFS_HSIZE(handle); } @@ -585,6 +583,14 @@ case XFS_IOC_FREESP64: case XFS_IOC_RESVSP64: case XFS_IOC_UNRESVSP64: + /* + * Only allow the sys admin to reserve space unless + * unwritten extents are enabled. + */ + if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) && + !capable(CAP_SYS_ADMIN)) + return -EPERM; + return xfs_ioc_space(bdp, vp, filp, cmd, arg); case XFS_IOC_DIOINFO: { @@ -685,11 +691,7 @@ xfs_fsop_resblks_t inout; __uint64_t in; - /* Only allow the sys admin to reserve space unless - * unwritten extents are enabled. - */ - if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) && - !capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (copy_from_user(&inout, (char *)arg, sizeof(inout))) @@ -810,9 +812,6 @@ int attr_flags = 0; int error; - if (!capable(CAP_SYS_ADMIN)) - return -XFS_ERROR(EPERM); - if (filp->f_flags & O_RDONLY) return -XFS_ERROR(EBADF); @@ -847,10 +846,7 @@ /* done = 1 if there are more stats to get and if bulkstat */ /* should be called again (unused here, but used in dmapi) */ - /* Do not allow space reservation if this is not the admin and - * unwritten extents are turned off. - */ - if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) && !capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (XFS_FORCED_SHUTDOWN(mp)) diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_iomap.c linux-2.5.65-bk3/fs/xfs/linux/xfs_iomap.c --- linux-2.5.65-bk2/fs/xfs/linux/xfs_iomap.c Mon Mar 17 13:44:06 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_iomap.c Mon Mar 31 12:41:45 2003 @@ -530,6 +530,7 @@ xfs_trans_t *tp; int i, nimaps, committed; int error = 0; + int nres; *retmap = 0; @@ -562,9 +563,19 @@ nimaps = 0; while (nimaps == 0) { tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); - error = xfs_trans_reserve(tp, 0, XFS_WRITE_LOG_RES(mp), + nres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); + error = xfs_trans_reserve(tp, nres, + XFS_WRITE_LOG_RES(mp), 0, XFS_TRANS_PERM_LOG_RES, XFS_WRITE_LOG_COUNT); + + if (error == ENOSPC) { + error = xfs_trans_reserve(tp, 0, + XFS_WRITE_LOG_RES(mp), + 0, + XFS_TRANS_PERM_LOG_RES, + XFS_WRITE_LOG_COUNT); + } if (error) { xfs_trans_cancel(tp, 0); return XFS_ERROR(error); diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_iops.c linux-2.5.65-bk3/fs/xfs/linux/xfs_iops.c --- linux-2.5.65-bk2/fs/xfs/linux/xfs_iops.c Mon Mar 17 13:44:02 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_iops.c Mon Mar 31 12:41:45 2003 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -45,7 +45,7 @@ vattr_t va; int error; - va.va_mask = XFS_AT_NLINK|XFS_AT_SIZE; + va.va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; VOP_GETATTR(vp, &va, ATTR_LAZY, NULL, error); ip->i_nlink = va.va_nlink; ip->i_size = va.va_size; @@ -154,20 +154,18 @@ return linvfs_mknod(dir, dentry, mode|S_IFDIR, 0); } - STATIC struct dentry * linvfs_lookup( struct inode *dir, struct dentry *dentry) { - int error; - vnode_t *vp, *cvp; struct inode *ip = NULL; + vnode_t *vp, *cvp = NULL; + int error; if (dentry->d_name.len >= MAXNAMELEN) return ERR_PTR(-ENAMETOOLONG); - cvp = NULL; vp = LINVFS_GET_VP(dir); VOP_LOOKUP(vp, dentry, &cvp, 0, NULL, NULL, error); if (!error) { @@ -189,10 +187,10 @@ struct inode *dir, struct dentry *dentry) { - int error; - vnode_t *tdvp; /* Target directory for new name/link */ - vnode_t *vp; /* vp of name being linked */ struct inode *ip; /* inode of guy being linked to */ + vnode_t *tdvp; /* target directory for new name/link */ + vnode_t *vp; /* vp of name being linked */ + int error; ip = old_dentry->d_inode; /* inode being linked to */ if (S_ISDIR(ip->i_mode)) @@ -201,7 +199,6 @@ tdvp = LINVFS_GET_VP(dir); vp = LINVFS_GET_VP(ip); - error = 0; VOP_LINK(tdvp, vp, dentry, NULL, error); if (!error) { VMODIFY(tdvp); @@ -218,16 +215,14 @@ struct inode *dir, struct dentry *dentry) { - int error = 0; struct inode *inode; vnode_t *dvp; /* directory containing name to remove */ + int error; inode = dentry->d_inode; - dvp = LINVFS_GET_VP(dir); VOP_REMOVE(dvp, dentry, NULL, error); - if (!error) { validate_fields(dir); /* For size only */ validate_fields(inode); @@ -244,13 +239,14 @@ struct dentry *dentry, const char *symname) { - int error; + struct inode *ip; + vattr_t va; vnode_t *dvp; /* directory containing name to remove */ vnode_t *cvp; /* used to lookup symlink to put in dentry */ - vattr_t va; - struct inode *ip = NULL; + int error; dvp = LINVFS_GET_VP(dir); + cvp = NULL; memset(&va, 0, sizeof(va)); va.va_type = VLNK; @@ -259,20 +255,14 @@ error = 0; VOP_SYMLINK(dvp, dentry, &va, (char *)symname, &cvp, NULL, error); - if (!error) { - ASSERT(cvp); + if (!error && cvp) { ASSERT(cvp->v_type == VLNK); ip = LINVFS_GET_IP(cvp); - if (!ip) { - error = ENOMEM; - VN_RELE(cvp); - } else { - d_instantiate(dentry, ip); - validate_fields(dir); - validate_fields(ip); /* size needs update */ - mark_inode_dirty_sync(ip); - mark_inode_dirty_sync(dir); - } + d_instantiate(dentry, ip); + validate_fields(dir); + validate_fields(ip); /* size needs update */ + mark_inode_dirty_sync(ip); + mark_inode_dirty_sync(dir); } return -error; } @@ -303,23 +293,20 @@ struct inode *ndir, struct dentry *ndentry) { - int error; + struct inode *new_inode = ndentry->d_inode; vnode_t *fvp; /* from directory */ vnode_t *tvp; /* target directory */ - struct inode *new_inode = NULL; + int error; fvp = LINVFS_GET_VP(odir); tvp = LINVFS_GET_VP(ndir); - new_inode = ndentry->d_inode; - VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error); if (error) return -error; - if (new_inode) { + if (new_inode) validate_fields(new_inode); - } validate_fields(odir); if (ndir != odir) @@ -334,13 +321,11 @@ char *buf, int size) { - vnode_t *vp; + vnode_t *vp = LINVFS_GET_VP(dentry->d_inode); uio_t uio; iovec_t iov; int error; - vp = LINVFS_GET_VP(dentry->d_inode); - iov.iov_base = buf; iov.iov_len = size; @@ -348,6 +333,7 @@ uio.uio_offset = 0; uio.uio_segflg = UIO_USERSPACE; uio.uio_resid = size; + uio.uio_iovcnt = 1; VOP_READLINK(vp, &uio, NULL, error); if (error) @@ -395,6 +381,7 @@ uio->uio_segflg = UIO_SYSSPACE; uio->uio_resid = MAXNAMELEN; uio->uio_fmode = 0; + uio->uio_iovcnt = 1; VOP_READLINK(vp, uio, NULL, error); if (error) { @@ -425,11 +412,6 @@ return -error; } -/* Brute force approach for now - copy data into linux inode - * from the results of a getattr. This gets called out of things - * like stat. - */ - STATIC int linvfs_getattr( struct vfsmount *mnt, @@ -440,9 +422,8 @@ vnode_t *vp = LINVFS_GET_VP(inode); int error = 0; - if (unlikely(vp->v_flag & VMODIFIED)) { + if (unlikely(vp->v_flag & VMODIFIED)) error = vn_revalidate(vp); - } if (!error) generic_fillattr(inode, stat); return 0; @@ -454,11 +435,11 @@ struct iattr *attr) { struct inode *inode = dentry->d_inode; + unsigned int ia_valid = attr->ia_valid; vnode_t *vp = LINVFS_GET_VP(inode); vattr_t vattr; - unsigned int ia_valid = attr->ia_valid; - int error; int flags = 0; + int error; memset(&vattr, 0, sizeof(vattr_t)); if (ia_valid & ATTR_UID) { @@ -511,7 +492,7 @@ STATIC void linvfs_truncate( - struct inode *inode) + struct inode *inode) { block_truncate_page(inode->i_mapping, inode->i_size, linvfs_get_block); } @@ -579,11 +560,11 @@ size_t size, int flags) { - int error; - int xflags = 0; - char *p = (char *)name; struct inode *inode = dentry->d_inode; vnode_t *vp = LINVFS_GET_VP(inode); + char *p = (char *)name; + int xflags = 0; + int error; if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name, xfs_namespaces[SYSTEM_NAMES].namelen) == 0) { @@ -592,20 +573,16 @@ return error; error = -EOPNOTSUPP; p += xfs_namespaces[SYSTEM_NAMES].namelen; - if (strcmp(p, POSIXACL_ACCESS) == 0) { + if (strcmp(p, POSIXACL_ACCESS) == 0) error = xfs_acl_vset(vp, (void *) data, size, _ACL_TYPE_ACCESS); - } - else if (strcmp(p, POSIXACL_DEFAULT) == 0) { + else if (strcmp(p, POSIXACL_DEFAULT) == 0) error = xfs_acl_vset(vp, (void *) data, size, _ACL_TYPE_DEFAULT); - } - else if (strcmp(p, POSIXCAP) == 0) { + else if (strcmp(p, POSIXCAP) == 0) error = xfs_cap_vset(vp, (void *) data, size); - } - if (!error) { + if (!error) error = vn_revalidate(vp); - } return error; } @@ -642,25 +619,22 @@ void *data, size_t size) { - ssize_t error; - int xflags = 0; - char *p = (char *)name; struct inode *inode = dentry->d_inode; vnode_t *vp = LINVFS_GET_VP(inode); + char *p = (char *)name; + int xflags = 0; + ssize_t error; if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name, xfs_namespaces[SYSTEM_NAMES].namelen) == 0) { error = -EOPNOTSUPP; p += xfs_namespaces[SYSTEM_NAMES].namelen; - if (strcmp(p, POSIXACL_ACCESS) == 0) { + if (strcmp(p, POSIXACL_ACCESS) == 0) error = xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS); - } - else if (strcmp(p, POSIXACL_DEFAULT) == 0) { + else if (strcmp(p, POSIXACL_DEFAULT) == 0) error = xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT); - } - else if (strcmp(p, POSIXCAP) == 0) { + else if (strcmp(p, POSIXCAP) == 0) error = xfs_cap_vget(vp, data, size); - } return error; } @@ -699,15 +673,13 @@ char *data, size_t size) { - ssize_t error; - int result = 0; - int xflags = ATTR_KERNAMELS; - char *k = data; attrlist_cursor_kern_t cursor; xattr_namespace_t *sys; - vnode_t *vp; - - vp = LINVFS_GET_VP(dentry->d_inode); + vnode_t *vp = LINVFS_GET_VP(dentry->d_inode); + char *k = data; + int xflags = ATTR_KERNAMELS; + int result = 0; + ssize_t error; if (!size) xflags |= ATTR_KERNOVAL; @@ -743,11 +715,11 @@ struct dentry *dentry, const char *name) { - int error; - int xflags = 0; - char *p = (char *)name; struct inode *inode = dentry->d_inode; vnode_t *vp = LINVFS_GET_VP(inode); + char *p = (char *)name; + int xflags = 0; + int error; if (strncmp(name, xfs_namespaces[SYSTEM_NAMES].name, xfs_namespaces[SYSTEM_NAMES].namelen) == 0) { @@ -786,8 +758,8 @@ struct inode_operations linvfs_file_inode_operations = { .permission = linvfs_permission, - .getattr = linvfs_getattr, .truncate = linvfs_truncate, + .getattr = linvfs_getattr, .setattr = linvfs_setattr, .setxattr = linvfs_setxattr, .getxattr = linvfs_getxattr, diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_iops.h linux-2.5.65-bk3/fs/xfs/linux/xfs_iops.h --- linux-2.5.65-bk2/fs/xfs/linux/xfs_iops.h Mon Mar 17 13:44:07 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_iops.h Mon Mar 31 12:41:45 2003 @@ -66,5 +66,6 @@ extern struct address_space_operations linvfs_aops; extern int linvfs_get_block(struct inode *, sector_t, struct buffer_head *, int); +extern void linvfs_unwritten_done(struct buffer_head *, int); #endif /* __XFS_IOPS_H__ */ diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_linux.h linux-2.5.65-bk3/fs/xfs/linux/xfs_linux.h --- linux-2.5.65-bk2/fs/xfs/linux/xfs_linux.h Mon Mar 17 13:43:37 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_linux.h Mon Mar 31 12:41:45 2003 @@ -69,22 +69,25 @@ #define STATIC static #endif +/* + * State flag for unwritten extent buffers. + * + * We need to be able to distinguish between these and delayed + * allocate buffers within XFS. The generic IO path code does + * not need to distinguish - we use the BH_Delay flag for both + * delalloc and these ondisk-uninitialised buffers. + */ +BUFFER_FNS(PrivateStart, unwritten); +static inline void set_buffer_unwritten_io(struct buffer_head *bh) +{ + bh->b_end_io = linvfs_unwritten_done; +} + #define restricted_chown xfs_params.restrict_chown #define irix_sgid_inherit xfs_params.sgid_inherit #define irix_symlink_mode xfs_params.symlink_mode #define xfs_panic_mask xfs_params.panic_mask - -typedef struct xfs_dirent { /* data from readdir() */ - xfs_ino_t d_ino; /* inode number of entry */ - xfs_off_t d_off; /* offset of disk directory entry */ - unsigned short d_reclen; /* length of this record */ - char d_name[1]; /* name of file */ -} xfs_dirent_t; - -#define DIRENTBASESIZE (((xfs_dirent_t *)0)->d_name - (char *)0) -#define DIRENTSIZE(namelen) \ - ((DIRENTBASESIZE + (namelen) + \ - sizeof(xfs_off_t)) & ~(sizeof(xfs_off_t) - 1)) +#define xfs_error_level xfs_params.error_level #define NBPP PAGE_SIZE #define DPPSHFT (PAGE_SHIFT - 9) diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_lrw.c linux-2.5.65-bk3/fs/xfs/linux/xfs_lrw.c --- linux-2.5.65-bk2/fs/xfs/linux/xfs_lrw.c Mon Mar 17 13:43:37 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_lrw.c Mon Mar 31 12:41:45 2003 @@ -35,7 +35,6 @@ */ #include -#include #include diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_lrw.h linux-2.5.65-bk3/fs/xfs/linux/xfs_lrw.h --- linux-2.5.65-bk2/fs/xfs/linux/xfs_lrw.h Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_lrw.h Mon Mar 31 12:41:45 2003 @@ -47,36 +47,36 @@ */ #define XFS_MAX_RW_NBMAPS 4 -extern int xfs_bmap (struct bhv_desc *, xfs_off_t, ssize_t, int, +extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int, struct page_buf_bmap_s *, int *); -extern int xfsbdstrat (struct xfs_mount *, struct page_buf_s *); -extern int xfs_bdstrat_cb (struct page_buf_s *); +extern int xfsbdstrat(struct xfs_mount *, struct page_buf_s *); +extern int xfs_bdstrat_cb(struct page_buf_s *); -extern int xfs_zero_eof (struct vnode *, struct xfs_iocore *, xfs_off_t, +extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t, xfs_fsize_t, xfs_fsize_t); -extern ssize_t xfs_read (struct bhv_desc *, struct file *, +extern ssize_t xfs_read(struct bhv_desc *, struct file *, const struct iovec *, unsigned long, loff_t *, struct cred *); -extern ssize_t xfs_write (struct bhv_desc *, struct file *, +extern ssize_t xfs_write(struct bhv_desc *, struct file *, const struct iovec *, unsigned long, loff_t *, struct cred *); -extern ssize_t xfs_sendfile (struct bhv_desc *, struct file *, +extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *, loff_t *, size_t, read_actor_t, void *, struct cred *); -extern int xfs_iomap (struct xfs_iocore *, xfs_off_t, ssize_t, int, +extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int, struct page_buf_bmap_s *, int *); -extern int xfs_iomap_write_direct (struct xfs_inode *, loff_t, size_t, +extern int xfs_iomap_write_direct(struct xfs_inode *, loff_t, size_t, int, struct xfs_bmbt_irec *, int *, int); -extern int xfs_iomap_write_delay (struct xfs_inode *, loff_t, size_t, +extern int xfs_iomap_write_delay(struct xfs_inode *, loff_t, size_t, int, struct xfs_bmbt_irec *, int *); -extern int xfs_iomap_write_allocate (struct xfs_inode *, +extern int xfs_iomap_write_allocate(struct xfs_inode *, struct xfs_bmbt_irec *, int *); -extern int xfs_iomap_write_unwritten (struct xfs_inode *, loff_t, size_t); +extern int xfs_iomap_write_unwritten(struct xfs_inode *, loff_t, size_t); -extern int xfs_dev_is_read_only (struct xfs_mount *, char *); +extern int xfs_dev_is_read_only(struct xfs_mount *, char *); -extern void XFS_log_write_unmount_ro (struct bhv_desc *); +extern void XFS_log_write_unmount_ro(struct bhv_desc *); #define XFS_FSB_TO_DB_IO(io,fsb) \ (((io)->io_flags & XFS_IOCORE_RT) ? \ diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_super.c linux-2.5.65-bk3/fs/xfs/linux/xfs_super.c --- linux-2.5.65-bk2/fs/xfs/linux/xfs_super.c Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_super.c Mon Mar 31 12:41:45 2003 @@ -766,7 +766,9 @@ vfs_t *vfsp = LINVFS_GET_VFS(sb); int error; - VFS_DOUNMOUNT(vfsp, 0, NULL, NULL, error); + VFS_SYNC(vfsp, SYNC_ATTR|SYNC_DELWRI, NULL, error); + if (error == 0) + VFS_UNMOUNT(vfsp, 0, NULL, error); if (error) { printk("XFS unmount got error %d\n", error); printk("%s: vfsp/0x%p left dangling!\n", __FUNCTION__, vfsp); diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_sysctl.c linux-2.5.65-bk3/fs/xfs/linux/xfs_sysctl.c --- linux-2.5.65-bk2/fs/xfs/linux/xfs_sysctl.c Mon Mar 17 13:44:51 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_sysctl.c Mon Mar 31 12:41:45 2003 @@ -35,8 +35,8 @@ #include -STATIC ulong xfs_min[XFS_PARAM] = { 0, 0, 0, 0, 0 }; -STATIC ulong xfs_max[XFS_PARAM] = { 1, 1, 1, 1, 127 }; +STATIC ulong xfs_min[XFS_PARAM] = { 0, 0, 0, 0, 0, 0 }; +STATIC ulong xfs_max[XFS_PARAM] = { 1, 1, 1, 1, 127, 3 }; static struct ctl_table_header *xfs_table_header; @@ -69,23 +69,27 @@ STATIC ctl_table xfs_table[] = { {XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear, sizeof(ulong), 0644, NULL, &xfs_stats_clear_proc_handler, - &sysctl_intvec, NULL, &xfs_min[2], &xfs_max[2]}, + &sysctl_intvec, NULL, &xfs_min[0], &xfs_max[0]}, {XFS_RESTRICT_CHOWN, "restrict_chown", &xfs_params.restrict_chown, sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax, - &sysctl_intvec, NULL, &xfs_min[3], &xfs_max[3]}, + &sysctl_intvec, NULL, &xfs_min[1], &xfs_max[1]}, {XFS_SGID_INHERIT, "irix_sgid_inherit", &xfs_params.sgid_inherit, sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax, - &sysctl_intvec, NULL, &xfs_min[4], &xfs_max[4]}, + &sysctl_intvec, NULL, &xfs_min[2], &xfs_max[2]}, {XFS_SYMLINK_MODE, "irix_symlink_mode", &xfs_params.symlink_mode, sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax, - &sysctl_intvec, NULL, &xfs_min[5], &xfs_max[5]}, + &sysctl_intvec, NULL, &xfs_min[3], &xfs_max[3]}, {XFS_PANIC_MASK, "panic_mask", &xfs_params.panic_mask, sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax, - &sysctl_intvec, NULL, &xfs_min[6], &xfs_max[6]}, + &sysctl_intvec, NULL, &xfs_min[4], &xfs_max[4]}, + + {XFS_ERRLEVEL, "error_level", &xfs_params.error_level, + sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax, + &sysctl_intvec, NULL, &xfs_min[5], &xfs_max[5]}, {0} }; diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_sysctl.h linux-2.5.65-bk3/fs/xfs/linux/xfs_sysctl.h --- linux-2.5.65-bk2/fs/xfs/linux/xfs_sysctl.h Mon Mar 17 13:43:37 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_sysctl.h Mon Mar 31 12:41:45 2003 @@ -48,14 +48,31 @@ /* not a member of the parent dir GID. */ ulong symlink_mode; /* Symlink creat mode affected by umask. */ ulong panic_mask; /* bitmask to specify panics on errors. */ + ulong error_level; /* Degree of reporting for internal probs*/ } xfs_param_t; +/* + * xfs_error_level: + * + * How much error reporting will be done when internal problems are + * encountered. These problems normally return an EFSCORRUPTED to their + * caller, with no other information reported. + * + * 0 No error reports + * 1 Report EFSCORRUPTED errors that will cause a filesystem shutdown + * 5 Report all EFSCORRUPTED errors (all of the above errors, plus any + * additional errors that are known to not cause shutdowns) + * + * xfs_panic_mask bit 0x8 turns the error reports into panics + */ + enum { XFS_STATS_CLEAR = 1, XFS_RESTRICT_CHOWN = 2, XFS_SGID_INHERIT = 3, XFS_SYMLINK_MODE = 4, XFS_PANIC_MASK = 5, + XFS_ERRLEVEL = 6, }; extern xfs_param_t xfs_params; diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_vfs.h linux-2.5.65-bk3/fs/xfs/linux/xfs_vfs.h --- linux-2.5.65-bk2/fs/xfs/linux/xfs_vfs.h Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_vfs.h Mon Mar 31 12:41:45 2003 @@ -75,9 +75,6 @@ int (*vfs_mount)(struct vfs *, struct xfs_mount_args *, struct cred *); /* mount file system */ - int (*vfs_dounmount)(bhv_desc_t *, int, struct vnode *, - struct cred *); - /* preparation and unmount */ int (*vfs_unmount)(bhv_desc_t *, int, struct cred *); /* unmount file system */ int (*vfs_root)(bhv_desc_t *, struct vnode **); @@ -98,48 +95,30 @@ int, char *, int); } vfsops_t; -#define VFS_DOUNMOUNT(vfsp,f,vp,cr, rv) \ -{ \ - BHV_READ_LOCK(&(vfsp)->vfs_bh); \ - rv = (*(VFS_FOPS(vfsp)->vfs_dounmount))((vfsp)->vfs_fbhv, f, vp, cr); \ - BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \ -} #define VFS_UNMOUNT(vfsp,f,cr, rv) \ { \ - BHV_READ_LOCK(&(vfsp)->vfs_bh); \ - rv = (*(VFS_FOPS(vfsp)->vfs_unmount))((vfsp)->vfs_fbhv, f, cr); \ - BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \ + rv = (*(VFS_FOPS(vfsp)->vfs_unmount))((vfsp)->vfs_fbhv, f, cr); \ } #define VFS_ROOT(vfsp, vpp, rv) \ { \ - BHV_READ_LOCK(&(vfsp)->vfs_bh); \ rv = (*(VFS_FOPS(vfsp)->vfs_root))((vfsp)->vfs_fbhv, vpp); \ - BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \ } #define VFS_STATVFS(vfsp, sp, vp, rv) \ { \ - BHV_READ_LOCK(&(vfsp)->vfs_bh); \ - rv = (*(VFS_FOPS(vfsp)->vfs_statvfs))((vfsp)->vfs_fbhv, sp, vp); \ - BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \ + rv = (*(VFS_FOPS(vfsp)->vfs_statvfs))((vfsp)->vfs_fbhv, sp, vp);\ } #define VFS_SYNC(vfsp, flag, cr, rv) \ { \ - BHV_READ_LOCK(&(vfsp)->vfs_bh); \ rv = (*(VFS_FOPS(vfsp)->vfs_sync))((vfsp)->vfs_fbhv, flag, cr); \ - BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \ } #define VFS_VGET(vfsp, vpp, fidp, rv) \ { \ - BHV_READ_LOCK(&(vfsp)->vfs_bh); \ rv = (*(VFS_FOPS(vfsp)->vfs_vget))((vfsp)->vfs_fbhv, vpp, fidp); \ - BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \ } #define VFS_INIT_VNODE(vfsp, vp, bhv, unlock) \ { \ - BHV_READ_LOCK(&(vfsp)->vfs_bh); \ (*(VFS_FOPS(vfsp)->vfs_init_vnode))((vfsp)->vfs_fbhv, vp, bhv, unlock);\ - BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \ } /* No behavior lock here */ @@ -148,9 +127,7 @@ #define VFS_DMAPI_FSYS_VECTOR(vfsp, df, rv) \ { \ - BHV_READ_LOCK(&(vfsp)->vfs_bh); \ rv = (*(VFS_FOPS(vfsp)->vfs_dmapi_fsys_vector))((vfsp)->vfs_fbhv, df); \ - BHV_READ_UNLOCK(&(vfsp)->vfs_bh); \ } diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_vnode.c linux-2.5.65-bk3/fs/xfs/linux/xfs_vnode.c --- linux-2.5.65-bk2/fs/xfs/linux/xfs_vnode.c Mon Mar 17 13:44:02 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_vnode.c Mon Mar 31 12:41:45 2003 @@ -137,6 +137,7 @@ struct vnode *vp = LINVFS_GET_VP(inode); XFS_STATS_INC(xfsstats.vn_active); + XFS_STATS_INC(xfsstats.vn_alloc); vp->v_flag = VMODIFIED; spinlock_init(&vp->v_lock, "v_lock"); diff -urN linux-2.5.65-bk2/fs/xfs/linux/xfs_vnode.h linux-2.5.65-bk3/fs/xfs/linux/xfs_vnode.h --- linux-2.5.65-bk2/fs/xfs/linux/xfs_vnode.h Mon Mar 17 13:44:51 2003 +++ linux-2.5.65-bk3/fs/xfs/linux/xfs_vnode.h Mon Mar 31 12:41:45 2003 @@ -98,11 +98,6 @@ #define VNODE_TO_FIRST_BHV(vp) (BHV_HEAD_FIRST(&(vp)->v_bh)) #define VN_BHV_HEAD(vp) ((bhv_head_t *)(&((vp)->v_bh))) -#define VN_BHV_READ_LOCK(bhp) BHV_READ_LOCK(bhp) -#define VN_BHV_READ_UNLOCK(bhp) BHV_READ_UNLOCK(bhp) -#define VN_BHV_WRITE_LOCK(bhp) BHV_WRITE_LOCK(bhp) -#define VN_BHV_NOT_READ_LOCKED(bhp) BHV_NOT_READ_LOCKED(bhp) -#define VN_BHV_NOT_WRITE_LOCKED(bhp) BHV_NOT_WRITE_LOCKED(bhp) #define vn_bhv_head_init(bhp,name) bhv_head_init(bhp,name) #define vn_bhv_remove(bhp,bdp) bhv_remove(bhp,bdp) #define vn_bhv_lookup(bhp,ops) bhv_lookup(bhp,ops) @@ -274,187 +269,130 @@ #define VOP_READ(vp,file,iov,segs,offset,cr,rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,cr); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_WRITE(vp,file,iov,segs,offset,cr,rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,cr);\ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_SENDFILE(vp,f,of,cnt,act,targ,cr,rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,of,cnt,act,targ,cr);\ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_BMAP(vp,of,sz,rw,b,n,rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_OPEN(vp, cr, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_GETATTR(vp, vap, f, cr, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_SETATTR(vp, vap, f, cr, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_ACCESS(vp, mode, cr, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, cr); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_LOOKUP(vp,d,vpp,f,rdir,cr,rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_CREATE(dvp,d,vap,vpp,cr,rv) \ { \ - VN_BHV_READ_LOCK(&(dvp)->v_bh); \ rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr); \ - VN_BHV_READ_UNLOCK(&(dvp)->v_bh); \ } #define VOP_REMOVE(dvp,d,cr,rv) \ { \ - VN_BHV_READ_LOCK(&(dvp)->v_bh); \ rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,d,cr); \ - VN_BHV_READ_UNLOCK(&(dvp)->v_bh); \ } #define VOP_LINK(tdvp,fvp,d,cr,rv) \ { \ - VN_BHV_READ_LOCK(&(tdvp)->v_bh); \ rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr); \ - VN_BHV_READ_UNLOCK(&(tdvp)->v_bh); \ } #define VOP_RENAME(fvp,fnm,tdvp,tnm,cr,rv) \ { \ - VN_BHV_READ_LOCK(&(fvp)->v_bh); \ rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr); \ - VN_BHV_READ_UNLOCK(&(fvp)->v_bh); \ } #define VOP_MKDIR(dp,d,vap,vpp,cr,rv) \ { \ - VN_BHV_READ_LOCK(&(dp)->v_bh); \ rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr); \ - VN_BHV_READ_UNLOCK(&(dp)->v_bh); \ } #define VOP_RMDIR(dp,d,cr,rv) \ { \ - VN_BHV_READ_LOCK(&(dp)->v_bh); \ rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr); \ - VN_BHV_READ_UNLOCK(&(dp)->v_bh); \ } #define VOP_READDIR(vp,uiop,cr,eofp,rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv) \ { \ - VN_BHV_READ_LOCK(&(dvp)->v_bh); \ - rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr); \ - VN_BHV_READ_UNLOCK(&(dvp)->v_bh); \ + rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr); \ } #define VOP_READLINK(vp,uiop,cr,rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,cr); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_FSYNC(vp,f,cr,b,e,rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_INACTIVE(vp, cr, rv) \ -{ /* vnode not reference-able, so no need to lock chain */ \ +{ \ rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr); \ } #define VOP_RELEASE(vp, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_release, vp)((vp)->v_fbhv); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_FID2(vp, fidp, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_RWLOCK(vp,i) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ (void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i); \ - /* "allow" is done by rwunlock */ \ } #define VOP_RWLOCK_TRY(vp,i) \ _VOP_(vop_rwlock, vp)((vp)->v_fbhv, i) #define VOP_RWUNLOCK(vp,i) \ -{ /* "prevent" was done by rwlock */ \ +{ \ (void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_RECLAIM(vp, rv) \ -{ /* vnode not reference-able, so no need to lock chain */ \ +{ \ rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv); \ } #define VOP_ATTR_GET(vp, name, val, vallenp, fl, cred, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_ATTR_SET(vp, name, val, vallen, fl, cred, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_ATTR_REMOVE(vp, name, flags, cred, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_ATTR_LIST(vp, buf, buflen, fl, cursor, cred, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred);\ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_LINK_REMOVED(vp, dvp, linkzero) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ (void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_VNODE_CHANGE(vp, cmd, val) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ (void)_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,cmd,val); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } /* * These are page cache functions that now go thru VOPs. @@ -462,39 +400,29 @@ */ #define VOP_TOSS_PAGES(vp, first, last, fiopt) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ _VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } /* * 'last' parameter is unused and left in for IRIX compatibility */ #define VOP_FLUSHINVAL_PAGES(vp, first, last, fiopt) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ _VOP_(vop_flushinval_pages, vp)((vp)->v_fbhv,first,last,fiopt); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } /* * 'last' parameter is unused and left in for IRIX compatibility */ #define VOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt);\ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_IOCTL(vp, inode, filp, cmd, arg, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,cmd,arg); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } #define VOP_IFLUSH(vp, flags, rv) \ { \ - VN_BHV_READ_LOCK(&(vp)->v_bh); \ rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags); \ - VN_BHV_READ_UNLOCK(&(vp)->v_bh); \ } /* diff -urN linux-2.5.65-bk2/fs/xfs/pagebuf/page_buf.c linux-2.5.65-bk3/fs/xfs/pagebuf/page_buf.c --- linux-2.5.65-bk2/fs/xfs/pagebuf/page_buf.c Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/fs/xfs/pagebuf/page_buf.c Mon Mar 31 12:41:45 2003 @@ -121,7 +121,8 @@ STATIC kmem_cache_t *pagebuf_cache; STATIC void pagebuf_daemon_wakeup(int); STATIC void pagebuf_delwri_queue(page_buf_t *, int); -STATIC struct workqueue_struct *pagebuf_workqueue; +STATIC struct workqueue_struct *pagebuf_logio_workqueue; +STATIC struct workqueue_struct *pagebuf_dataio_workqueue; /* * Pagebuf module configuration parameters, exported via @@ -786,6 +787,25 @@ } /* + * Create a skeletal pagebuf (no pages associated with it). + */ +page_buf_t * +pagebuf_lookup( + struct pb_target *target, + loff_t ioff, + size_t isize, + page_buf_flags_t flags) +{ + page_buf_t *pb; + + pb = pagebuf_allocate(flags); + if (pb) { + _pagebuf_initialize(pb, target, ioff, isize, flags); + } + return pb; +} + +/* * If we are not low on memory then do the readahead in a deadlock * safe manner. */ @@ -1131,6 +1151,7 @@ void pagebuf_iodone( page_buf_t *pb, + int dataio, int schedule) { pb->pb_flags &= ~(PBF_READ | PBF_WRITE); @@ -1143,7 +1164,8 @@ if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) { if (schedule) { INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb); - queue_work(pagebuf_workqueue, &pb->pb_iodone_work); + queue_work(dataio ? pagebuf_dataio_workqueue : + pagebuf_logio_workqueue, &pb->pb_iodone_work); } else { pagebuf_iodone_work(pb); } @@ -1268,7 +1290,7 @@ if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { pb->pb_locked = 0; - pagebuf_iodone(pb, 1); + pagebuf_iodone(pb, 0, 1); } bio_put(bio); @@ -1412,7 +1434,7 @@ if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) { pb->pb_locked = 0; - pagebuf_iodone(pb, 0); + pagebuf_iodone(pb, 0, 0); } return 0; @@ -1734,13 +1756,21 @@ { int rval; - pagebuf_workqueue = create_workqueue("pagebuf"); - if (!pagebuf_workqueue) + pagebuf_logio_workqueue = create_workqueue("xfslogd"); + if (!pagebuf_logio_workqueue) return -ENOMEM; + pagebuf_dataio_workqueue = create_workqueue("xfsdatad"); + if (!pagebuf_dataio_workqueue) { + destroy_workqueue(pagebuf_logio_workqueue); + return -ENOMEM; + } + rval = kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES); - if (rval < 0) - destroy_workqueue(pagebuf_workqueue); + if (rval < 0) { + destroy_workqueue(pagebuf_logio_workqueue); + destroy_workqueue(pagebuf_dataio_workqueue); + } return rval; } @@ -1756,7 +1786,8 @@ pbd_active = 0; wake_up_interruptible(&pbd_waitq); wait_event_interruptible(pbd_waitq, pbd_active); - destroy_workqueue(pagebuf_workqueue); + destroy_workqueue(pagebuf_logio_workqueue); + destroy_workqueue(pagebuf_dataio_workqueue); } diff -urN linux-2.5.65-bk2/fs/xfs/pagebuf/page_buf.h linux-2.5.65-bk3/fs/xfs/pagebuf/page_buf.h --- linux-2.5.65-bk2/fs/xfs/pagebuf/page_buf.h Mon Mar 17 13:44:09 2003 +++ linux-2.5.65-bk3/fs/xfs/pagebuf/page_buf.h Mon Mar 31 12:41:45 2003 @@ -169,8 +169,8 @@ * This buffer structure is used by the page cache buffer management routines * to refer to an assembly of pages forming a logical buffer. The actual * I/O is performed with buffer_head or bio structures, as required by drivers, - * for drivers which do not understand this structure. The buffer structure is - * used on temporary basis only, and discarded when released. + * for drivers which do not understand this structure. The buffer structure is + * used on temporary basis only, and discarded when released. * * The real data storage is recorded in the page cache. Metadata is * hashed to the inode for the block device on which the file system resides. @@ -245,6 +245,13 @@ page_buf_flags_t); /* PBF_LOCK, PBF_READ, */ /* PBF_ASYNC */ +extern page_buf_t *pagebuf_lookup( + struct pb_target *, + loff_t, /* starting offset of range */ + size_t, /* length of range */ + page_buf_flags_t); /* PBF_READ, PBF_WRITE, */ + /* PBF_FORCEIO, _PBF_LOCKABLE */ + extern page_buf_t *pagebuf_get_empty( /* allocate pagebuf struct with */ /* no memory or disk address */ struct pb_target *); /* mount point "fake" inode */ @@ -300,6 +307,7 @@ extern void pagebuf_iodone( /* mark buffer I/O complete */ page_buf_t *, /* buffer to mark */ + int, /* use data/log helper thread. */ int); /* run completion locally, or in * a helper thread. */ diff -urN linux-2.5.65-bk2/fs/xfs/support/debug.c linux-2.5.65-bk3/fs/xfs/support/debug.c --- linux-2.5.65-bk2/fs/xfs/support/debug.c Mon Mar 17 13:43:40 2003 +++ linux-2.5.65-bk3/fs/xfs/support/debug.c Mon Mar 31 12:41:45 2003 @@ -55,7 +55,7 @@ BUG(); } -#ifdef DEBUG +#if (defined(DEBUG) || defined(INDUCE_IO_ERRROR)) unsigned long random(void) @@ -85,8 +85,8 @@ cmn_err(register int level, char *fmt, ...) { char *fp = fmt; - ulong flags; int len; + ulong flags; va_list ap; level &= XFS_ERR_MASK; diff -urN linux-2.5.65-bk2/fs/xfs/support/kmem.c linux-2.5.65-bk3/fs/xfs/support/kmem.c --- linux-2.5.65-bk2/fs/xfs/support/kmem.c Mon Mar 17 13:44:06 2003 +++ linux-2.5.65-bk3/fs/xfs/support/kmem.c Mon Mar 31 12:41:45 2003 @@ -139,7 +139,7 @@ } rval = __vmalloc(size, flag_convert(flags), PAGE_KERNEL); - if (!rval && !(flags & KM_SLEEP)) + if (!rval && (flags & KM_SLEEP)) panic("kmem_alloc: NULL memory on KM_SLEEP request!"); return rval; @@ -176,7 +176,9 @@ new = kmem_alloc(newsize, flags); if (ptr) { - memcpy(new, ptr, ((oldsize < newsize) ? oldsize : newsize)); + if (new) + memcpy(new, ptr, + ((oldsize < newsize) ? oldsize : newsize)); kmem_free(ptr, oldsize); } diff -urN linux-2.5.65-bk2/fs/xfs/support/time.h linux-2.5.65-bk3/fs/xfs/support/time.h --- linux-2.5.65-bk2/fs/xfs/support/time.h Mon Mar 17 13:44:50 2003 +++ linux-2.5.65-bk3/fs/xfs/support/time.h Mon Mar 31 12:41:45 2003 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -35,6 +35,8 @@ #include #include +typedef struct timespec timespec_t; + static inline void delay(long ticks) { current->state = TASK_UNINTERRUPTIBLE; diff -urN linux-2.5.65-bk2/fs/xfs/support/uuid.h linux-2.5.65-bk3/fs/xfs/support/uuid.h --- linux-2.5.65-bk2/fs/xfs/support/uuid.h Mon Mar 17 13:44:50 2003 +++ linux-2.5.65-bk3/fs/xfs/support/uuid.h Mon Mar 31 12:41:45 2003 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -32,6 +32,10 @@ #ifndef __XFS_SUPPORT_UUID_H__ #define __XFS_SUPPORT_UUID_H__ +typedef struct { + unsigned char __u_bits[16]; +} uuid_t; + void uuid_create_nil(uuid_t *uuid); int uuid_is_nil(uuid_t *uuid); int uuid_equal(uuid_t *uuid1, uuid_t *uuid2); diff -urN linux-2.5.65-bk2/fs/xfs/xfs_alloc.c linux-2.5.65-bk3/fs/xfs/xfs_alloc.c --- linux-2.5.65-bk2/fs/xfs/xfs_alloc.c Mon Mar 17 13:43:49 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_alloc.c Mon Mar 31 12:41:45 2003 @@ -2183,34 +2183,11 @@ INT_GET(agf->agf_flfirst, ARCH_CONVERT) < XFS_AGFL_SIZE(mp) && INT_GET(agf->agf_fllast, ARCH_CONVERT) < XFS_AGFL_SIZE(mp) && INT_GET(agf->agf_flcount, ARCH_CONVERT) <= XFS_AGFL_SIZE(mp); - if (XFS_TEST_ERROR(!agf_ok, mp, XFS_ERRTAG_ALLOC_READ_AGF, - XFS_RANDOM_ALLOC_READ_AGF)) { + if (unlikely(XFS_TEST_ERROR(!agf_ok, mp, XFS_ERRTAG_ALLOC_READ_AGF, + XFS_RANDOM_ALLOC_READ_AGF))) { + XFS_CORRUPTION_ERROR("xfs_alloc_read_agf", + XFS_ERRLEVEL_LOW, mp, agf); xfs_trans_brelse(tp, bp); -#ifdef __KERNEL__ /* additional, temporary, debugging code */ - cmn_err(CE_NOTE, - "xfs_alloc_read_agf: error in <%s> AG %d", - mp->m_fsname, agno); - if (INT_GET(agf->agf_magicnum, ARCH_CONVERT) != XFS_AGF_MAGIC) - cmn_err(CE_NOTE, "bad agf_magicnum 0x%x", - INT_GET(agf->agf_magicnum, ARCH_CONVERT)); - if (!XFS_AGF_GOOD_VERSION(INT_GET(agf->agf_versionnum, ARCH_CONVERT))) - cmn_err(CE_NOTE, "Bad version number 0x%x", - INT_GET(agf->agf_versionnum, ARCH_CONVERT)); - if (!(INT_GET(agf->agf_freeblks, ARCH_CONVERT) <= - INT_GET(agf->agf_length, ARCH_CONVERT))) - cmn_err(CE_NOTE, "Bad freeblks %d %d", - INT_GET(agf->agf_freeblks, ARCH_CONVERT), - INT_GET(agf->agf_length, ARCH_CONVERT)); - if (!(INT_GET(agf->agf_flfirst, ARCH_CONVERT) < XFS_AGFL_SIZE(mp))) - cmn_err(CE_NOTE, "Bad flfirst %d", - INT_GET(agf->agf_flfirst, ARCH_CONVERT)); - if (!(INT_GET(agf->agf_fllast, ARCH_CONVERT) < XFS_AGFL_SIZE(mp))) - cmn_err(CE_NOTE, "Bad fllast %d", - INT_GET(agf->agf_fllast, ARCH_CONVERT)); - if (!(INT_GET(agf->agf_flcount, ARCH_CONVERT) <= XFS_AGFL_SIZE(mp))) - cmn_err(CE_NOTE, "Bad flcount %d", - INT_GET(agf->agf_flcount, ARCH_CONVERT)); -#endif return XFS_ERROR(EFSCORRUPTED); } pag = &mp->m_perag[agno]; diff -urN linux-2.5.65-bk2/fs/xfs/xfs_attr.c linux-2.5.65-bk3/fs/xfs/xfs_attr.c --- linux-2.5.65-bk2/fs/xfs/xfs_attr.c Mon Mar 17 13:44:09 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_attr.c Mon Mar 31 12:41:45 2003 @@ -1125,8 +1125,10 @@ return(error); ASSERT(bp != NULL); leaf = bp->data; - if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - != XFS_ATTR_LEAF_MAGIC) { + if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) + != XFS_ATTR_LEAF_MAGIC)) { + XFS_CORRUPTION_ERROR("xfs_attr_leaf_list", XFS_ERRLEVEL_LOW, + context->dp->i_mount, leaf); xfs_da_brelse(NULL, bp); return(XFS_ERROR(EFSCORRUPTED)); } @@ -1806,14 +1808,22 @@ XFS_ATTR_FORK); if (error) return(error); - if (bp == NULL) + if (unlikely(bp == NULL)) { + XFS_ERROR_REPORT("xfs_attr_node_list(2)", + XFS_ERRLEVEL_LOW, + context->dp->i_mount); return(XFS_ERROR(EFSCORRUPTED)); + } node = bp->data; if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) == XFS_ATTR_LEAF_MAGIC) break; - if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) - != XFS_DA_NODE_MAGIC) { + if (unlikely(INT_GET(node->hdr.info.magic, ARCH_CONVERT) + != XFS_DA_NODE_MAGIC)) { + XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)", + XFS_ERRLEVEL_LOW, + context->dp->i_mount, + node); xfs_da_brelse(NULL, bp); return(XFS_ERROR(EFSCORRUPTED)); } @@ -1846,8 +1856,11 @@ */ for (;;) { leaf = bp->data; - if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) - != XFS_ATTR_LEAF_MAGIC) { + if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) + != XFS_ATTR_LEAF_MAGIC)) { + XFS_CORRUPTION_ERROR("xfs_attr_node_list(4)", + XFS_ERRLEVEL_LOW, + context->dp->i_mount, leaf); xfs_da_brelse(NULL, bp); return(XFS_ERROR(EFSCORRUPTED)); } @@ -1860,8 +1873,12 @@ &bp, XFS_ATTR_FORK); if (error) return(error); - if (bp == NULL) + if (unlikely((bp == NULL))) { + XFS_ERROR_REPORT("xfs_attr_node_list(5)", + XFS_ERRLEVEL_LOW, + context->dp->i_mount); return(XFS_ERROR(EFSCORRUPTED)); + } } xfs_da_brelse(NULL, bp); return(0); diff -urN linux-2.5.65-bk2/fs/xfs/xfs_attr_leaf.c linux-2.5.65-bk3/fs/xfs/xfs_attr_leaf.c --- linux-2.5.65-bk2/fs/xfs/xfs_attr_leaf.c Mon Mar 17 13:44:05 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_attr_leaf.c Mon Mar 31 12:41:45 2003 @@ -455,9 +455,13 @@ nsbuf = 0; for (i = 0, sfe = &sf->list[0]; i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) { - if (((char *)sfe < (char *)sf) || + if (unlikely( + ((char *)sfe < (char *)sf) || ((char *)sfe >= ((char *)sf + dp->i_afp->if_bytes)) || - (sfe->namelen >= MAXNAMELEN)) { + (sfe->namelen >= MAXNAMELEN))) { + XFS_CORRUPTION_ERROR("xfs_attr_shortform_list", + XFS_ERRLEVEL_LOW, + context->dp->i_mount, sfe); xfs_attr_trace_l_c("sf corrupted", context); kmem_free(sbuf, sbsize); return XFS_ERROR(EFSCORRUPTED); diff -urN linux-2.5.65-bk2/fs/xfs/xfs_bmap.c linux-2.5.65-bk3/fs/xfs/xfs_bmap.c --- linux-2.5.65-bk2/fs/xfs/xfs_bmap.c Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_bmap.c Mon Mar 31 12:41:45 2003 @@ -160,8 +160,7 @@ xfs_inode_t *ip, /* incore inode pointer */ xfs_btree_cur_t *cur, /* btree cursor */ int *logflagsp, /* inode logging flags */ - int whichfork, /* data or attr fork */ - int async); /* xaction can be async */ + int whichfork); /* data or attr fork */ #ifdef XFSDEBUG /* @@ -187,7 +186,6 @@ xfs_bmap_free_t *flist, /* list of extents to be freed */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *new, /* new data to put in extent list */ - int iflags, /* input flags (meta-data or not) */ int *logflagsp,/* inode logging flags */ int whichfork, /* data or attr fork */ int rsvd); /* OK to allocate reserved blocks */ @@ -811,7 +809,7 @@ RIGHT.br_blockcount, &i))) goto done; ASSERT(i == 1); - if ((error = xfs_bmbt_delete(cur, 0, &i))) + if ((error = xfs_bmbt_delete(cur, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_decrement(cur, 0, &i))) @@ -1349,13 +1347,13 @@ RIGHT.br_blockcount, &i))) goto done; ASSERT(i == 1); - if ((error = xfs_bmbt_delete(cur, 0, &i))) + if ((error = xfs_bmbt_delete(cur, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_decrement(cur, 0, &i))) goto done; ASSERT(i == 1); - if ((error = xfs_bmbt_delete(cur, 0, &i))) + if ((error = xfs_bmbt_delete(cur, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_decrement(cur, 0, &i))) @@ -1394,7 +1392,7 @@ &i))) goto done; ASSERT(i == 1); - if ((error = xfs_bmbt_delete(cur, 0, &i))) + if ((error = xfs_bmbt_delete(cur, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_decrement(cur, 0, &i))) @@ -1434,7 +1432,7 @@ RIGHT.br_blockcount, &i))) goto done; ASSERT(i == 1); - if ((error = xfs_bmbt_delete(cur, 0, &i))) + if ((error = xfs_bmbt_delete(cur, &i))) goto done; ASSERT(i == 1); if ((error = xfs_bmbt_decrement(cur, 0, &i))) @@ -2010,7 +2008,7 @@ right.br_startblock, right.br_blockcount, &i))) return error; ASSERT(i == 1); - if ((error = xfs_bmbt_delete(cur, 0, &i))) + if ((error = xfs_bmbt_delete(cur, &i))) return error; ASSERT(i == 1); if ((error = xfs_bmbt_decrement(cur, 0, &i))) @@ -2722,8 +2720,7 @@ xfs_inode_t *ip, /* incore inode pointer */ xfs_btree_cur_t *cur, /* btree cursor */ int *logflagsp, /* inode logging flags */ - int whichfork, /* data or attr fork */ - int async) /* xaction can be async */ + int whichfork) /* data or attr fork */ { /* REFERENCED */ xfs_bmbt_block_t *cblock;/* child btree block */ @@ -2757,8 +2754,6 @@ if ((error = xfs_btree_check_lblock(cur, cblock, 0, cbp))) return error; xfs_bmap_add_free(cbno, 1, cur->bc_private.b.flist, mp); - if (!async) - xfs_trans_set_sync(tp); ip->i_d.di_nblocks--; if (XFS_IS_QUOTA_ON(mp) && ip->i_ino != mp->m_sb.sb_uquotino && @@ -2787,7 +2782,6 @@ xfs_bmap_free_t *flist, /* list of extents to be freed */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *del, /* data to remove from extent list */ - int iflags, /* input flags */ int *logflagsp, /* inode logging flags */ int whichfork, /* data or attr fork */ int rsvd) /* OK to allocate reserved blocks */ @@ -2916,7 +2910,7 @@ flags |= XFS_ILOG_FEXT(whichfork); break; } - if ((error = xfs_bmbt_delete(cur, iflags & XFS_BMAPI_ASYNC, &i))) + if ((error = xfs_bmbt_delete(cur, &i))) goto done; ASSERT(i == 1); break; @@ -4396,12 +4390,14 @@ num_recs = INT_GET(block->bb_numrecs, ARCH_CONVERT); - if (i + num_recs > room) { + if (unlikely(i + num_recs > room)) { ASSERT(i + num_recs <= room); xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt dinode %Lu, (btree extents). " - "Unmount and run xfs_repair.", + "corrupt dinode %Lu, (btree extents). Unmount and run xfs_repair.", (unsigned long long) ip->i_ino); + XFS_ERROR_REPORT("xfs_bmap_read_extents(1)", + XFS_ERRLEVEL_LOW, + ip->i_mount); goto error0; } XFS_WANT_CORRUPTED_GOTO( @@ -4429,7 +4425,10 @@ * any "older" data bmap btree records for a * set bit in the "extent flag" position. */ - if (xfs_check_nostate_extents(temp, num_recs)) { + if (unlikely(xfs_check_nostate_extents(temp, num_recs))) { + XFS_ERROR_REPORT("xfs_bmap_read_extents(2)", + XFS_ERRLEVEL_LOW, + ip->i_mount); goto error0; } } @@ -4606,12 +4605,15 @@ ASSERT(*nmap <= XFS_BMAP_MAX_NMAP || !(flags & XFS_BMAPI_WRITE)); whichfork = (flags & XFS_BMAPI_ATTRFORK) ? XFS_ATTR_FORK : XFS_DATA_FORK; - if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && - XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && - XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL) { + mp = ip->i_mount; + if (unlikely(XFS_TEST_ERROR( + (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL), + mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { + XFS_ERROR_REPORT("xfs_bmapi", XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } - mp = ip->i_mount; if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); ifp = XFS_IFORK_PTR(ip, whichfork); @@ -5027,7 +5029,7 @@ XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) { ASSERT(wr && cur); error = xfs_bmap_btree_to_extents(tp, ip, cur, - &tmp_logflags, whichfork, 0); + &tmp_logflags, whichfork); logflags |= tmp_logflags; if (error) goto error0; @@ -5102,8 +5104,11 @@ xfs_bmbt_irec_t prev; /* previous extent list record */ ifp = XFS_IFORK_PTR(ip, whichfork); - if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && - XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) { + if (unlikely( + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)) { + XFS_ERROR_REPORT("xfs_bmapi_single", XFS_ERRLEVEL_LOW, + ip->i_mount); return XFS_ERROR(EFSCORRUPTED); } if (XFS_FORCED_SHUTDOWN(ip->i_mount)) @@ -5148,7 +5153,6 @@ xfs_bmap_free_t *flist, /* i/o: list extents to free */ int *done) /* set if not done yet */ { - int async; /* xactions can be async */ xfs_btree_cur_t *cur; /* bmap btree cursor */ xfs_bmbt_irec_t del; /* extent being deleted */ int eof; /* is deleting at eof */ @@ -5175,14 +5179,16 @@ whichfork = (flags & XFS_BMAPI_ATTRFORK) ? XFS_ATTR_FORK : XFS_DATA_FORK; ifp = XFS_IFORK_PTR(ip, whichfork); - if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && - XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) { + if (unlikely( + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) { + XFS_ERROR_REPORT("xfs_bunmapi", XFS_ERRLEVEL_LOW, + ip->i_mount); return XFS_ERROR(EFSCORRUPTED); } mp = ip->i_mount; if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); - async = flags & XFS_BMAPI_ASYNC; rsvd = (flags & XFS_BMAPI_RSVBLOCKS) != 0; ASSERT(len > 0); ASSERT(nexts >= 0); @@ -5409,7 +5415,7 @@ goto error0; } error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del, - flags, &tmp_logflags, whichfork, rsvd); + &tmp_logflags, whichfork, rsvd); logflags |= tmp_logflags; if (error) goto error0; @@ -5455,7 +5461,7 @@ XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) { ASSERT(cur != NULL); error = xfs_bmap_btree_to_extents(tp, ip, cur, &tmp_logflags, - whichfork, async); + whichfork); logflags |= tmp_logflags; if (error) goto error0; @@ -5562,11 +5568,11 @@ ip->i_d.di_aformat != XFS_DINODE_FMT_BTREE && ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) return XFS_ERROR(EINVAL); - } else if (ip->i_d.di_aformat != 0 && - ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS) { - cmn_err(CE_NOTE, - "EFSCORRUPTED returned from file %s line %d", - __FILE__, __LINE__); + } else if (unlikely( + ip->i_d.di_aformat != 0 && + ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS)) { + XFS_ERROR_REPORT("xfs_getbmap", XFS_ERRLEVEL_LOW, + ip->i_mount); return XFS_ERROR(EFSCORRUPTED); } } else if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS && @@ -6114,12 +6120,11 @@ mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); if ( XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS ) { - if (xfs_bmap_count_leaves(ifp->if_u1.if_extents, + if (unlikely(xfs_bmap_count_leaves(ifp->if_u1.if_extents, ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t), - count) < 0) { - cmn_err(CE_NOTE, - "EFSCORRUPTED returned from file %s line %d", - __FILE__, __LINE__); + count) < 0)) { + XFS_ERROR_REPORT("xfs_bmap_count_blocks(1)", + XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } return 0; @@ -6137,10 +6142,9 @@ ASSERT(XFS_FSB_TO_AGBNO(mp, INT_GET(*pp, ARCH_CONVERT)) < mp->m_sb.sb_agblocks); bno = INT_GET(*pp, ARCH_CONVERT); - if (xfs_bmap_count_tree(mp, tp, bno, level, count) < 0) { - cmn_err(CE_NOTE, - "EFSCORRUPTED returned from file %s line %d", - __FILE__, __LINE__); + if (unlikely(xfs_bmap_count_tree(mp, tp, bno, level, count) < 0)) { + XFS_ERROR_REPORT("xfs_bmap_count_blocks(2)", XFS_ERRLEVEL_LOW, + mp); return XFS_ERROR(EFSCORRUPTED); } @@ -6191,12 +6195,11 @@ pp = XFS_BTREE_PTR_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block, 1, mp->m_bmap_dmxr[1]); bno = INT_GET(*pp, ARCH_CONVERT); - if ((error = - xfs_bmap_count_tree(mp, tp, bno, level, count)) < 0) { + if (unlikely((error = + xfs_bmap_count_tree(mp, tp, bno, level, count)) < 0)) { xfs_trans_brelse(tp, bp); - cmn_err(CE_NOTE, - "EFSCORRUPTED returned from file %s line %d", - __FILE__, __LINE__); + XFS_ERROR_REPORT("xfs_bmap_count_tree(1)", + XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } xfs_trans_brelse(tp, bp); @@ -6207,11 +6210,10 @@ numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT); frp = XFS_BTREE_REC_ADDR(mp->m_sb.sb_blocksize, xfs_bmbt, block, 1, mp->m_bmap_dmxr[0]); - if (xfs_bmap_count_leaves(frp, numrecs, count) < 0) { + if (unlikely(xfs_bmap_count_leaves(frp, numrecs, count) < 0)) { xfs_trans_brelse(tp, bp); - cmn_err(CE_NOTE, - "EFSCORRUPTED returned from file %s line %d", - __FILE__, __LINE__); + XFS_ERROR_REPORT("xfs_bmap_count_tree(2)", + XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } xfs_trans_brelse(tp, bp); diff -urN linux-2.5.65-bk2/fs/xfs/xfs_bmap_btree.c linux-2.5.65-bk3/fs/xfs/xfs_bmap_btree.c --- linux-2.5.65-bk2/fs/xfs/xfs_bmap_btree.c Mon Mar 17 13:44:07 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_bmap_btree.c Mon Mar 31 12:41:45 2003 @@ -41,7 +41,7 @@ */ -STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *, int); +STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *); STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *); @@ -304,7 +304,6 @@ xfs_bmbt_delrec( xfs_btree_cur_t *cur, int level, - int async, /* deletion can be async */ int *stat) /* success/failure */ { xfs_bmbt_block_t *block; /* bmap btree block */ @@ -408,7 +407,7 @@ if (level == cur->bc_nlevels - 1) { xfs_iroot_realloc(cur->bc_private.b.ip, -1, cur->bc_private.b.whichfork); - if ((error = xfs_bmbt_killroot(cur, async))) { + if ((error = xfs_bmbt_killroot(cur))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); goto error0; } @@ -442,7 +441,7 @@ */ if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK && level == cur->bc_nlevels - 2) { - if ((error = xfs_bmbt_killroot(cur, async))) { + if ((error = xfs_bmbt_killroot(cur))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); goto error0; } @@ -645,8 +644,6 @@ } xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1, cur->bc_private.b.flist, mp); - if (!async) - xfs_trans_set_sync(cur->bc_tp); cur->bc_private.b.ip->i_d.di_nblocks--; xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE); if (XFS_IS_QUOTA_ON(mp) && @@ -911,8 +908,7 @@ STATIC int xfs_bmbt_killroot( - xfs_btree_cur_t *cur, - int async) + xfs_btree_cur_t *cur) { xfs_bmbt_block_t *block; xfs_bmbt_block_t *cblock; @@ -991,8 +987,6 @@ memcpy(pp, cpp, INT_GET(block->bb_numrecs, ARCH_CONVERT) * sizeof(*pp)); xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1, cur->bc_private.b.flist, cur->bc_mp); - if (!async) - xfs_trans_set_sync(cur->bc_tp); ip->i_d.di_nblocks--; if (XFS_IS_QUOTA_ON(cur->bc_mp) && ip->i_ino != cur->bc_mp->m_sb.sb_uquotino && @@ -1834,7 +1828,6 @@ int /* error */ xfs_bmbt_delete( xfs_btree_cur_t *cur, - int async, /* deletion can be async */ int *stat) /* success/failure */ { int error; /* error return value */ @@ -1846,7 +1839,7 @@ XFS_BMBT_TRACE_CURSOR(cur, ENTRY); for (level = 0, i = 2; i == 2; level++) { - if ((error = xfs_bmbt_delrec(cur, level, async, &i))) { + if ((error = xfs_bmbt_delrec(cur, level, &i))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } diff -urN linux-2.5.65-bk2/fs/xfs/xfs_bmap_btree.h linux-2.5.65-bk3/fs/xfs/xfs_bmap_btree.h --- linux-2.5.65-bk2/fs/xfs/xfs_bmap_btree.h Mon Mar 17 13:44:06 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_bmap_btree.h Mon Mar 31 12:41:45 2003 @@ -479,7 +479,6 @@ int xfs_bmbt_delete( struct xfs_btree_cur *, - int, int *); void diff -urN linux-2.5.65-bk2/fs/xfs/xfs_btree.c linux-2.5.65-bk3/fs/xfs/xfs_btree.c --- linux-2.5.65-bk2/fs/xfs/xfs_btree.c Mon Mar 17 13:44:22 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_btree.c Mon Mar 31 12:41:45 2003 @@ -190,15 +190,12 @@ !INT_ISZERO(block->bb_rightsib, ARCH_CONVERT) && (INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLDFSBNO || XFS_FSB_SANITY_CHECK(mp, INT_GET(block->bb_rightsib, ARCH_CONVERT))); - if (XFS_TEST_ERROR(!lblock_ok, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK, - XFS_RANDOM_BTREE_CHECK_LBLOCK)) { + if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK, + XFS_RANDOM_BTREE_CHECK_LBLOCK))) { if (bp) xfs_buftrace("LBTREE ERROR", bp); -#ifdef __KERNEL__ /* additional, temporary, debugging code */ - cmn_err(CE_NOTE, - "EFSCORRUPTED returned from file %s line %d", - __FILE__, __LINE__); -#endif + XFS_ERROR_REPORT("xfs_btree_check_lblock", XFS_ERRLEVEL_LOW, + mp); return XFS_ERROR(EFSCORRUPTED); } return 0; @@ -312,22 +309,13 @@ (INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK || INT_GET(block->bb_rightsib, ARCH_CONVERT) < agflen) && !INT_ISZERO(block->bb_rightsib, ARCH_CONVERT); - if (XFS_TEST_ERROR(!sblock_ok, cur->bc_mp, + if (unlikely(XFS_TEST_ERROR(!sblock_ok, cur->bc_mp, XFS_ERRTAG_BTREE_CHECK_SBLOCK, - XFS_RANDOM_BTREE_CHECK_SBLOCK)) { + XFS_RANDOM_BTREE_CHECK_SBLOCK))) { if (bp) xfs_buftrace("SBTREE ERROR", bp); -#ifdef __KERNEL__ /* additional, temporary, debugging code */ - cmn_err(CE_NOTE, - "xfs_btree_check_sblock: Not OK:"); - cmn_err(CE_NOTE, - "magic 0x%x level %d numrecs %d leftsib %d rightsib %d", - INT_GET(block->bb_magic, ARCH_CONVERT), - INT_GET(block->bb_level, ARCH_CONVERT), - INT_GET(block->bb_numrecs, ARCH_CONVERT), - INT_GET(block->bb_leftsib, ARCH_CONVERT), - INT_GET(block->bb_rightsib, ARCH_CONVERT)); -#endif + XFS_ERROR_REPORT("xfs_btree_check_sblock", XFS_ERRLEVEL_LOW, + cur->bc_mp); return XFS_ERROR(EFSCORRUPTED); } return 0; diff -urN linux-2.5.65-bk2/fs/xfs/xfs_btree.h linux-2.5.65-bk3/fs/xfs/xfs_btree.h --- linux-2.5.65-bk2/fs/xfs/xfs_btree.h Mon Mar 17 13:43:44 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_btree.h Mon Mar 31 12:41:45 2003 @@ -570,7 +570,9 @@ { \ int fs_is_ok = (x); \ ASSERT(fs_is_ok); \ - if (!fs_is_ok) { \ + if (unlikely(!fs_is_ok)) { \ + XFS_ERROR_REPORT("XFS_WANT_CORRUPTED_GOTO", \ + XFS_ERRLEVEL_LOW, NULL); \ error = XFS_ERROR(EFSCORRUPTED); \ goto l; \ } \ @@ -580,8 +582,11 @@ { \ int fs_is_ok = (x); \ ASSERT(fs_is_ok); \ - if (!fs_is_ok) \ + if (unlikely(!fs_is_ok)) { \ + XFS_ERROR_REPORT("XFS_WANT_CORRUPTED_RETURN", \ + XFS_ERRLEVEL_LOW, NULL); \ return XFS_ERROR(EFSCORRUPTED); \ + } \ } #endif /* __XFS_BTREE_H__ */ diff -urN linux-2.5.65-bk2/fs/xfs/xfs_buf.h linux-2.5.65-bk3/fs/xfs/xfs_buf.h --- linux-2.5.65-bk2/fs/xfs/xfs_buf.h Mon Mar 17 13:44:47 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_buf.h Mon Mar 31 12:41:45 2003 @@ -163,15 +163,17 @@ #define XFS_BUF_SET_PTR(bp, val, count) \ pagebuf_associate_memory(bp, val, count) #define XFS_BUF_ADDR(bp) ((bp)->pb_bn) -#define XFS_BUF_OFFSET(bp) ((bp)->pb_file_offset >> 9) #define XFS_BUF_SET_ADDR(bp, blk) \ ((bp)->pb_bn = (page_buf_daddr_t)(blk)) +#define XFS_BUF_OFFSET(bp) ((bp)->pb_file_offset) +#define XFS_BUF_SET_OFFSET(bp, off) \ + ((bp)->pb_file_offset = (off)) #define XFS_BUF_COUNT(bp) ((bp)->pb_count_desired) #define XFS_BUF_SET_COUNT(bp, cnt) \ - ((bp)->pb_count_desired = cnt) + ((bp)->pb_count_desired = (cnt)) #define XFS_BUF_SIZE(bp) ((bp)->pb_buffer_length) #define XFS_BUF_SET_SIZE(bp, cnt) \ - ((bp)->pb_buffer_length = cnt) + ((bp)->pb_buffer_length = (cnt)) #define XFS_BUF_SET_VTYPE_REF(bp, type, ref) #define XFS_BUF_SET_VTYPE(bp, type) #define XFS_BUF_SET_REF(bp, ref) @@ -242,7 +244,7 @@ #define xfs_biodone(pb) \ - pagebuf_iodone(pb, 0) + pagebuf_iodone(pb, 0, 0) #define xfs_incore(buftarg,blkno,len,lockit) \ pagebuf_find(buftarg, blkno ,len, lockit) diff -urN linux-2.5.65-bk2/fs/xfs/xfs_buf_item.c linux-2.5.65-bk3/fs/xfs/xfs_buf_item.c --- linux-2.5.65-bk2/fs/xfs/xfs_buf_item.c Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_buf_item.c Mon Mar 31 12:41:45 2003 @@ -991,7 +991,7 @@ xfs_buf_t *bp) { xfs_log_item_t *lip; - static time_t lasttime; + static ulong lasttime; static dev_t lastdev; xfs_mount_t *mp; diff -urN linux-2.5.65-bk2/fs/xfs/xfs_da_btree.c linux-2.5.65-bk3/fs/xfs/xfs_da_btree.c --- linux-2.5.65-bk2/fs/xfs/xfs_da_btree.c Mon Mar 17 13:44:38 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_da_btree.c Mon Mar 31 12:41:45 2003 @@ -1791,8 +1791,11 @@ error = xfs_bmap_last_offset(tp, ip, &lastoff, w); if (error) return error; - if (lastoff == 0) + if (unlikely(lastoff == 0)) { + XFS_ERROR_REPORT("xfs_da_swap_lastblock(1)", XFS_ERRLEVEL_LOW, + mp); return XFS_ERROR(EFSCORRUPTED); + } /* * Read the last block in the btree space. */ @@ -1833,8 +1836,11 @@ if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w))) goto done; sib_info = sib_buf->data; - if (INT_GET(sib_info->forw, ARCH_CONVERT) != last_blkno || - INT_GET(sib_info->magic, ARCH_CONVERT) != INT_GET(dead_info->magic, ARCH_CONVERT)) { + if (unlikely( + INT_GET(sib_info->forw, ARCH_CONVERT) != last_blkno || + INT_GET(sib_info->magic, ARCH_CONVERT) != INT_GET(dead_info->magic, ARCH_CONVERT))) { + XFS_ERROR_REPORT("xfs_da_swap_lastblock(2)", + XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto done; } @@ -1852,9 +1858,12 @@ if ((error = xfs_da_read_buf(tp, ip, sib_blkno, -1, &sib_buf, w))) goto done; sib_info = sib_buf->data; - if ( INT_GET(sib_info->back, ARCH_CONVERT) != last_blkno + if (unlikely( + INT_GET(sib_info->back, ARCH_CONVERT) != last_blkno || INT_GET(sib_info->magic, ARCH_CONVERT) - != INT_GET(dead_info->magic, ARCH_CONVERT)) { + != INT_GET(dead_info->magic, ARCH_CONVERT))) { + XFS_ERROR_REPORT("xfs_da_swap_lastblock(3)", + XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto done; } @@ -1874,8 +1883,11 @@ if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w))) goto done; par_node = par_buf->data; - if (INT_GET(par_node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC || - (level >= 0 && level != INT_GET(par_node->hdr.level, ARCH_CONVERT) + 1)) { + if (unlikely( + INT_GET(par_node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC || + (level >= 0 && level != INT_GET(par_node->hdr.level, ARCH_CONVERT) + 1))) { + XFS_ERROR_REPORT("xfs_da_swap_lastblock(4)", + XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto done; } @@ -1885,7 +1897,9 @@ INT_GET(par_node->btree[entno].hashval, ARCH_CONVERT) < dead_hash; entno++) continue; - if (entno == INT_GET(par_node->hdr.count, ARCH_CONVERT)) { + if (unlikely(entno == INT_GET(par_node->hdr.count, ARCH_CONVERT))) { + XFS_ERROR_REPORT("xfs_da_swap_lastblock(5)", + XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto done; } @@ -1910,15 +1924,20 @@ par_blkno = INT_GET(par_node->hdr.info.forw, ARCH_CONVERT); xfs_da_brelse(tp, par_buf); par_buf = NULL; - if (par_blkno == 0) { + if (unlikely(par_blkno == 0)) { + XFS_ERROR_REPORT("xfs_da_swap_lastblock(6)", + XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto done; } if ((error = xfs_da_read_buf(tp, ip, par_blkno, -1, &par_buf, w))) goto done; par_node = par_buf->data; - if (INT_GET(par_node->hdr.level, ARCH_CONVERT) != level || - INT_GET(par_node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC) { + if (unlikely( + INT_GET(par_node->hdr.level, ARCH_CONVERT) != level || + INT_GET(par_node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC)) { + XFS_ERROR_REPORT("xfs_da_swap_lastblock(7)", + XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto done; } @@ -2111,6 +2130,26 @@ } if (!xfs_da_map_covers_blocks(nmap, mapp, bno, nfsb)) { error = mappedbno == -2 ? 0 : XFS_ERROR(EFSCORRUPTED); + if (unlikely(error == EFSCORRUPTED)) { + if (xfs_error_level >= XFS_ERRLEVEL_LOW) { + int i; + cmn_err(CE_ALERT, "xfs_da_do_buf: bno %lld\n", + bno); + cmn_err(CE_ALERT, "dir: inode %lld\n", + dp->i_ino); + for (i = 0; i < nmap; i++) { + cmn_err(CE_ALERT, + "[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d\n", + i, + mapp[i].br_startoff, + mapp[i].br_startblock, + mapp[i].br_blockcount, + mapp[i].br_state); + } + } + XFS_ERROR_REPORT("xfs_da_do_buf(1)", + XFS_ERRLEVEL_LOW, mp); + } goto exit0; } if (caller != 3 && nmap > 1) { @@ -2193,7 +2232,8 @@ free = rbp->data; magic = INT_GET(info->magic, ARCH_CONVERT); magic1 = INT_GET(data->hdr.magic, ARCH_CONVERT); - if (XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && + if (unlikely( + XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && (magic != XFS_DIR_LEAF_MAGIC) && (magic != XFS_ATTR_LEAF_MAGIC) && (magic != XFS_DIR2_LEAF1_MAGIC) && @@ -2202,8 +2242,10 @@ (magic1 != XFS_DIR2_DATA_MAGIC) && (INT_GET(free->hdr.magic, ARCH_CONVERT) != XFS_DIR2_FREE_MAGIC), mp, XFS_ERRTAG_DA_READ_BUF, - XFS_RANDOM_DA_READ_BUF)) { + XFS_RANDOM_DA_READ_BUF))) { xfs_buftrace("DA READ ERROR", rbp->bps[0]); + XFS_CORRUPTION_ERROR("xfs_da_do_buf(2)", + XFS_ERRLEVEL_LOW, mp, info); error = XFS_ERROR(EFSCORRUPTED); xfs_da_brelse(trans, rbp); nbplist = 0; diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dfrag.c linux-2.5.65-bk3/fs/xfs/xfs_dfrag.c --- linux-2.5.65-bk2/fs/xfs/xfs_dfrag.c Mon Mar 17 13:43:40 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_dfrag.c Mon Mar 31 12:41:45 2003 @@ -69,15 +69,12 @@ } bhp = VN_BHV_HEAD(vp); - VN_BHV_READ_LOCK(bhp); bdp = vn_bhv_lookup(bhp, &xfs_vnodeops); if (bdp == NULL) { - VN_BHV_READ_UNLOCK(bhp); error = XFS_ERROR(EBADF); goto error0; } else { ip = XFS_BHVTOI(bdp); - VN_BHV_READ_UNLOCK(bhp); } if (((tfp = fget((int)sx.sx_fdtmp)) == NULL) || @@ -87,15 +84,12 @@ } tbhp = VN_BHV_HEAD(tvp); - VN_BHV_READ_LOCK(tbhp); tbdp = vn_bhv_lookup(tbhp, &xfs_vnodeops); if (tbdp == NULL) { - VN_BHV_READ_UNLOCK(tbhp); error = XFS_ERROR(EBADF); goto error0; } else { tip = XFS_BHVTOI(tbdp); - VN_BHV_READ_UNLOCK(tbhp); } if (ip->i_ino == tip->i_ino) { diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dir.c linux-2.5.65-bk3/fs/xfs/xfs_dir.c --- linux-2.5.65-bk2/fs/xfs/xfs_dir.c Mon Mar 17 13:43:48 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_dir.c Mon Mar 31 12:41:45 2003 @@ -887,7 +887,7 @@ * hashval, then we run with it. */ if (bno > 0) { - error = xfs_da_read_buf(trans, dp, bno, -1, &bp, XFS_DATA_FORK); + error = xfs_da_read_buf(trans, dp, bno, -2, &bp, XFS_DATA_FORK); if ((error != 0) && (error != EFSCORRUPTED)) return(error); if (bp) @@ -962,9 +962,11 @@ */ for (;;) { leaf = bp->data; - if (INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR_LEAF_MAGIC) { + if (unlikely(INT_GET(leaf->hdr.info.magic, ARCH_CONVERT) != XFS_DIR_LEAF_MAGIC)) { xfs_dir_trace_g_dul("node: not a leaf", dp, uio, leaf); xfs_da_brelse(trans, bp); + XFS_CORRUPTION_ERROR("xfs_dir_node_getdents(1)", + XFS_ERRLEVEL_LOW, mp, leaf); return XFS_ERROR(EFSCORRUPTED); } xfs_dir_trace_g_dul("node: leaf detail", dp, uio, leaf); @@ -988,8 +990,11 @@ XFS_DATA_FORK); if (error) return(error); - if (bp == NULL) + if (unlikely(bp == NULL)) { + XFS_ERROR_REPORT("xfs_dir_node_getdents(2)", + XFS_ERRLEVEL_LOW, mp); return(XFS_ERROR(EFSCORRUPTED)); + } } *eofp = 1; xfs_dir_trace_g_du("node: E-O-F", dp, uio); diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dir2_block.c linux-2.5.65-bk3/fs/xfs/xfs_dir2_block.c --- linux-2.5.65-bk2/fs/xfs/xfs_dir2_block.c Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_dir2_block.c Mon Mar 31 12:41:45 2003 @@ -98,7 +98,10 @@ /* * Check the magic number, corrupted if wrong. */ - if (INT_GET(block->hdr.magic, ARCH_CONVERT) != XFS_DIR2_BLOCK_MAGIC) { + if (unlikely(INT_GET(block->hdr.magic, ARCH_CONVERT) + != XFS_DIR2_BLOCK_MAGIC)) { + XFS_CORRUPTION_ERROR("xfs_dir2_block_addname", + XFS_ERRLEVEL_LOW, mp, block); xfs_da_brelse(tp, bp); return XFS_ERROR(EFSCORRUPTED); } @@ -437,7 +440,6 @@ xfs_mount_t *mp; /* filesystem mount point */ xfs_dir2_put_args_t p; /* arg package for put rtn */ char *ptr; /* current data entry */ - char *savptr; /* saved data entry */ int wantoff; /* starting block offset */ mp = dp->i_mount; @@ -488,8 +490,6 @@ dep = (xfs_dir2_data_entry_t *)ptr; - savptr = ptr; /* In case we need it.. */ - /* * Bump pointer for the next iteration. */ @@ -504,14 +504,8 @@ */ p.namelen = dep->namelen; - /* - * NOTE! Linux "filldir" semantics require that the - * offset "cookie" be for this entry, not the - * next; all the actual shuffling to make it - * "look right" to the user is done in filldir. - */ p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, - savptr - (char *)block); + ptr - (char *)block); #if XFS_BIG_FILESYSTEMS p.ino = INT_GET(dep->inumber, ARCH_CONVERT) + mp->m_inoadd; #else diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dir2_leaf.c linux-2.5.65-bk3/fs/xfs/xfs_dir2_leaf.c --- linux-2.5.65-bk2/fs/xfs/xfs_dir2_leaf.c Mon Mar 17 13:44:05 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_dir2_leaf.c Mon Mar 31 12:41:45 2003 @@ -1059,6 +1059,9 @@ XFS_DIR2_DB_OFF_TO_BYTE(mp, XFS_DIR2_BYTE_TO_DB(mp, curoff), (char *)ptr - (char *)data); + if (ptr >= (char *)data + mp->m_dirblksize) { + continue; + } } } /* @@ -1086,13 +1089,7 @@ length = XFS_DIR2_DATA_ENTSIZE(p.namelen); - /* - * NOTE! Linux "filldir" semantics require that the - * offset "cookie" be for this entry, not the - * next; all the actual shuffling to make it - * "look right" to the user is done in filldir. - */ - p.cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff); + p.cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length); #if XFS_BIG_FILESYSTEMS p.ino = INT_GET(dep->inumber, ARCH_CONVERT) + mp->m_inoadd; diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dir2_node.c linux-2.5.65-bk3/fs/xfs/xfs_dir2_node.c --- linux-2.5.65-bk2/fs/xfs/xfs_dir2_node.c Mon Mar 17 13:43:37 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_dir2_node.c Mon Mar 31 12:41:45 2003 @@ -511,7 +511,9 @@ /* * If it has room, return it. */ - if (INT_GET(free->bests[fi], ARCH_CONVERT) == NULLDATAOFF) { + if (unlikely(INT_GET(free->bests[fi], ARCH_CONVERT) == NULLDATAOFF)) { + XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", + XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } if (INT_GET(free->bests[fi], ARCH_CONVERT) >= length) { @@ -1346,6 +1348,7 @@ int findex; /* freespace entry index */ xfs_dir2_db_t foundbno=0; /* found freespace block no */ int foundindex=0; /* found freespace entry idx */ + int foundhole; /* found hole in freespace */ xfs_dir2_free_t *free=NULL; /* freespace block structure */ xfs_dir2_db_t ifbno; /* initial freespace block no */ xfs_dir2_db_t lastfbno=0; /* highest freespace block no */ @@ -1354,6 +1357,7 @@ xfs_mount_t *mp; /* filesystem mount point */ int needlog; /* need to log data header */ int needscan; /* need to rescan data frees */ + int needfreesp; /* need to allocate freesp blk */ xfs_dir2_data_off_t *tagp; /* data entry tag pointer */ xfs_trans_t *tp; /* transaction pointer */ @@ -1361,6 +1365,7 @@ mp = dp->i_mount; tp = args->trans; length = XFS_DIR2_DATA_ENTSIZE(args->namelen); + foundhole = 0; /* * If we came in with a freespace block that means that lookup * found an entry with our hash value. This is the freespace @@ -1450,11 +1455,12 @@ * to avoid it. */ if ((error = xfs_da_read_buf(tp, dp, - XFS_DIR2_DB_TO_DA(mp, fbno), -1, &fbp, + XFS_DIR2_DB_TO_DA(mp, fbno), -2, &fbp, XFS_DATA_FORK))) { return error; } - if (fbp == NULL) { + if (unlikely(fbp == NULL)) { + foundhole = 1; continue; } free = fbp->data; @@ -1473,7 +1479,7 @@ * one is empty, remember this slot. */ if (foundindex == -1 && - INT_GET(free->bests[findex], ARCH_CONVERT) == NULLDATAOFF) { + INT_GET(free->bests[findex], ARCH_CONVERT) == NULLDATAOFF && !foundhole) { foundindex = findex; foundbno = fbno; } @@ -1487,7 +1493,8 @@ * remember this slot. */ if (foundindex == -1 && - findex < XFS_DIR2_MAX_FREE_BESTS(mp)) { + findex < XFS_DIR2_MAX_FREE_BESTS(mp) && + !foundhole) { foundindex = findex; foundbno = fbno; } @@ -1502,68 +1509,10 @@ } } /* - * If we don't have a data block, and there's no free slot in a - * freeblock, we need to add a new freeblock. - */ - if (dbno == -1 && foundindex == -1) { - /* - * Not allowed to allocate, so return failure. - */ - if (args->justcheck || args->total == 0) { - return XFS_ERROR(ENOSPC); - } - /* - * Add the new freeblock. - */ - if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, - &fbno))) { - return error; - } - /* - * Get a buffer for the new block. - */ - if ((error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, fbno), - -1, &fbp, XFS_DATA_FORK))) { - return error; - } - ASSERT(fbp != NULL); - /* - * Initialize the new block to be empty, and remember - * its first slot as our empty slot. - */ - free = fbp->data; - INT_SET(free->hdr.magic, ARCH_CONVERT, XFS_DIR2_FREE_MAGIC); - INT_SET(free->hdr.firstdb, ARCH_CONVERT, (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * - XFS_DIR2_MAX_FREE_BESTS(mp)); - INT_ZERO(free->hdr.nused, ARCH_CONVERT); - INT_ZERO(free->hdr.nvalid, ARCH_CONVERT); - foundindex = 0; - foundbno = fbno; - } - /* - * If we don't have a data block, and we don't have a freeblock buffer - * in hand (we dropped the one with the free slot in it), - * go read the freeblock again. - */ - if (dbno == -1 && fbp == NULL) { - /* - * We're going to use the empty slot we found before. - */ - findex = foundindex; - fbno = foundbno; - if ((error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, fbno), - -1, &fbp, XFS_DATA_FORK))) { - return error; - } - ASSERT(fbp != NULL); - free = fbp->data; - ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); - } - /* * If we don't have a data block, we need to allocate one and make * the freespace entries refer to it. */ - if (dbno == -1) { + if (unlikely(dbno == -1)) { /* * Not allowed to allocate, return failure. */ @@ -1572,7 +1521,7 @@ * Drop the freespace buffer unless it came from our * caller. */ - if (fblk == NULL || fblk->bp == NULL) + if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) xfs_da_buf_done(fbp); return XFS_ERROR(ENOSPC); } @@ -1586,7 +1535,7 @@ * Drop the freespace buffer unless it came from our * caller. */ - if (fblk == NULL || fblk->bp == NULL) + if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) xfs_da_buf_done(fbp); return error; } @@ -1595,21 +1544,80 @@ * freespace block we have in hand, drop the one we have * and get the right one. */ - if (XFS_DIR2_DB_TO_FDB(mp, dbno) != fbno) { - xfs_da_brelse(tp, fbp); + needfreesp = 0; + if (XFS_DIR2_DB_TO_FDB(mp, dbno) != fbno || fbp == NULL) { + if (fbp) + xfs_da_brelse(tp, fbp); if (fblk && fblk->bp) fblk->bp = NULL; fbno = XFS_DIR2_DB_TO_FDB(mp, dbno); if ((error = xfs_da_read_buf(tp, dp, - XFS_DIR2_DB_TO_DA(mp, fbno), -1, &fbp, + XFS_DIR2_DB_TO_DA(mp, fbno), -2, &fbp, XFS_DATA_FORK))) { xfs_da_buf_done(dbp); return error; } + + /* + * If there wasn't a freespace block, the read will + * return a NULL fbp. Allocate one later. + */ + + if(unlikely( fbp == NULL )) { + needfreesp = 1; + } else { + free = fbp->data; + ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); + } + } + + /* + * If we don't have a data block, and there's no free slot in a + * freeblock, we need to add a new freeblock. + */ + if (unlikely(needfreesp || foundindex == -1)) { + /* + * Add the new freeblock. + */ + if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, + &fbno))) { + return error; + } + + if (XFS_DIR2_DB_TO_FDB(mp, dbno) != fbno) { + cmn_err(CE_ALERT, + "xfs_dir2_node_addname_int: needed block %lld, got %lld\n", + XFS_DIR2_DB_TO_FDB(mp, dbno), fbno); + XFS_ERROR_REPORT("xfs_dir2_node_addname_int", + XFS_ERRLEVEL_LOW, mp); + return XFS_ERROR(EFSCORRUPTED); + } + + /* + * Get a buffer for the new block. + */ + if ((error = xfs_da_get_buf(tp, dp, + XFS_DIR2_DB_TO_DA(mp, fbno), + -1, &fbp, XFS_DATA_FORK))) { + return error; + } ASSERT(fbp != NULL); + + /* + * Initialize the new block to be empty, and remember + * its first slot as our empty slot. + */ free = fbp->data; - ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); + INT_SET(free->hdr.magic, ARCH_CONVERT, XFS_DIR2_FREE_MAGIC); + INT_SET(free->hdr.firstdb, ARCH_CONVERT, + (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * + XFS_DIR2_MAX_FREE_BESTS(mp)); + INT_ZERO(free->hdr.nvalid, ARCH_CONVERT); + INT_ZERO(free->hdr.nused, ARCH_CONVERT); + foundindex = 0; + foundbno = fbno; } + /* * Set the freespace block index from the data block number. */ @@ -1651,16 +1659,17 @@ * If just checking, we succeeded. */ if (args->justcheck) { - if (fblk == NULL || fblk->bp == NULL) + if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) xfs_da_buf_done(fbp); return 0; } /* * Read the data block in. */ - if ((error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, dbno), + if (unlikely( + error = xfs_da_read_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, dbno), -1, &dbp, XFS_DATA_FORK))) { - if (fblk == NULL || fblk->bp == NULL) + if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) xfs_da_buf_done(fbp); return error; } @@ -1715,7 +1724,7 @@ /* * If the caller didn't hand us the freespace block, drop it. */ - if (fblk == NULL || fblk->bp == NULL) + if ((fblk == NULL || fblk->bp == NULL) && fbp != NULL) xfs_da_buf_done(fbp); /* * Return the data block and offset in args, then drop the data block. @@ -1943,10 +1952,18 @@ /* * Read the freespace block. */ - if ((error = xfs_da_read_buf(tp, dp, (xfs_dablk_t)fo, -1, &bp, + if (unlikely(error = xfs_da_read_buf(tp, dp, (xfs_dablk_t)fo, -2, &bp, XFS_DATA_FORK))) { return error; } + + /* + * There can be holes in freespace. If fo is a hole, there's + * nothing to do. + */ + if (bp == NULL) { + return 0; + } free = bp->data; ASSERT(INT_GET(free->hdr.magic, ARCH_CONVERT) == XFS_DIR2_FREE_MAGIC); /* diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dir2_sf.c linux-2.5.65-bk3/fs/xfs/xfs_dir2_sf.c --- linux-2.5.65-bk2/fs/xfs/xfs_dir2_sf.c Mon Mar 17 13:44:17 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_dir2_sf.c Mon Mar 31 12:41:45 2003 @@ -752,14 +752,8 @@ if (dir_offset <= XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, XFS_DIR2_DATA_DOT_OFFSET)) { - /* - * NOTE! Linux "filldir" semantics require that the - * offset "cookie" be for this entry, not the - * next; all the actual shuffling to make it - * "look right" to the user is done in filldir. - */ p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, 0, - XFS_DIR2_DATA_DOT_OFFSET); + XFS_DIR2_DATA_DOTDOT_OFFSET); #if XFS_BIG_FILESYSTEMS p.ino = dp->i_ino + mp->m_inoadd; #else @@ -784,14 +778,8 @@ if (dir_offset <= XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, XFS_DIR2_DATA_DOTDOT_OFFSET)) { - /* - * NOTE! Linux "filldir" semantics require that the - * offset "cookie" be for this entry, not the - * next; all the actual shuffling to make it - * "look right" to the user is done in filldir. - */ p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, - XFS_DIR2_DATA_DOTDOT_OFFSET); + XFS_DIR2_DATA_FIRST_OFFSET); #if XFS_BIG_FILESYSTEMS p.ino = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, &sfp->hdr.parent, ARCH_CONVERT) + mp->m_inoadd; @@ -826,14 +814,9 @@ p.namelen = sfep->namelen; - /* - * NOTE! Linux "filldir" semantics require that the - * offset "cookie" be for this entry, not the - * next; all the actual shuffling to make it - * "look right" to the user is done in filldir. - */ p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, - XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT)); + XFS_DIR2_SF_GET_OFFSET_ARCH(sfep, ARCH_CONVERT) + + XFS_DIR2_DATA_ENTSIZE(p.namelen)); #if XFS_BIG_FILESYSTEMS p.ino = XFS_DIR2_SF_GET_INUMBER_ARCH(sfp, diff -urN linux-2.5.65-bk2/fs/xfs/xfs_dir_leaf.c linux-2.5.65-bk3/fs/xfs/xfs_dir_leaf.c --- linux-2.5.65-bk2/fs/xfs/xfs_dir_leaf.c Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_dir_leaf.c Mon Mar 31 12:41:45 2003 @@ -103,10 +103,11 @@ agblkno != 0 && ioff < (1 << mp->m_sb.sb_inopblog) && XFS_AGINO_TO_INO(mp, agno, agino) == ino; - if (XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, - XFS_RANDOM_DIR_INO_VALIDATE)) { + if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, + XFS_RANDOM_DIR_INO_VALIDATE))) { xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx", (unsigned long long) ino); + XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } return 0; @@ -455,10 +456,13 @@ for (i = 0, sfe = &sf->list[0]; i < INT_GET(sf->hdr.count, ARCH_CONVERT); i++) { - if (((char *)sfe < (char *)sf) || + if (unlikely( + ((char *)sfe < (char *)sf) || ((char *)sfe >= ((char *)sf + dp->i_df.if_bytes)) || - (sfe->namelen >= MAXNAMELEN)) { + (sfe->namelen >= MAXNAMELEN))) { xfs_dir_trace_g_du("sf: corrupted", dp, uio); + XFS_CORRUPTION_ERROR("xfs_dir_shortform_getdents", + XFS_ERRLEVEL_LOW, mp, sfe); kmem_free(sbuf, sbsize); return XFS_ERROR(EFSCORRUPTED); } @@ -1970,9 +1974,12 @@ namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); - if (((char *)namest < (char *)leaf) || + if (unlikely( + ((char *)namest < (char *)leaf) || ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)) || - (entry->namelen >= MAXNAMELEN)) { + (entry->namelen >= MAXNAMELEN))) { + XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(1)", + XFS_ERRLEVEL_LOW, mp, leaf); xfs_dir_trace_g_du("leaf: corrupted", dp, uio); return XFS_ERROR(EFSCORRUPTED); } @@ -2031,9 +2038,12 @@ namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); - if (((char *)namest < (char *)leaf) || + if (unlikely( + ((char *)namest < (char *)leaf) || ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)) || - (entry->namelen >= MAXNAMELEN)) { + (entry->namelen >= MAXNAMELEN))) { + XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(2)", + XFS_ERRLEVEL_LOW, mp, leaf); xfs_dir_trace_g_du("leaf: corrupted", dp, uio); return XFS_ERROR(EFSCORRUPTED); } @@ -2076,11 +2086,14 @@ leaf2 = bp2->data; - if ( (INT_GET(leaf2->hdr.info.magic, ARCH_CONVERT) + if (unlikely( + (INT_GET(leaf2->hdr.info.magic, ARCH_CONVERT) != XFS_DIR_LEAF_MAGIC) || (INT_GET(leaf2->hdr.info.back, ARCH_CONVERT) - != bno)) { /* GROT */ - + != bno))) { /* GROT */ + XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(3)", + XFS_ERRLEVEL_LOW, mp, + leaf2); xfs_da_brelse(dp->i_transp, bp2); return(XFS_ERROR(EFSCORRUPTED)); diff -urN linux-2.5.65-bk2/fs/xfs/xfs_error.c linux-2.5.65-bk3/fs/xfs/xfs_error.c --- linux-2.5.65-bk2/fs/xfs/xfs_error.c Mon Mar 17 13:44:45 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_error.c Mon Mar 31 12:41:45 2003 @@ -238,3 +238,79 @@ xfs_fs_vcmn_err(level, mp, fmt, ap); va_end(ap); } + +void +xfs_stack_trace(void) +{ + dump_stack(); +} + +void +xfs_error_report( + char *tag, + int level, + xfs_mount_t *mp, + char *fname, + int linenum, + inst_t *ra) +{ + if (level <= xfs_error_level) { + if (mp != NULL) { + xfs_cmn_err(XFS_PTAG_ERROR_REPORT, + CE_ALERT, mp, + "XFS internal error %s at line %d of file %s. Caller 0x%x\n", + tag, linenum, fname, ra); + } else { + cmn_err(CE_ALERT, + "XFS internal error %s at line %d of file %s. Caller 0x%x\n", + tag, linenum, fname, ra); + } + + xfs_stack_trace(); + } +} + +void +xfs_hex_dump(void *p, int length) +{ + __uint8_t *uip = (__uint8_t*)p; + int i; + char sbuf[128], *s; + + s = sbuf; + *s = '\0'; + for (i=0; iagi_magicnum, ARCH_CONVERT) == XFS_AGI_MAGIC && XFS_AGI_GOOD_VERSION( INT_GET(agi->agi_versionnum, ARCH_CONVERT)); - if (XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI, - XFS_RANDOM_IALLOC_READ_AGI)) { + if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI, + XFS_RANDOM_IALLOC_READ_AGI))) { + XFS_CORRUPTION_ERROR("xfs_ialloc_read_agi", XFS_ERRLEVEL_LOW, + mp, agi); xfs_trans_brelse(tp, bp); -#ifdef __KERNEL__ /* additional, temporary, debugging code */ - cmn_err(CE_NOTE, - "EFSCORRUPTED returned from file %s line %d", - __FILE__, __LINE__); -#endif return XFS_ERROR(EFSCORRUPTED); } pag = &mp->m_perag[agno]; diff -urN linux-2.5.65-bk2/fs/xfs/xfs_iget.c linux-2.5.65-bk3/fs/xfs/xfs_iget.c --- linux-2.5.65-bk2/fs/xfs/xfs_iget.c Mon Mar 17 13:44:48 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_iget.c Mon Mar 31 12:41:45 2003 @@ -422,7 +422,6 @@ vp = LINVFS_GET_VP(inode); if (inode->i_state & I_NEW) { inode_allocate: - XFS_STATS_INC(xfsstats.vn_alloc); vn_initialize(inode); error = xfs_iget_core(vp, mp, tp, ino, lock_flags, ipp, bno); diff -urN linux-2.5.65-bk2/fs/xfs/xfs_inode.c linux-2.5.65-bk3/fs/xfs/xfs_inode.c --- linux-2.5.65-bk2/fs/xfs/xfs_inode.c Mon Mar 17 13:44:48 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_inode.c Mon Mar 31 12:41:45 2003 @@ -31,6 +31,7 @@ */ #include +#include /* for get_unaligned, put_unaligned */ kmem_zone_t *xfs_ifork_zone; @@ -226,8 +227,9 @@ di_ok = INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC && XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT)); - if (XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, - XFS_RANDOM_ITOBP_INOTOBP)) { + if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, + XFS_RANDOM_ITOBP_INOTOBP))) { + XFS_CORRUPTION_ERROR("xfs_inotobp", XFS_ERRLEVEL_LOW, mp, dip); xfs_trans_brelse(tp, bp); cmn_err(CE_WARN, "xfs_inotobp: XFS_TEST_ERROR() returned an " @@ -369,13 +371,15 @@ (i << mp->m_sb.sb_inodelog)); di_ok = INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC && XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT)); - if (XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, - XFS_RANDOM_ITOBP_INOTOBP)) { + if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, + XFS_RANDOM_ITOBP_INOTOBP))) { #ifdef DEBUG prdev("bad inode magic/vsn daddr 0x%llx #%d (magic=%x)", mp->m_dev, (unsigned long long)imap.im_blkno, i, INT_GET(dip->di_core.di_magic, ARCH_CONVERT)); #endif + XFS_CORRUPTION_ERROR("xfs_itobp", XFS_ERRLEVEL_LOW, + mp, dip); xfs_trans_brelse(tp, bp); return XFS_ERROR(EFSCORRUPTED); } @@ -419,9 +423,10 @@ XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t); error = 0; - if (INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) + + if (unlikely( + INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) + INT_GET(dip->di_core.di_anextents, ARCH_CONVERT) > - INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT)) { + INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT))) { xfs_fs_cmn_err(CE_WARN, ip->i_mount, "corrupt dinode %Lu, extent total = %d, nblocks = %Lu." " Unmount and run xfs_repair.", @@ -430,15 +435,19 @@ + INT_GET(dip->di_core.di_anextents, ARCH_CONVERT)), (unsigned long long) INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT)); + XFS_CORRUPTION_ERROR("xfs_iformat(1)", XFS_ERRLEVEL_LOW, + ip->i_mount, dip); return XFS_ERROR(EFSCORRUPTED); } - if (INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT) > ip->i_mount->m_sb.sb_inodesize) { + if (unlikely(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT) > ip->i_mount->m_sb.sb_inodesize)) { xfs_fs_cmn_err(CE_WARN, ip->i_mount, "corrupt dinode %Lu, forkoff = 0x%x." " Unmount and run xfs_repair.", (unsigned long long)ip->i_ino, (int)(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT))); + XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW, + ip->i_mount, dip); return XFS_ERROR(EFSCORRUPTED); } @@ -447,8 +456,11 @@ case IFCHR: case IFBLK: case IFSOCK: - if (INT_GET(dip->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_DEV) + if (unlikely(INT_GET(dip->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_DEV)) { + XFS_CORRUPTION_ERROR("xfs_iformat(3)", XFS_ERRLEVEL_LOW, + ip->i_mount, dip); return XFS_ERROR(EFSCORRUPTED); + } ip->i_d.di_size = 0; ip->i_df.if_u2.if_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT); break; @@ -461,24 +473,26 @@ /* * no local regular files yet */ - if ((INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & IFMT) == IFREG) { + if (unlikely((INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & IFMT) == IFREG)) { xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode " - "(local format for regular file) %Lu. " - "Unmount and run xfs_repair.", + "corrupt inode (local format for regular file) %Lu. Unmount and run xfs_repair.", (unsigned long long) ip->i_ino); + XFS_CORRUPTION_ERROR("xfs_iformat(4)", + XFS_ERRLEVEL_LOW, + ip->i_mount, dip); return XFS_ERROR(EFSCORRUPTED); } di_size = INT_GET(dip->di_core.di_size, ARCH_CONVERT); - if (di_size > - XFS_DFORK_DSIZE_ARCH(dip, ip->i_mount, ARCH_CONVERT)) { + if (unlikely(di_size > + XFS_DFORK_DSIZE_ARCH(dip, ip->i_mount, ARCH_CONVERT))) { xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu " - "(bad size %Ld for local inode). " - "Unmount and run xfs_repair.", + "corrupt inode %Lu (bad size %Ld for local inode). Unmount and run xfs_repair.", (unsigned long long) ip->i_ino, (long long) di_size); + XFS_CORRUPTION_ERROR("xfs_iformat(5)", + XFS_ERRLEVEL_LOW, + ip->i_mount, dip); return XFS_ERROR(EFSCORRUPTED); } @@ -492,11 +506,14 @@ error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK); break; default: + XFS_ERROR_REPORT("xfs_iformat(6)", XFS_ERRLEVEL_LOW, + ip->i_mount); return XFS_ERROR(EFSCORRUPTED); } break; default: + XFS_ERROR_REPORT("xfs_iformat(7)", XFS_ERRLEVEL_LOW, ip->i_mount); return XFS_ERROR(EFSCORRUPTED); } if (error) { @@ -557,13 +574,13 @@ * is wrong and we just bail out rather than crash in * kmem_alloc() or memcpy() below. */ - if (size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT)) { + if (unlikely(size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT))) { xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu " - "(bad size %d for local fork, size = %d). " - "Unmount and run xfs_repair.", + "corrupt inode %Lu (bad size %d for local fork, size = %d). Unmount and run xfs_repair.", (unsigned long long) ip->i_ino, size, XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT)); + XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW, + ip->i_mount, dip); return XFS_ERROR(EFSCORRUPTED); } ifp = XFS_IFORK_PTR(ip, whichfork); @@ -619,11 +636,12 @@ * is wrong and we just bail out rather than crash in * kmem_alloc() or memcpy() below. */ - if (size < 0 || size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT)) { + if (unlikely(size < 0 || size > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT))) { xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu ((a)extents = %d). " - "Unmount and run xfs_repair.", + "corrupt inode %Lu ((a)extents = %d). Unmount and run xfs_repair.", (unsigned long long) ip->i_ino, nex); + XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW, + ip->i_mount, dip); return XFS_ERROR(EFSCORRUPTED); } @@ -647,8 +665,10 @@ ep = ifp->if_u1.if_extents; #if ARCH_CONVERT != ARCH_NOCONVERT for (i = 0; i < nex; i++, ep++, dp++) { - ep->l0 = INT_GET(dp->l0, ARCH_CONVERT); - ep->l1 = INT_GET(dp->l1, ARCH_CONVERT); + ep->l0 = INT_GET(get_unaligned((u64*)&dp->l0), + ARCH_CONVERT); + ep->l1 = INT_GET(get_unaligned((u64*)&dp->l1), + ARCH_CONVERT); } #else memcpy(ep, dp, size); @@ -657,9 +677,13 @@ whichfork); if (whichfork != XFS_DATA_FORK || XFS_EXTFMT_INODE(ip) == XFS_EXTFMT_NOSTATE) - if (xfs_check_nostate_extents( - ifp->if_u1.if_extents, nex)) + if (unlikely(xfs_check_nostate_extents( + ifp->if_u1.if_extents, nex))) { + XFS_ERROR_REPORT("xfs_iformat_extents(2)", + XFS_ERRLEVEL_LOW, + ip->i_mount); return XFS_ERROR(EFSCORRUPTED); + } } ifp->if_flags |= XFS_IFEXTENTS; return 0; @@ -697,14 +721,15 @@ * or the number of extents is greater than the number of * blocks. */ - if (XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max + if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max || XFS_BMDR_SPACE_CALC(nrecs) > XFS_DFORK_SIZE_ARCH(dip, ip->i_mount, whichfork, ARCH_CONVERT) - || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks) { + || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) { xfs_fs_cmn_err(CE_WARN, ip->i_mount, - "corrupt inode %Lu (btree). " - "Unmount and run xfs_repair.", + "corrupt inode %Lu (btree). Unmount and run xfs_repair.", (unsigned long long) ip->i_ino); + XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW, + ip->i_mount); return XFS_ERROR(EFSCORRUPTED); } @@ -975,8 +1000,11 @@ xfs_ifork_t *ifp; size_t size; - if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) + if (unlikely(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) { + XFS_ERROR_REPORT("xfs_iread_extents", XFS_ERRLEVEL_LOW, + ip->i_mount); return XFS_ERROR(EFSCORRUPTED); + } size = XFS_IFORK_NEXTENTS(ip, whichfork) * (uint)sizeof(xfs_bmbt_rec_t); ifp = XFS_IFORK_PTR(ip, whichfork); /* @@ -1817,8 +1845,9 @@ agi_ok = INT_GET(agi->agi_magicnum, ARCH_CONVERT) == XFS_AGI_MAGIC && XFS_AGI_GOOD_VERSION(INT_GET(agi->agi_versionnum, ARCH_CONVERT)); - if (XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IUNLINK, - XFS_RANDOM_IUNLINK)) { + if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IUNLINK, + XFS_RANDOM_IUNLINK))) { + XFS_CORRUPTION_ERROR("xfs_iunlink", XFS_ERRLEVEL_LOW, mp, agi); xfs_trans_brelse(tp, agibp); return XFS_ERROR(EFSCORRUPTED); } @@ -1919,8 +1948,10 @@ agi_ok = INT_GET(agi->agi_magicnum, ARCH_CONVERT) == XFS_AGI_MAGIC && XFS_AGI_GOOD_VERSION(INT_GET(agi->agi_versionnum, ARCH_CONVERT)); - if (XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IUNLINK_REMOVE, - XFS_RANDOM_IUNLINK_REMOVE)) { + if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IUNLINK_REMOVE, + XFS_RANDOM_IUNLINK_REMOVE))) { + XFS_CORRUPTION_ERROR("xfs_iunlink_remove", XFS_ERRLEVEL_LOW, + mp, agi); xfs_trans_brelse(tp, agibp); cmn_err(CE_WARN, "xfs_iunlink_remove: XFS_TEST_ERROR() returned an error on %s. Returning EFSCORRUPTED.", @@ -2676,8 +2707,10 @@ #if ARCH_CONVERT != ARCH_NOCONVERT /* Translate to on disk format */ - dest_ep->l0 = INT_GET(ep->l0, ARCH_CONVERT); - dest_ep->l1 = INT_GET(ep->l1, ARCH_CONVERT); + put_unaligned(INT_GET(ep->l0, ARCH_CONVERT), + (u64*)&dest_ep->l0); + put_unaligned(INT_GET(ep->l1, ARCH_CONVERT), + (u64*)&dest_ep->l1); #else *dest_ep = *ep; #endif @@ -2745,7 +2778,9 @@ memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes); } if (whichfork == XFS_DATA_FORK) { - if (XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip)) { + if (unlikely(XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip))) { + XFS_ERROR_REPORT("xfs_iflush_fork", + XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } } diff -urN linux-2.5.65-bk2/fs/xfs/xfs_log.c linux-2.5.65-bk3/fs/xfs/xfs_log.c --- linux-2.5.65-bk2/fs/xfs/xfs_log.c Mon Mar 17 13:44:51 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_log.c Mon Mar 31 12:41:45 2003 @@ -62,10 +62,6 @@ /* local state machine functions */ STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int); STATIC void xlog_state_do_callback(xlog_t *log,int aborted, xlog_in_core_t *iclog); -static inline void xlog_state_finish_copy(xlog_t *log, - xlog_in_core_t *iclog, - int first_write, - int bytes); STATIC int xlog_state_get_iclog_space(xlog_t *log, int len, xlog_in_core_t **iclog, @@ -876,7 +872,7 @@ * We may be holding the log iclog lock upon entering this routine. */ xfs_lsn_t -xlog_assign_tail_lsn(xfs_mount_t *mp, xlog_in_core_t *iclog) +xlog_assign_tail_lsn(xfs_mount_t *mp) { xfs_lsn_t tail_lsn; SPLDECL(s); @@ -888,8 +884,6 @@ log->l_tail_lsn = tail_lsn; else tail_lsn = log->l_tail_lsn = log->l_last_sync_lsn; - if (iclog) - INT_SET(iclog->ic_header.h_tail_lsn, ARCH_CONVERT, tail_lsn); GRANT_UNLOCK(log, s); return tail_lsn; @@ -1402,7 +1396,7 @@ { xfs_caddr_t dptr; /* pointer to byte sized element */ xfs_buf_t *bp; - int i; + int i, ops; uint roundup; uint count; /* byte count of bwrite */ int split = 0; /* split write into two regions */ @@ -1439,7 +1433,12 @@ log->l_roundoff += iclog->ic_roundoff; xlog_pack_data(log, iclog); /* put cycle number in every block */ - INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset); /* real byte length */ + + /* real byte length */ + INT_SET(iclog->ic_header.h_len, ARCH_CONVERT, iclog->ic_offset); + /* put ops count in correct order */ + ops = iclog->ic_header.h_num_logops; + INT_SET(iclog->ic_header.h_num_logops, ARCH_CONVERT, ops); bp = iclog->ic_bp; ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1); @@ -1596,6 +1595,28 @@ kmem_free(log, sizeof(xlog_t)); } /* xlog_unalloc_log */ +/* + * Update counters atomically now that memcpy is done. + */ +/* ARGSUSED */ +static inline void +xlog_state_finish_copy(xlog_t *log, + xlog_in_core_t *iclog, + int record_cnt, + int copy_bytes) +{ + SPLDECL(s); + + s = LOG_LOCK(log); + + iclog->ic_header.h_num_logops += record_cnt; + iclog->ic_offset += copy_bytes; + + LOG_UNLOCK(log, s); +} /* xlog_state_finish_copy */ + + + /* * Write some region out to in-core log @@ -1663,6 +1684,7 @@ int contwr; /* continued write of in-core log? */ int firstwr = 0; /* first write of transaction */ int error; + int record_cnt = 0, data_cnt = 0; partial_copy_len = partial_copy = 0; @@ -1725,7 +1747,8 @@ logop_head->oh_flags = XLOG_START_TRANS; INT_ZERO(logop_head->oh_res2, ARCH_CONVERT); ticket->t_flags &= ~XLOG_TIC_INITED; /* clear bit */ - firstwr++; /* increment log ops below */ + firstwr = 1; /* increment log ops below */ + record_cnt++; start_rec_copy = sizeof(xlog_op_header_t); xlog_write_adv_cnt(ptr, len, log_offset, start_rec_copy); @@ -1793,10 +1816,13 @@ /* make copy_len total bytes copied, including headers */ copy_len += start_rec_copy + sizeof(xlog_op_header_t); - xlog_state_finish_copy(log, iclog, firstwr, (contwr? copy_len : 0)); + record_cnt++; + data_cnt += contwr ? copy_len : 0; firstwr = 0; if (partial_copy) { /* copied partial region */ /* already marked WANT_SYNC by xlog_state_get_iclog_space */ + xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); + record_cnt = data_cnt = 0; if ((error = xlog_state_release_iclog(log, iclog))) return (error); break; /* don't increment index */ @@ -1805,6 +1831,8 @@ partial_copy_len = partial_copy = 0; if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) { + xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); + record_cnt = data_cnt = 0; xlog_state_want_sync(log, iclog); if (commit_iclog) { ASSERT(flags & XLOG_COMMIT_TRANS); @@ -1821,6 +1849,7 @@ } /* for (index = 0; index < nentries; ) */ ASSERT(len == 0); + xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); if (commit_iclog) { ASSERT(flags & XLOG_COMMIT_TRANS); *commit_iclog = iclog; @@ -2208,30 +2237,6 @@ /* - * Update counters atomically now that memcpy is done. - */ -/* ARGSUSED */ -static inline void -xlog_state_finish_copy(xlog_t *log, - xlog_in_core_t *iclog, - int first_write, - int copy_bytes) -{ - SPLDECL(s); - - s = LOG_LOCK(log); - - if (first_write) - INT_MOD(iclog->ic_header.h_num_logops, ARCH_CONVERT, +1); - INT_MOD(iclog->ic_header.h_num_logops, ARCH_CONVERT, +1); - iclog->ic_offset += copy_bytes; - - LOG_UNLOCK(log, s); -} /* xlog_state_finish_copy */ - - - -/* * If the head of the in-core log ring is not (ACTIVE or DIRTY), then we must * sleep. The flush semaphore is set to the number of in-core buffers and * decremented around disk syncing. Therefore, if all buffers are syncing, @@ -2722,7 +2727,7 @@ SPLDECL(s); int sync = 0; /* do we sync? */ - xlog_assign_tail_lsn(log->l_mp, 0); + xlog_assign_tail_lsn(log->l_mp); s = LOG_LOCK(log); @@ -3594,7 +3599,10 @@ iclog = log->l_iclog; do { - if (INT_GET(iclog->ic_header.h_num_logops, ARCH_CONVERT)) + /* endianness does not matter here, zero is zero in + * any language. + */ + if (iclog->ic_header.h_num_logops) return(0); iclog = iclog->ic_next; } while (iclog != log->l_iclog); diff -urN linux-2.5.65-bk2/fs/xfs/xfs_log_priv.h linux-2.5.65-bk3/fs/xfs/xfs_log_priv.h --- linux-2.5.65-bk2/fs/xfs/xfs_log_priv.h Mon Mar 17 13:43:40 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_log_priv.h Mon Mar 31 12:41:45 2003 @@ -536,8 +536,7 @@ /* common routines */ -extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp, - xlog_in_core_t *iclog); +extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp); extern int xlog_find_head(xlog_t *log, xfs_daddr_t *head_blk); extern int xlog_find_tail(xlog_t *log, xfs_daddr_t *head_blk, diff -urN linux-2.5.65-bk2/fs/xfs/xfs_log_recover.c linux-2.5.65-bk3/fs/xfs/xfs_log_recover.c --- linux-2.5.65-bk2/fs/xfs/xfs_log_recover.c Mon Mar 17 13:44:07 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_log_recover.c Mon Mar 31 12:41:45 2003 @@ -166,17 +166,21 @@ * a dirty log created in IRIX. */ - if (INT_GET(head->h_fmt, ARCH_CONVERT) != XLOG_FMT) { + if (unlikely(INT_GET(head->h_fmt, ARCH_CONVERT) != XLOG_FMT)) { xlog_warn("XFS: dirty log written in incompatible format - can't recover"); #ifdef DEBUG xlog_header_check_dump(mp, head); #endif + XFS_ERROR_REPORT("xlog_header_check_recover(1)", + XFS_ERRLEVEL_HIGH, mp); return XFS_ERROR(EFSCORRUPTED); - } else if (!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid)) { + } else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) { xlog_warn("XFS: dirty log entry has mismatched uuid - can't recover"); #ifdef DEBUG xlog_header_check_dump(mp, head); #endif + XFS_ERROR_REPORT("xlog_header_check_recover(2)", + XFS_ERRLEVEL_HIGH, mp); return XFS_ERROR(EFSCORRUPTED); } @@ -202,11 +206,13 @@ xlog_warn("XFS: nil uuid in log - IRIX style log"); - } else if (!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid)) { + } else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) { xlog_warn("XFS: log has mismatched uuid - can't recover"); #ifdef DEBUG xlog_header_check_dump(mp, head); #endif + XFS_ERROR_REPORT("xlog_header_check_mount", + XFS_ERRLEVEL_HIGH, mp); return XFS_ERROR(EFSCORRUPTED); } @@ -1113,8 +1119,11 @@ * the distance from the beginning of the log to the * tail. */ - if (head_block < tail_block || head_block >= log->l_logBBsize) + if (unlikely(head_block < tail_block || head_block >= log->l_logBBsize)) { + XFS_ERROR_REPORT("xlog_clear_stale_blocks(1)", + XFS_ERRLEVEL_LOW, log->l_mp); return XFS_ERROR(EFSCORRUPTED); + } tail_distance = tail_block + (log->l_logBBsize - head_block); } else { /* @@ -1122,8 +1131,11 @@ * so the distance from the head to the tail is just * the tail block minus the head block. */ - if (head_block >= tail_block || head_cycle != (tail_cycle + 1)) + if (unlikely(head_block >= tail_block || head_cycle != (tail_cycle + 1))){ + XFS_ERROR_REPORT("xlog_clear_stale_blocks(2)", + XFS_ERRLEVEL_LOW, log->l_mp); return XFS_ERROR(EFSCORRUPTED); + } tail_distance = tail_block - head_block; } @@ -1732,10 +1744,12 @@ logged_nextp = (xfs_agino_t *) ((char *)(item->ri_buf[item_index].i_addr) + (next_unlinked_offset - reg_buf_offset)); - if (*logged_nextp == 0) { + if (unlikely(*logged_nextp == 0)) { xfs_fs_cmn_err(CE_ALERT, mp, "bad inode buffer log record (ptr = 0x%p, bp = 0x%p). XFS trying to replay bad (0) inode di_next_unlinked field", item, bp); + XFS_ERROR_REPORT("xlog_recover_do_inode_buf", + XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } @@ -1933,6 +1947,8 @@ xfs_fs_cmn_err(CE_ALERT, log->l_mp, "xfs_log_recover: unknown buffer type 0x%x, dev 0x%x", buf_f->blf_type, log->l_dev); + XFS_ERROR_REPORT("xlog_recover_do_buffer_trans", + XFS_ERRLEVEL_LOW, log->l_mp); return XFS_ERROR(EFSCORRUPTED); } @@ -2038,7 +2054,6 @@ imap.im_blkno = 0; xfs_imap(log->l_mp, 0, ino, &imap, 0); } - bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len, XFS_BUF_LOCK); if (XFS_BUF_ISERROR(bp)) { @@ -2049,7 +2064,6 @@ return error; } error = 0; - xfs_inobp_check(mp, bp); ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); dip = (xfs_dinode_t *)xfs_buf_offset(bp, imap.im_boffset); @@ -2057,34 +2071,42 @@ * Make sure the place we're flushing out to really looks * like an inode! */ - if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) { + if (unlikely(INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC)) { xfs_buf_relse(bp); xfs_fs_cmn_err(CE_ALERT, mp, "xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld", dip, bp, ino); + XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)", + XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr); - if (dicp->di_magic != XFS_DINODE_MAGIC) { + if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { xfs_buf_relse(bp); xfs_fs_cmn_err(CE_ALERT, mp, "xfs_inode_recover: Bad inode log record, rec ptr 0x%p, ino %Ld", item, ino); + XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)", + XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } - if ((dicp->di_mode & IFMT) == IFREG) { + if (unlikely((dicp->di_mode & IFMT) == IFREG)) { if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && (dicp->di_format != XFS_DINODE_FMT_BTREE)) { + XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(3)", + XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); xfs_fs_cmn_err(CE_ALERT, mp, "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", item, dip, bp, ino); return XFS_ERROR(EFSCORRUPTED); } - } else if ((dicp->di_mode & IFMT) == IFDIR) { + } else if (unlikely((dicp->di_mode & IFMT) == IFDIR)) { if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && (dicp->di_format != XFS_DINODE_FMT_BTREE) && (dicp->di_format != XFS_DINODE_FMT_LOCAL)) { + XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(4)", + XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); xfs_fs_cmn_err(CE_ALERT, mp, "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", @@ -2092,7 +2114,9 @@ return XFS_ERROR(EFSCORRUPTED); } } - if (dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks) { + if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ + XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(5)", + XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); xfs_fs_cmn_err(CE_ALERT, mp, "xfs_inode_recover: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld", @@ -2101,14 +2125,18 @@ dicp->di_nblocks); return XFS_ERROR(EFSCORRUPTED); } - if (dicp->di_forkoff > mp->m_sb.sb_inodesize) { + if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { + XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)", + XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); xfs_fs_cmn_err(CE_ALERT, mp, "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", item, dip, bp, ino, dicp->di_forkoff); return XFS_ERROR(EFSCORRUPTED); } - if (item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t)) { + if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) { + XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)", + XFS_ERRLEVEL_LOW, mp, dicp); xfs_buf_relse(bp); xfs_fs_cmn_err(CE_ALERT, mp, "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p", @@ -2207,14 +2235,6 @@ write_inode_buffer: -#if 0 - /* - * Can't do this if the transaction didn't log the current - * contents, e.g. rmdir. - */ - XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip); -#endif - xfs_inobp_check(mp, bp); if (ITEM_TYPE(item) == XFS_LI_INODE) { ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL || XFS_BUF_FSPRIVATE(bp, xfs_mount_t *) == mp); @@ -3238,10 +3258,12 @@ ASSERT(BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT) <= INT_MAX)); bblks = (int) BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT)); /* blocks in data section */ - if ((INT_GET(rhead->h_magicno, ARCH_CONVERT) != XLOG_HEADER_MAGIC_NUM) || + if (unlikely((INT_GET(rhead->h_magicno, ARCH_CONVERT) != XLOG_HEADER_MAGIC_NUM) || (BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT) > INT_MAX)) || (bblks <= 0) || - (blk_no > log->l_logBBsize)) { + (blk_no > log->l_logBBsize))) { + XFS_ERROR_REPORT("xlog_do_recovery_pass(1)", + XFS_ERRLEVEL_LOW, log->l_mp); error = EFSCORRUPTED; goto bread_err2; } @@ -3307,9 +3329,11 @@ ASSERT(bblks > 0); blk_no += hblks; /* successfully read header */ - if ((INT_GET(rhead->h_magicno, ARCH_CONVERT) != XLOG_HEADER_MAGIC_NUM) || + if (unlikely((INT_GET(rhead->h_magicno, ARCH_CONVERT) != XLOG_HEADER_MAGIC_NUM) || (BTOBB(INT_GET(rhead->h_len, ARCH_CONVERT) > INT_MAX)) || - (bblks <= 0)) { + (bblks <= 0))) { + XFS_ERROR_REPORT("xlog_do_recovery_pass(2)", + XFS_ERRLEVEL_LOW, log->l_mp); error = EFSCORRUPTED; goto bread_err2; } @@ -3472,7 +3496,7 @@ * or iunlinks they will have some entries in the AIL; so we look at * the AIL to determine how to set the tail_lsn. */ - xlog_assign_tail_lsn(log->l_mp, NULL); + xlog_assign_tail_lsn(log->l_mp); /* * Now that we've finished replaying all buffer and inode diff -urN linux-2.5.65-bk2/fs/xfs/xfs_macros.h linux-2.5.65-bk3/fs/xfs/xfs_macros.h --- linux-2.5.65-bk2/fs/xfs/xfs_macros.h Mon Mar 17 13:43:42 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_macros.h Mon Mar 31 12:41:45 2003 @@ -33,13 +33,12 @@ #define __XFS_MACROS_H__ /* - * Set for debug kernels and simulation, and 32-bit kernels, - * but not for standalone. These replacements save space. + * Set for debug kernels and simulation + * These replacements save space. * Used in xfs_macros.c. */ #define XFS_WANT_SPACE_C \ - (!defined(_STANDALONE) && \ - (defined(DEBUG) || (defined(_KERNEL)))) + (!defined(_STANDALONE) && defined(DEBUG)) /* * Set for debug simulation and kernel builds, but not for standalone. diff -urN linux-2.5.65-bk2/fs/xfs/xfs_mount.c linux-2.5.65-bk3/fs/xfs/xfs_mount.c --- linux-2.5.65-bk2/fs/xfs/xfs_mount.c Mon Mar 17 13:44:02 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_mount.c Mon Mar 31 12:41:45 2003 @@ -205,13 +205,17 @@ return XFS_ERROR(EWRONGFS); } - if (sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp) { + if (unlikely(sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { cmn_err(CE_WARN, "XFS: filesystem is marked as having an external log; specify logdev on the\nmount command line."); + XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(1)", + XFS_ERRLEVEL_HIGH, mp, sbp); return XFS_ERROR(EFSCORRUPTED); } - if (sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp) { + if (unlikely(sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { cmn_err(CE_WARN, "XFS: filesystem is marked as having an internal log; don't specify logdev on\nthe mount command line."); + XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(2)", + XFS_ERRLEVEL_HIGH, mp, sbp); return XFS_ERROR(EFSCORRUPTED); } @@ -219,7 +223,8 @@ * More sanity checking. These were stolen directly from * xfs_repair. */ - if (sbp->sb_agcount <= 0 || + if (unlikely( + sbp->sb_agcount <= 0 || sbp->sb_sectsize < XFS_MIN_SECTORSIZE || sbp->sb_sectsize > XFS_MAX_SECTORSIZE || sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG || @@ -232,20 +237,25 @@ sbp->sb_inodesize > XFS_DINODE_MAX_SIZE || (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || - sbp->sb_imax_pct > 100) { + sbp->sb_imax_pct > 100)) { cmn_err(CE_WARN, "XFS: SB sanity check 1 failed"); + XFS_CORRUPTION_ERROR("xfs_mount_validate_sb(3)", + XFS_ERRLEVEL_LOW, mp, sbp); return XFS_ERROR(EFSCORRUPTED); } /* * Sanity check AG count, size fields against data size field */ - if (sbp->sb_dblocks == 0 || + if (unlikely( + sbp->sb_dblocks == 0 || sbp->sb_dblocks > (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks || sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) * - sbp->sb_agblocks + XFS_MIN_AG_BLOCKS) { + sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) { cmn_err(CE_WARN, "XFS: SB sanity check 2 failed"); + XFS_ERROR_REPORT("xfs_mount_validate_sb(4)", + XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } @@ -257,8 +267,10 @@ } #endif - if (sbp->sb_inprogress) { + if (unlikely(sbp->sb_inprogress)) { cmn_err(CE_WARN, "XFS: file system busy"); + XFS_ERROR_REPORT("xfs_mount_validate_sb(5)", + XFS_ERRLEVEL_LOW, mp); return XFS_ERROR(EFSCORRUPTED); } @@ -636,7 +648,6 @@ error = XFS_ERROR(EINVAL); goto error1; } - mp->m_dalign = mp->m_swidth = 0; } else { /* * Convert the stripe unit and width to FSBs. @@ -915,7 +926,7 @@ /* * log's mount-time initialization. Perform 1st part recovery if needed */ - if (sbp->sb_logblocks > 0) { /* check for volume case */ + if (likely(sbp->sb_logblocks > 0)) { /* check for volume case */ error = xfs_log_mount(mp, mp->m_logdev_targp->pbr_dev, XFS_FSB_TO_DADDR(mp, sbp->sb_logstart), XFS_FSB_TO_BB(mp, sbp->sb_logblocks)); @@ -925,6 +936,7 @@ } } else { /* No log has been defined */ cmn_err(CE_WARN, "XFS: no log defined"); + XFS_ERROR_REPORT("xfs_mountfs_int(1)", XFS_ERRLEVEL_LOW, mp); error = XFS_ERROR(EFSCORRUPTED); goto error2; } @@ -941,7 +953,7 @@ ASSERT(rip != NULL); rvp = XFS_ITOV(rip); - if ((rip->i_d.di_mode & IFMT) != IFDIR) { + if (unlikely((rip->i_d.di_mode & IFMT) != IFDIR)) { cmn_err(CE_WARN, "XFS: corrupted root inode"); VMAP(rvp, vmap); prdev("Root inode %llu is not a directory", @@ -949,6 +961,8 @@ xfs_iunlock(rip, XFS_ILOCK_EXCL); VN_RELE(rvp); vn_purge(rvp, &vmap); + XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, + mp); error = XFS_ERROR(EFSCORRUPTED); goto error3; } diff -urN linux-2.5.65-bk2/fs/xfs/xfs_qm.c linux-2.5.65-bk3/fs/xfs/xfs_qm.c --- linux-2.5.65-bk2/fs/xfs/xfs_qm.c Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_qm.c Mon Mar 31 12:41:45 2003 @@ -444,16 +444,22 @@ xfs_iflock(uqp); error = xfs_iflush(uqp, XFS_IFLUSH_SYNC); xfs_iunlock(uqp, XFS_ILOCK_EXCL); - if (error == EFSCORRUPTED) + if (unlikely(error == EFSCORRUPTED)) { + XFS_ERROR_REPORT("xfs_qm_unmount_quotas(1)", + XFS_ERRLEVEL_LOW, mp); goto out; + } } if ((gqp = mp->m_quotainfo->qi_gquotaip) != NULL) { xfs_ilock(gqp, XFS_ILOCK_EXCL); xfs_iflock(gqp); error = xfs_iflush(gqp, XFS_IFLUSH_SYNC); xfs_iunlock(gqp, XFS_ILOCK_EXCL); - if (error == EFSCORRUPTED) + if (unlikely(error == EFSCORRUPTED)) { + XFS_ERROR_REPORT("xfs_qm_unmount_quotas(2)", + XFS_ERRLEVEL_LOW, mp); goto out; + } } } if (uqp) { diff -urN linux-2.5.65-bk2/fs/xfs/xfs_rename.c linux-2.5.65-bk3/fs/xfs/xfs_rename.c --- linux-2.5.65-bk2/fs/xfs/xfs_rename.c Mon Mar 17 13:44:06 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_rename.c Mon Mar 31 12:41:45 2003 @@ -467,9 +467,6 @@ } target_ip_dropped = 1; - /* Do this test while we still hold the locks */ - target_link_zero = (target_ip)->i_d.di_nlink==0; - if (src_is_directory) { /* * Drop the link from the old "." entry. @@ -481,6 +478,9 @@ } } + /* Do this test while we still hold the locks */ + target_link_zero = (target_ip)->i_d.di_nlink==0; + } /* target_ip != NULL */ /* diff -urN linux-2.5.65-bk2/fs/xfs/xfs_types.h linux-2.5.65-bk3/fs/xfs/xfs_types.h --- linux-2.5.65-bk2/fs/xfs/xfs_types.h Mon Mar 17 13:43:49 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_types.h Mon Mar 31 12:41:45 2003 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -34,8 +34,6 @@ #ifdef __KERNEL__ -#include - /* * POSIX Extensions */ @@ -56,9 +54,7 @@ typedef signed long long int __int64_t; typedef unsigned long long int __uint64_t; -typedef enum { B_FALSE, B_TRUE } boolean_t; - - +typedef enum { B_FALSE,B_TRUE } boolean_t; typedef __int64_t prid_t; /* project ID */ typedef __uint32_t inst_t; /* an instruction */ @@ -68,12 +64,6 @@ typedef char * xfs_caddr_t; /* type */ typedef __u32 xfs_dev_t; -typedef struct timespec timespec_t; - -typedef struct { - unsigned char __u_bits[16]; -} uuid_t; - /* __psint_t is the same size as a pointer */ #if (BITS_PER_LONG == 32) typedef __int32_t __psint_t; @@ -185,6 +175,18 @@ */ #define MAXNAMELEN 256 +typedef struct xfs_dirent { /* data from readdir() */ + xfs_ino_t d_ino; /* inode number of entry */ + xfs_off_t d_off; /* offset of disk directory entry */ + unsigned short d_reclen; /* length of this record */ + char d_name[1]; /* name of file */ +} xfs_dirent_t; + +#define DIRENTBASESIZE (((xfs_dirent_t *)0)->d_name - (char *)0) +#define DIRENTSIZE(namelen) \ + ((DIRENTBASESIZE + (namelen) + \ + sizeof(xfs_off_t)) & ~(sizeof(xfs_off_t) - 1)) + typedef enum { XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi } xfs_lookup_t; diff -urN linux-2.5.65-bk2/fs/xfs/xfs_vfsops.c linux-2.5.65-bk3/fs/xfs/xfs_vfsops.c --- linux-2.5.65-bk2/fs/xfs/xfs_vfsops.c Mon Mar 17 13:43:45 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_vfsops.c Mon Mar 31 12:41:45 2003 @@ -1582,7 +1582,6 @@ vfsops_t xfs_vfsops = { .vfs_mount = xfs_mount, - .vfs_dounmount = fs_dounmount, .vfs_unmount = xfs_unmount, .vfs_root = xfs_root, .vfs_statvfs = xfs_statvfs, diff -urN linux-2.5.65-bk2/fs/xfs/xfs_vnodeops.c linux-2.5.65-bk3/fs/xfs/xfs_vnodeops.c --- linux-2.5.65-bk2/fs/xfs/xfs_vnodeops.c Mon Mar 17 13:44:51 2003 +++ linux-2.5.65-bk3/fs/xfs/xfs_vnodeops.c Mon Mar 31 12:41:45 2003 @@ -72,7 +72,8 @@ */ if (vp->v_type == VDIR && ip->i_d.di_nextents > 0) { mode = xfs_ilock_map_shared(ip); - (void)xfs_da_reada_buf(NULL, ip, 0, XFS_DATA_FORK); + if (ip->i_d.di_nextents > 0) + (void)xfs_da_reada_buf(NULL, ip, 0, XFS_DATA_FORK); xfs_iunlock(ip, mode); } return 0; @@ -125,7 +126,8 @@ * Quick exit for non-stat callers */ if ((vap->va_mask & - ~(XFS_AT_SIZE|XFS_AT_FSID|XFS_AT_NODEID|XFS_AT_NLINK)) == 0) { + ~(XFS_AT_SIZE|XFS_AT_FSID|XFS_AT_NODEID| + XFS_AT_NLINK|XFS_AT_BLKSIZE)) == 0) { if (!(flags & ATTR_LAZY)) xfs_iunlock(ip, XFS_ILOCK_SHARED); return 0; @@ -1919,6 +1921,7 @@ xfs_bmap_free_t free_list; xfs_fsblock_t first_block; boolean_t dp_joined_to_trans; + int dm_event_sent = 0; uint cancel_flags; int committed; xfs_prid_t prid; @@ -1943,15 +1946,16 @@ dm_di_mode, 0, 0); if (error) return error; + dm_event_sent = 1; } - /* Return through std_return after this point. */ - mp = dp->i_mount; if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); + /* Return through std_return after this point. */ + udqp = gdqp = NULL; if (vap->va_mask & XFS_AT_PROJID) prid = (xfs_prid_t)vap->va_projid; @@ -2111,12 +2115,12 @@ /* Fallthrough to std_return with error = 0 */ std_return: - if ((error != 0) && + if ( (*vpp || (error != 0 && dm_event_sent != 0)) && DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp), DM_EVENT_POSTCREATE)) { (void) dm_send_namesp_event(DM_EVENT_POSTCREATE, dir_bdp, DM_RIGHT_NULL, - vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops), + *vpp ? vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops):NULL, DM_RIGHT_NULL, name, NULL, dm_di_mode, error, 0); } @@ -2838,6 +2842,7 @@ vnode_t *dir_vp; boolean_t dp_joined_to_trans; boolean_t created = B_FALSE; + int dm_event_sent = 0; xfs_prid_t prid; xfs_dquot_t *udqp, *gdqp; uint resblks; @@ -2864,6 +2869,7 @@ dm_di_mode, 0, 0); if (error) return error; + dm_event_sent = 1; } /* Return through std_return after this point. */ @@ -3026,7 +3032,7 @@ * xfs_trans_commit. */ std_return: - if ( (created || (error != 0)) && + if ( (created || (error != 0 && dm_event_sent != 0)) && DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp), DM_EVENT_POSTCREATE)) { (void) dm_send_namesp_event(DM_EVENT_POSTCREATE, diff -urN linux-2.5.65-bk2/fs/xfs/xfsidbg.c linux-2.5.65-bk3/fs/xfs/xfsidbg.c --- linux-2.5.65-bk2/fs/xfs/xfsidbg.c Mon Mar 17 13:44:38 2003 +++ linux-2.5.65-bk3/fs/xfs/xfsidbg.c Mon Mar 31 12:41:45 2003 @@ -4162,8 +4162,6 @@ } if (!(ip->i_flags & XFS_IQUIESCE)) { kdb_printf("ip 0x%p not quiesced\n", ip); - } else if (!BHV_IS_WRITE_LOCKED(VN_BHV_HEAD(XFS_ITOV(ip)))) { - kdb_printf("ip 0x%p not write locked\n", ip); } ip = ip->i_mnext; } while (ip != mp->m_inodes); diff -urN linux-2.5.65-bk2/include/asm-alpha/core_cia.h linux-2.5.65-bk3/include/asm-alpha/core_cia.h --- linux-2.5.65-bk2/include/asm-alpha/core_cia.h Mon Mar 17 13:44:07 2003 +++ linux-2.5.65-bk3/include/asm-alpha/core_cia.h Mon Mar 31 12:41:45 2003 @@ -293,7 +293,8 @@ #ifdef __KERNEL__ #ifndef __EXTERN_INLINE -#define __EXTERN_INLINE static inline +/* Do not touch, this should *NOT* be static inline */ +#define __EXTERN_INLINE extern inline #define __IO_EXTERN_INLINE #endif diff -urN linux-2.5.65-bk2/include/asm-i386/mach-default/pci-functions.h linux-2.5.65-bk3/include/asm-i386/mach-default/pci-functions.h --- linux-2.5.65-bk2/include/asm-i386/mach-default/pci-functions.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/include/asm-i386/mach-default/pci-functions.h Mon Mar 31 12:41:45 2003 @@ -0,0 +1,19 @@ +/* + * PCI BIOS function numbering for conventional PCI BIOS + * systems + */ + +#define PCIBIOS_PCI_FUNCTION_ID 0xb1XX +#define PCIBIOS_PCI_BIOS_PRESENT 0xb101 +#define PCIBIOS_FIND_PCI_DEVICE 0xb102 +#define PCIBIOS_FIND_PCI_CLASS_CODE 0xb103 +#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106 +#define PCIBIOS_READ_CONFIG_BYTE 0xb108 +#define PCIBIOS_READ_CONFIG_WORD 0xb109 +#define PCIBIOS_READ_CONFIG_DWORD 0xb10a +#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b +#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c +#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d +#define PCIBIOS_GET_ROUTING_OPTIONS 0xb10e +#define PCIBIOS_SET_PCI_HW_INT 0xb10f + diff -urN linux-2.5.65-bk2/include/asm-i386/mach-pc9800/pci-functions.h linux-2.5.65-bk3/include/asm-i386/mach-pc9800/pci-functions.h --- linux-2.5.65-bk2/include/asm-i386/mach-pc9800/pci-functions.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/include/asm-i386/mach-pc9800/pci-functions.h Mon Mar 31 12:41:45 2003 @@ -0,0 +1,20 @@ +/* + * PCI BIOS function codes for the PC9800. Different to + * standard PC systems + */ + +/* Note: PC-9800 confirms PCI 2.1 on only few models */ + +#define PCIBIOS_PCI_FUNCTION_ID 0xccXX +#define PCIBIOS_PCI_BIOS_PRESENT 0xcc81 +#define PCIBIOS_FIND_PCI_DEVICE 0xcc82 +#define PCIBIOS_FIND_PCI_CLASS_CODE 0xcc83 +/* PCIBIOS_GENERATE_SPECIAL_CYCLE 0xcc86 (not supported by bios) */ +#define PCIBIOS_READ_CONFIG_BYTE 0xcc88 +#define PCIBIOS_READ_CONFIG_WORD 0xcc89 +#define PCIBIOS_READ_CONFIG_DWORD 0xcc8a +#define PCIBIOS_WRITE_CONFIG_BYTE 0xcc8b +#define PCIBIOS_WRITE_CONFIG_WORD 0xcc8c +#define PCIBIOS_WRITE_CONFIG_DWORD 0xcc8d +#define PCIBIOS_GET_ROUTING_OPTIONS 0xcc8e /* PCI 2.1 only */ +#define PCIBIOS_SET_PCI_HW_INT 0xcc8f /* PCI 2.1 only */ diff -urN linux-2.5.65-bk2/include/asm-i386/mach-pc9800/setup_arch_post.h linux-2.5.65-bk3/include/asm-i386/mach-pc9800/setup_arch_post.h --- linux-2.5.65-bk2/include/asm-i386/mach-pc9800/setup_arch_post.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/include/asm-i386/mach-pc9800/setup_arch_post.h Mon Mar 31 12:41:45 2003 @@ -0,0 +1,29 @@ +/** + * machine_specific_memory_setup - Hook for machine specific memory setup. + * + * Description: + * This is included late in kernel/setup.c so that it can make + * use of all of the static functions. + **/ + +static inline char * __init machine_specific_memory_setup(void) +{ + char *who; + unsigned long low_mem_size, lower_high, higher_high; + + + who = "BIOS (common area)"; + + low_mem_size = ((*(unsigned char *)__va(PC9800SCA_BIOS_FLAG) & 7) + 1) << 17; + add_memory_region(0, low_mem_size, 1); + lower_high = (__u32) *(__u8 *) bus_to_virt(PC9800SCA_EXPMMSZ) << 17; + higher_high = (__u32) *(__u16 *) bus_to_virt(PC9800SCA_MMSZ16M) << 20; + if (lower_high != 0x00f00000UL) { + add_memory_region(HIGH_MEMORY, lower_high, 1); + add_memory_region(0x01000000UL, higher_high, 1); + } + else + add_memory_region(HIGH_MEMORY, lower_high + higher_high, 1); + + return who; +} diff -urN linux-2.5.65-bk2/include/asm-i386/mach-pc9800/setup_arch_pre.h linux-2.5.65-bk3/include/asm-i386/mach-pc9800/setup_arch_pre.h --- linux-2.5.65-bk2/include/asm-i386/mach-pc9800/setup_arch_pre.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/include/asm-i386/mach-pc9800/setup_arch_pre.h Mon Mar 31 12:41:45 2003 @@ -0,0 +1,36 @@ +/* Hook to call BIOS initialisation function */ + +/* no action for generic */ + +#define ARCH_SETUP arch_setup_pc9800(); + +#include +#include +#include +#include + +int CLOCK_TICK_RATE; +extern unsigned long tick_usec; /* ACTHZ period (usec) */ +extern unsigned long tick_nsec; /* USER_HZ period (nsec) */ +unsigned char pc9800_misc_flags; +/* (bit 0) 1:High Address Video ram exists 0:otherwise */ + +#ifdef CONFIG_SMP +#define MPC_TABLE_SIZE 512 +#define MPC_TABLE ((char *) (PARAM+0x400)) +char mpc_table[MPC_TABLE_SIZE]; +#endif + +static inline void arch_setup_pc9800(void) +{ + CLOCK_TICK_RATE = PC9800_8MHz_P() ? 1996800 : 2457600; + printk(KERN_DEBUG "CLOCK_TICK_RATE = %d\n", CLOCK_TICK_RATE); + tick_usec = TICK_USEC; /* ACTHZ period (usec) */ + tick_nsec = TICK_NSEC(TICK_USEC); /* USER_HZ period (nsec) */ + + pc9800_misc_flags = PC9800_MISC_FLAGS; +#ifdef CONFIG_SMP + if ((*(u32 *)(MPC_TABLE)) == 0x504d4350) + memcpy(mpc_table, MPC_TABLE, *(u16 *)(MPC_TABLE + 4)); +#endif /* CONFIG_SMP */ +} diff -urN linux-2.5.65-bk2/include/asm-i386/pc9800_sca.h linux-2.5.65-bk3/include/asm-i386/pc9800_sca.h --- linux-2.5.65-bk2/include/asm-i386/pc9800_sca.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/include/asm-i386/pc9800_sca.h Mon Mar 31 12:41:45 2003 @@ -0,0 +1,25 @@ +/* + * System-common area definitions for NEC PC-9800 series + * + * Copyright (C) 1999 TAKAI Kousuke , + * Kyoto University Microcomputer Club. + */ + +#ifndef _ASM_I386_PC9800SCA_H_ +#define _ASM_I386_PC9800SCA_H_ + +#define PC9800SCA_EXPMMSZ (0x0401) /* B */ +#define PC9800SCA_SCSI_PARAMS (0x0460) /* 8 * 4B */ +#define PC9800SCA_DISK_EQUIPS (0x0482) /* B */ +#define PC9800SCA_XROM_ID (0x04C0) /* 52B */ +#define PC9800SCA_BIOS_FLAG (0x0501) /* B */ +#define PC9800SCA_MMSZ16M (0x0594) /* W */ + +/* PC-9821 have additional system common area in their BIOS-ROM segment. */ + +#define PC9821SCA__BASE (0xF8E8 << 4) +#define PC9821SCA_ROM_ID (PC9821SCA__BASE + 0x00) +#define PC9821SCA_ROM_FLAG4 (PC9821SCA__BASE + 0x05) +#define PC9821SCA_RSFLAGS (PC9821SCA__BASE + 0x11) /* B */ + +#endif /* !_ASM_I386_PC9800SCA_H_ */ diff -urN linux-2.5.65-bk2/include/asm-i386/system.h linux-2.5.65-bk3/include/asm-i386/system.h --- linux-2.5.65-bk2/include/asm-i386/system.h Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/include/asm-i386/system.h Mon Mar 31 12:41:45 2003 @@ -407,5 +407,6 @@ #define BROKEN_ACPI_Sx 0x0001 #define BROKEN_INIT_AFTER_S1 0x0002 +#define BROKEN_PNP_BIOS 0x0004 #endif diff -urN linux-2.5.65-bk2/include/asm-i386/timex.h linux-2.5.65-bk3/include/asm-i386/timex.h --- linux-2.5.65-bk2/include/asm-i386/timex.h Mon Mar 17 13:43:50 2003 +++ linux-2.5.65-bk3/include/asm-i386/timex.h Mon Mar 31 12:41:45 2003 @@ -9,11 +9,15 @@ #include #include +#ifdef CONFIG_X86_PC9800 + extern int CLOCK_TICK_RATE; +#else #ifdef CONFIG_MELAN # define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */ #else # define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ #endif +#endif #define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */ #define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \ diff -urN linux-2.5.65-bk2/include/asm-i386/upd4990a.h linux-2.5.65-bk3/include/asm-i386/upd4990a.h --- linux-2.5.65-bk2/include/asm-i386/upd4990a.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/include/asm-i386/upd4990a.h Mon Mar 31 12:41:45 2003 @@ -0,0 +1,52 @@ +/* + * Architecture dependent definitions + * for NEC uPD4990A serial I/O real-time clock. + * + * Copyright 2001 TAKAI Kousuke + * Kyoto University Microcomputer Club (KMC). + * + * References: + * uPD4990A serial I/O real-time clock users' manual (Japanese) + * No. S12828JJ4V0UM00 (4th revision), NEC Corporation, 1999. + */ + +#ifndef _ASM_I386_uPD4990A_H +#define _ASM_I386_uPD4990A_H + +#include + +#define UPD4990A_IO (0x0020) +#define UPD4990A_IO_DATAOUT (0x0033) + +#define UPD4990A_OUTPUT_DATA_CLK(data, clk) \ + outb((((data) & 1) << 5) | (((clk) & 1) << 4) \ + | UPD4990A_PAR_SERIAL_MODE, UPD4990A_IO) + +#define UPD4990A_OUTPUT_CLK(clk) UPD4990A_OUTPUT_DATA_CLK(0, (clk)) + +#define UPD4990A_OUTPUT_STROBE(stb) \ + outb(((stb) << 3) | UPD4990A_PAR_SERIAL_MODE, UPD4990A_IO) + +/* + * Note: udelay() is *not* usable for UPD4990A_DELAY because + * the Linux kernel reads uPD4990A to set up system clock + * before calibrating delay... + */ +#define UPD4990A_DELAY(usec) \ + do { \ + if (__builtin_constant_p((usec)) && (usec) < 5) \ + __asm__ (".rept %c1\n\toutb %%al,%0\n\t.endr" \ + : : "N" (0x5F), \ + "i" (((usec) * 10 + 5) / 6)); \ + else { \ + int _count = ((usec) * 10 + 5) / 6; \ + __asm__ volatile ("1: outb %%al,%1\n\tloop 1b" \ + : "=c" (_count) \ + : "N" (0x5F), "0" (_count)); \ + } \ + } while (0) + +/* Caller should ignore all bits except bit0 */ +#define UPD4990A_READ_DATA() inb(UPD4990A_IO_DATAOUT) + +#endif diff -urN linux-2.5.65-bk2/include/asm-s390x/bitops.h linux-2.5.65-bk3/include/asm-s390x/bitops.h --- linux-2.5.65-bk2/include/asm-s390x/bitops.h Mon Mar 17 13:44:45 2003 +++ linux-2.5.65-bk3/include/asm-s390x/bitops.h Mon Mar 31 12:41:46 2003 @@ -55,7 +55,7 @@ #ifdef CONFIG_SMP /* - * SMP save set_bit routine based on compare and swap (CS) + * SMP safe set_bit routine based on compare and swap (CS) */ static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr) { @@ -80,7 +80,7 @@ } /* - * SMP save clear_bit routine based on compare and swap (CS) + * SMP safe clear_bit routine based on compare and swap (CS) */ static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr) { @@ -105,7 +105,7 @@ } /* - * SMP save change_bit routine based on compare and swap (CS) + * SMP safe change_bit routine based on compare and swap (CS) */ static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr) { @@ -130,7 +130,7 @@ } /* - * SMP save test_and_set_bit routine based on compare and swap (CS) + * SMP safe test_and_set_bit routine based on compare and swap (CS) */ static inline int test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr) @@ -157,7 +157,7 @@ } /* - * SMP save test_and_clear_bit routine based on compare and swap (CS) + * SMP safe test_and_clear_bit routine based on compare and swap (CS) */ static inline int test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr) @@ -184,7 +184,7 @@ } /* - * SMP save test_and_change_bit routine based on compare and swap (CS) + * SMP safe test_and_change_bit routine based on compare and swap (CS) */ static inline int test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr) diff -urN linux-2.5.65-bk2/include/linux/buffer_head.h linux-2.5.65-bk3/include/linux/buffer_head.h --- linux-2.5.65-bk2/include/linux/buffer_head.h Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/include/linux/buffer_head.h Mon Mar 31 12:41:46 2003 @@ -137,6 +137,7 @@ void create_empty_buffers(struct page *, unsigned long, unsigned long b_state); void end_buffer_io_sync(struct buffer_head *bh, int uptodate); +void end_buffer_async_write(struct buffer_head *bh, int uptodate); /* Things to do with buffers at mapping->private_list */ void buffer_insert_list(spinlock_t *lock, diff -urN linux-2.5.65-bk2/include/linux/devfs_fs_kernel.h linux-2.5.65-bk3/include/linux/devfs_fs_kernel.h --- linux-2.5.65-bk2/include/linux/devfs_fs_kernel.h Mon Mar 17 13:44:22 2003 +++ linux-2.5.65-bk3/include/linux/devfs_fs_kernel.h Mon Mar 31 12:41:46 2003 @@ -13,7 +13,6 @@ #define DEVFS_FL_NONE 0x000 /* This helps to make code more readable */ -#define DEVFS_FL_REMOVABLE 0x008 /* This is a removable media device */ #define DEVFS_FL_WAIT 0x010 /* Wait for devfsd to finish */ #define DEVFS_FL_CURRENT_OWNER 0x020 /* Set initial ownership to current */ #define DEVFS_FL_DEFAULT DEVFS_FL_NONE @@ -37,7 +36,6 @@ #define UNIQUE_NUMBERSPACE_INITIALISER {SPIN_LOCK_UNLOCKED, 0, 0, 0, NULL} -extern void devfs_put (devfs_handle_t de); extern devfs_handle_t devfs_register (devfs_handle_t dir, const char *name, unsigned int flags, unsigned int major, unsigned int minor, @@ -66,10 +64,6 @@ #define UNIQUE_NUMBERSPACE_INITIALISER {0} -static inline void devfs_put (devfs_handle_t de) -{ - return; -} static inline devfs_handle_t devfs_register (devfs_handle_t dir, const char *name, unsigned int flags, diff -urN linux-2.5.65-bk2/include/linux/i2o.h linux-2.5.65-bk3/include/linux/i2o.h --- linux-2.5.65-bk2/include/linux/i2o.h Mon Mar 17 13:43:47 2003 +++ linux-2.5.65-bk3/include/linux/i2o.h Mon Mar 31 12:41:46 2003 @@ -23,7 +23,7 @@ #include /* How many different OSM's are we allowing */ -#define MAX_I2O_MODULES 64 +#define MAX_I2O_MODULES 4 /* How many OSMs can register themselves for device status updates? */ #define I2O_MAX_MANAGERS 4 @@ -76,10 +76,16 @@ }; /* - * Resource data for each PCI I2O controller + * Each I2O controller has one of these objects */ -struct i2o_pci +struct i2o_controller { + char name[16]; + int unit; + int type; + int enabled; + + struct pci_dev *pdev; /* PCI device */ int irq; int short_req:1; /* Use small block sizes */ int dpt:1; /* Don't quiesce */ @@ -88,25 +94,6 @@ int mtrr_reg0; int mtrr_reg1; #endif -}; - -/* - * Transport types supported by I2O stack - */ -#define I2O_TYPE_PCI 0x01 /* PCI I2O controller */ - - -/* - * Each I2O controller has one of these objects - */ -struct i2o_controller -{ - struct pci_dev *pdev; /* PCI device */ - - char name[16]; - int unit; - int type; - int enabled; struct notifier_block *event_notifer; /* Events */ atomic_t users; @@ -143,22 +130,6 @@ struct proc_dir_entry *proc_entry; /* /proc dir */ - union { /* Bus information */ - struct i2o_pci pci; - } bus; - - /* Bus specific destructor */ - void (*destructor)(struct i2o_controller *); - - /* Bus specific attach/detach */ - int (*bind)(struct i2o_controller *, struct i2o_device *); - - /* Bus specific initiator */ - int (*unbind)(struct i2o_controller *, struct i2o_device *); - - /* Bus specific enable/disable */ - void (*bus_enable)(struct i2o_controller *); - void (*bus_disable)(struct i2o_controller *); void *page_frame; /* Message buffers */ dma_addr_t page_frame_map; /* Cache map */ diff -urN linux-2.5.65-bk2/include/linux/ide.h linux-2.5.65-bk3/include/linux/ide.h --- linux-2.5.65-bk2/include/linux/ide.h Mon Mar 31 12:41:37 2003 +++ linux-2.5.65-bk3/include/linux/ide.h Mon Mar 31 12:41:46 2003 @@ -280,9 +280,6 @@ return ((hwif)->chipset == chipset) ? 1 : 0; \ } -#define IDE_DEBUG(lineno) \ - printk("%s,%s,line=%d\n", __FILE__, __FUNCTION__, (lineno)) - /* * Check for an interrupt and acknowledge the interrupt status */ @@ -302,7 +299,8 @@ ide_qd65xx, ide_umc8672, ide_ht6560b, ide_pdc4030, ide_rz1000, ide_trm290, ide_cmd646, ide_cy82c693, ide_4drives, - ide_pmac, ide_etrax100, ide_acorn + ide_pmac, ide_etrax100, ide_acorn, + ide_pc9800 } hwif_chipset_t; /* @@ -728,6 +726,7 @@ unsigned present : 1; /* drive is physically present */ unsigned dead : 1; /* device ejected hint */ + unsigned id_read : 1; /* 1=id read from disk 0 = synthetic */ unsigned noprobe : 1; /* from: hdx=noprobe */ unsigned removable : 1; /* 1 if need to do check_media_change */ unsigned is_flash : 1; /* 1 if probed as flash */ @@ -847,7 +846,7 @@ #define task_rq_offset(rq) \ (((rq)->nr_sectors - (rq)->current_nr_sectors) * SECTOR_SIZE) -extern inline void *ide_map_buffer(struct request *rq, unsigned long *flags) +static inline void *ide_map_buffer(struct request *rq, unsigned long *flags) { /* * fs request @@ -861,7 +860,7 @@ return rq->buffer + task_rq_offset(rq); } -extern inline void ide_unmap_buffer(struct request *rq, char *buffer, unsigned long *flags) +static inline void ide_unmap_buffer(struct request *rq, char *buffer, unsigned long *flags) { if (rq->bio) bio_kunmap_irq(buffer, flags); @@ -975,7 +974,7 @@ ide_startstop_t (*ide_dma_queued_start)(ide_drive_t *drive); void (*OUTB)(u8 addr, unsigned long port); - void (*OUTBSYNC)(u8 addr, unsigned long port); + void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port); void (*OUTW)(u16 addr, unsigned long port); void (*OUTL)(u32 addr, unsigned long port); void (*OUTSW)(unsigned long port, void *addr, u32 count); @@ -1181,6 +1180,7 @@ int (*end_request)(ide_drive_t *, int, int); u8 (*sense)(ide_drive_t *, const char *, u8); ide_startstop_t (*error)(ide_drive_t *, const char *, u8); + ide_startstop_t (*abort)(ide_drive_t *, const char *); int (*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long); void (*pre_reset)(ide_drive_t *); unsigned long (*capacity)(ide_drive_t *); @@ -1280,6 +1280,13 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat); /* + * Abort a running command on the controller triggering the abort + * from a host side, non error situation + * (drive, msg) + */ +extern ide_startstop_t ide_abort(ide_drive_t *, const char *); + +/* * Issue a simple drive command * The drive must be selected beforehand. * @@ -1327,12 +1334,6 @@ extern ide_startstop_t ide_do_reset (ide_drive_t *); /* - * Re-Start an operation for an IDE interface. - * The caller should return immediately after invoking this. - */ -extern int restart_request (ide_drive_t *, struct request *); - -/* * This function is intended to be used prior to invoking ide_do_drive_cmd(). */ extern void ide_init_drive_cmd (struct request *rq); @@ -1727,6 +1728,19 @@ extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate); extern spinlock_t ide_lock; +extern struct semaphore ide_cfg_sem; +/* + * Structure locking: + * + * ide_cfg_sem and ide_lock together protect changes to + * ide_hwif_t->{next,hwgroup} + * ide_drive_t->next + * + * ide_hwgroup_t->busy: ide_lock + * ide_hwgroup_t->hwif: ide_lock + * ide_hwif_t->mate: constant, no locking + * ide_drive_t->hwif: constant, no locking + */ #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable(); } while (0) diff -urN linux-2.5.65-bk2/include/linux/module.h linux-2.5.65-bk3/include/linux/module.h --- linux-2.5.65-bk2/include/linux/module.h Mon Mar 17 13:44:38 2003 +++ linux-2.5.65-bk3/include/linux/module.h Mon Mar 31 12:41:46 2003 @@ -69,8 +69,6 @@ __attribute__ ((unused, alias(__stringify(name)))) #define THIS_MODULE (&__this_module) -#define MOD_INC_USE_COUNT _MOD_INC_USE_COUNT(THIS_MODULE) -#define MOD_DEC_USE_COUNT __MOD_DEC_USE_COUNT(THIS_MODULE) /* * The following license idents are currently accepted as indicating free @@ -107,8 +105,6 @@ #define MODULE_ALIAS(alias) #define MODULE_GENERIC_TABLE(gtype,name) #define THIS_MODULE ((struct module *)0) -#define MOD_INC_USE_COUNT do { } while (0) -#define MOD_DEC_USE_COUNT do { } while (0) #define MODULE_LICENSE(license) #endif @@ -418,20 +414,6 @@ #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x) /* BELOW HERE ALL THESE ARE OBSOLETE AND WILL VANISH */ -static inline void __deprecated __MOD_INC_USE_COUNT(struct module *module) -{ - __unsafe(module); - /* - * Yes, we ignore the retval here, that's why it's deprecated. - */ - try_module_get(module); -} - -static inline void __deprecated __MOD_DEC_USE_COUNT(struct module *module) -{ - module_put(module); -} - #define SET_MODULE_OWNER(dev) ((dev)->owner = THIS_MODULE) struct obsolete_modparm { @@ -445,14 +427,7 @@ struct obsolete_modparm __parm_##var __attribute__((section("__obsparm"))) = \ { __stringify(var), type }; -#else -#define MODULE_PARM(var,type) -#endif - -/* People do this inside their init routines, when the module isn't - "live" yet. They should no longer be doing that, but - meanwhile... */ -static inline void __deprecated _MOD_INC_USE_COUNT(struct module *module) +static inline void __deprecated MOD_INC_USE_COUNT(struct module *module) { __unsafe(module); @@ -460,9 +435,23 @@ local_inc(&module->ref[get_cpu()].count); put_cpu(); #else - try_module_get(module); + (void)try_module_get(module); #endif } + +static inline void __deprecated MOD_DEC_USE_COUNT(struct module *module) +{ + module_put(module); +} + +#define MOD_INC_USE_COUNT MOD_INC_USE_COUNT(THIS_MODULE) +#define MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT(THIS_MODULE) +#else +#define MODULE_PARM(var,type) +#define MOD_INC_USE_COUNT do { } while (0) +#define MOD_DEC_USE_COUNT do { } while (0) +#endif + #define __MODULE_STRING(x) __stringify(x) /* diff -urN linux-2.5.65-bk2/include/linux/pci_ids.h linux-2.5.65-bk3/include/linux/pci_ids.h --- linux-2.5.65-bk2/include/linux/pci_ids.h Mon Mar 17 13:44:04 2003 +++ linux-2.5.65-bk3/include/linux/pci_ids.h Mon Mar 31 12:41:46 2003 @@ -144,6 +144,7 @@ #define PCI_DEVICE_ID_COMPAQ_NETEL100I 0xb011 #define PCI_DEVICE_ID_COMPAQ_CISS 0xb060 #define PCI_DEVICE_ID_COMPAQ_CISSB 0xb178 +#define PCI_DEVICE_ID_COMPAQ_CISSC 0x46 #define PCI_DEVICE_ID_COMPAQ_THUNDER 0xf130 #define PCI_DEVICE_ID_COMPAQ_NETFLEX3B 0xf150 @@ -1832,8 +1833,8 @@ #define PCI_DEVICE_ID_INTEL_82801E_0 0x2450 #define PCI_DEVICE_ID_INTEL_82801E_2 0x2452 #define PCI_DEVICE_ID_INTEL_82801E_3 0x2453 -#define PCI_DEVICE_ID_INTEL_82801E_9 0x245b -#define PCI_DEVICE_ID_INTEL_82801E_11 PCI_DEVICE_ID_INTEL_82801E_9 +#define PCI_DEVICE_ID_INTEL_82801E_9 0x2459 +#define PCI_DEVICE_ID_INTEL_82801E_11 0x245b #define PCI_DEVICE_ID_INTEL_82801E_13 0x245d #define PCI_DEVICE_ID_INTEL_82801E_14 0x245e #define PCI_DEVICE_ID_INTEL_82801CA_0 0x2480 @@ -1853,10 +1854,20 @@ #define PCI_DEVICE_ID_INTEL_82801DB_5 0x24c5 #define PCI_DEVICE_ID_INTEL_82801DB_6 0x24c6 #define PCI_DEVICE_ID_INTEL_82801DB_7 0x24c7 -#define PCI_DEVICE_ID_INTEL_82801DB_9 0x24cb -#define PCI_DEVICE_ID_INTEL_82801DB_11 PCI_DEVICE_ID_INTEL_82801DB_9 +#define PCI_DEVICE_ID_INTEL_82801DB_9 0x24c9 +#define PCI_DEVICE_ID_INTEL_82801DB_10 0x24ca +#define PCI_DEVICE_ID_INTEL_82801DB_11 0x24cb #define PCI_DEVICE_ID_INTEL_82801DB_12 0x24cc #define PCI_DEVICE_ID_INTEL_82801DB_13 0x24cd +#define PCI_DEVICE_ID_INTEL_82801EB_0 0x24d0 +#define PCI_DEVICE_ID_INTEL_82801EB_2 0x24d2 +#define PCI_DEVICE_ID_INTEL_82801EB_3 0x24d3 +#define PCI_DEVICE_ID_INTEL_82801EB_4 0x24d4 +#define PCI_DEVICE_ID_INTEL_82801EB_5 0x24d5 +#define PCI_DEVICE_ID_INTEL_82801EB_6 0x24d6 +#define PCI_DEVICE_ID_INTEL_82801EB_7 0x24d7 +#define PCI_DEVICE_ID_INTEL_82801EB_11 0x24db +#define PCI_DEVICE_ID_INTEL_82801EB_13 0x24dd #define PCI_DEVICE_ID_INTEL_82820_HB 0x2500 #define PCI_DEVICE_ID_INTEL_82820_UP_HB 0x2501 #define PCI_DEVICE_ID_INTEL_82850_HB 0x2530 diff -urN linux-2.5.65-bk2/include/linux/serial_core.h linux-2.5.65-bk3/include/linux/serial_core.h --- linux-2.5.65-bk2/include/linux/serial_core.h Mon Mar 17 13:43:41 2003 +++ linux-2.5.65-bk3/include/linux/serial_core.h Mon Mar 31 12:41:47 2003 @@ -59,6 +59,14 @@ /* NEC v850. */ #define PORT_NB85E_UART 40 +/* NEC PC-9800 */ +#define PORT_8251_PC98 41 +#define PORT_19K_PC98 42 +#define PORT_FIFO_PC98 43 +#define PORT_VFAST_PC98 44 +#define PORT_PC9861 45 +#define PORT_PC9801_101 46 + #ifdef __KERNEL__ diff -urN linux-2.5.65-bk2/include/linux/upd4990a.h linux-2.5.65-bk3/include/linux/upd4990a.h --- linux-2.5.65-bk2/include/linux/upd4990a.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/include/linux/upd4990a.h Mon Mar 31 12:41:47 2003 @@ -0,0 +1,140 @@ +/* + * Constant and architecture independent procedures + * for NEC uPD4990A serial I/O real-time clock. + * + * Copyright 2001 TAKAI Kousuke + * Kyoto University Microcomputer Club (KMC). + * + * References: + * uPD4990A serial I/O real-time clock users' manual (Japanese) + * No. S12828JJ4V0UM00 (4th revision), NEC Corporation, 1999. + */ + +#ifndef _LINUX_uPD4990A_H +#define _LINUX_uPD4990A_H + +#include + +#include + +/* Serial commands (4 bits) */ +#define UPD4990A_REGISTER_HOLD (0x0) +#define UPD4990A_REGISTER_SHIFT (0x1) +#define UPD4990A_TIME_SET_AND_COUNTER_HOLD (0x2) +#define UPD4990A_TIME_READ (0x3) +#define UPD4990A_TP_64HZ (0x4) +#define UPD4990A_TP_256HZ (0x5) +#define UPD4990A_TP_2048HZ (0x6) +#define UPD4990A_TP_4096HZ (0x7) +#define UPD4990A_TP_1S (0x8) +#define UPD4990A_TP_10S (0x9) +#define UPD4990A_TP_30S (0xA) +#define UPD4990A_TP_60S (0xB) +#define UPD4990A_INTERRUPT_RESET (0xC) +#define UPD4990A_INTERRUPT_TIMER_START (0xD) +#define UPD4990A_INTERRUPT_TIMER_STOP (0xE) +#define UPD4990A_TEST_MODE_SET (0xF) + +/* Parallel commands (3 bits) + 0-6 are same with serial commands. */ +#define UPD4990A_PAR_SERIAL_MODE 7 + +#ifndef UPD4990A_DELAY +# include +# define UPD4990A_DELAY(usec) udelay((usec)) +#endif +#ifndef UPD4990A_OUTPUT_DATA +# define UPD4990A_OUTPUT_DATA(bit) \ + do { \ + UPD4990A_OUTPUT_DATA_CLK((bit), 0); \ + UPD4990A_DELAY(1); /* t-DSU */ \ + UPD4990A_OUTPUT_DATA_CLK((bit), 1); \ + UPD4990A_DELAY(1); /* t-DHLD */ \ + } while (0) +#endif + +static __inline__ void upd4990a_serial_command(int command) +{ + UPD4990A_OUTPUT_DATA(command >> 0); + UPD4990A_OUTPUT_DATA(command >> 1); + UPD4990A_OUTPUT_DATA(command >> 2); + UPD4990A_OUTPUT_DATA(command >> 3); + UPD4990A_DELAY(1); /* t-HLD */ + UPD4990A_OUTPUT_STROBE(1); + UPD4990A_DELAY(1); /* t-STB & t-d1 */ + UPD4990A_OUTPUT_STROBE(0); + /* 19 microseconds extra delay is needed + iff previous mode is TIME READ command */ +} + +struct upd4990a_raw_data { + u8 sec; /* BCD */ + u8 min; /* BCD */ + u8 hour; /* BCD */ + u8 mday; /* BCD */ +#if defined __LITTLE_ENDIAN_BITFIELD + unsigned wday :4; /* 0-6 */ + unsigned mon :4; /* 1-based */ +#elif defined __BIG_ENDIAN_BITFIELD + unsigned mon :4; /* 1-based */ + unsigned wday :4; /* 0-6 */ +#else +# error Unknown bitfield endian! +#endif + u8 year; /* BCD */ +}; + +static __inline__ void upd4990a_get_time(struct upd4990a_raw_data *buf, + int leave_register_hold) +{ + int byte; + + upd4990a_serial_command(UPD4990A_TIME_READ); + upd4990a_serial_command(UPD4990A_REGISTER_SHIFT); + UPD4990A_DELAY(19); /* t-d2 - t-d1 */ + + for (byte = 0; byte < 6; byte++) { + u8 tmp; + int bit; + + for (tmp = 0, bit = 0; bit < 8; bit++) { + tmp = (tmp | (UPD4990A_READ_DATA() << 8)) >> 1; + UPD4990A_OUTPUT_CLK(1); + UPD4990A_DELAY(1); + UPD4990A_OUTPUT_CLK(0); + UPD4990A_DELAY(1); + } + ((u8 *) buf)[byte] = tmp; + } + + /* The uPD4990A users' manual says that we should issue `Register + Hold' command after each data retrieval, or next `Time Read' + command may not work correctly. */ + if (!leave_register_hold) + upd4990a_serial_command(UPD4990A_REGISTER_HOLD); +} + +static __inline__ void upd4990a_set_time(const struct upd4990a_raw_data *data, + int time_set_only) +{ + int byte; + + if (!time_set_only) + upd4990a_serial_command(UPD4990A_REGISTER_SHIFT); + + for (byte = 0; byte < 6; byte++) { + int bit; + u8 tmp = ((const u8 *) data)[byte]; + + for (bit = 0; bit < 8; bit++, tmp >>= 1) + UPD4990A_OUTPUT_DATA(tmp); + } + + upd4990a_serial_command(UPD4990A_TIME_SET_AND_COUNTER_HOLD); + + /* Release counter hold and start the clock. */ + if (!time_set_only) + upd4990a_serial_command(UPD4990A_REGISTER_HOLD); +} + +#endif /* _LINUX_uPD4990A_H */ diff -urN linux-2.5.65-bk2/kernel/ksyms.c linux-2.5.65-bk3/kernel/ksyms.c --- linux-2.5.65-bk2/kernel/ksyms.c Mon Mar 17 13:43:38 2003 +++ linux-2.5.65-bk3/kernel/ksyms.c Mon Mar 31 12:41:47 2003 @@ -175,6 +175,7 @@ EXPORT_SYMBOL(d_path); EXPORT_SYMBOL(mark_buffer_dirty); EXPORT_SYMBOL(end_buffer_io_sync); +EXPORT_SYMBOL(end_buffer_async_write); EXPORT_SYMBOL(__mark_inode_dirty); EXPORT_SYMBOL(get_empty_filp); EXPORT_SYMBOL(open_private_file); diff -urN linux-2.5.65-bk2/mm/oom_kill.c linux-2.5.65-bk3/mm/oom_kill.c --- linux-2.5.65-bk2/mm/oom_kill.c Mon Mar 17 13:44:07 2003 +++ linux-2.5.65-bk3/mm/oom_kill.c Mon Mar 31 12:41:47 2003 @@ -51,7 +51,7 @@ * 3) we don't kill anything innocent of eating tons of memory * 4) we want to kill the minimum amount of processes (one) * 5) we try to kill the process the user expects us to kill, this - * algorithm has been meticulously tuned to meet the priniciple + * algorithm has been meticulously tuned to meet the principle * of least surprise ... (be careful when you change it) */ diff -urN linux-2.5.65-bk2/mm/swapfile.c linux-2.5.65-bk3/mm/swapfile.c --- linux-2.5.65-bk2/mm/swapfile.c Mon Mar 17 13:43:46 2003 +++ linux-2.5.65-bk3/mm/swapfile.c Mon Mar 31 12:41:47 2003 @@ -736,8 +736,7 @@ * interactive performance. Interruptible check on * signal_pending() would be nice, but changes the spec? */ - if (need_resched()) - schedule(); + cond_resched(); } mmput(start_mm); diff -urN linux-2.5.65-bk2/net/core/neighbour.c linux-2.5.65-bk3/net/core/neighbour.c --- linux-2.5.65-bk2/net/core/neighbour.c Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/net/core/neighbour.c Mon Mar 31 12:41:47 2003 @@ -550,7 +550,7 @@ write_lock(&tbl->lock); /* - * periodicly recompute ReachableTime from random function + * periodically recompute ReachableTime from random function */ if (now - tbl->last_rand > 300 * HZ) { diff -urN linux-2.5.65-bk2/net/ipv4/netfilter/arp_tables.c linux-2.5.65-bk3/net/ipv4/netfilter/arp_tables.c --- linux-2.5.65-bk2/net/ipv4/netfilter/arp_tables.c Mon Mar 31 12:41:37 2003 +++ linux-2.5.65-bk3/net/ipv4/netfilter/arp_tables.c Mon Mar 31 12:41:47 2003 @@ -912,19 +912,25 @@ goto free_newinfo_counters_untrans_unlock; } + /* Get a reference in advance, we're not allowed fail later */ + if (!try_module_get(t->me)) { + ret = -EBUSY; + goto free_newinfo_counters_untrans_unlock; + } + oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); if (!oldinfo) - goto free_newinfo_counters_untrans_unlock; + goto put_module; /* Update module usage count based on number of rules */ duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n", oldinfo->number, oldinfo->initial_entries, newinfo->number); - if (t->me && (oldinfo->number <= oldinfo->initial_entries) && - (newinfo->number > oldinfo->initial_entries)) - __MOD_INC_USE_COUNT(t->me); - else if (t->me && (oldinfo->number > oldinfo->initial_entries) && - (newinfo->number <= oldinfo->initial_entries)) - __MOD_DEC_USE_COUNT(t->me); + if ((oldinfo->number > oldinfo->initial_entries) || + (newinfo->number <= oldinfo->initial_entries)) + module_put(t->me); + if ((oldinfo->number > oldinfo->initial_entries) && + (newinfo->number <= oldinfo->initial_entries)) + module_put(t->me); /* Get the old counters. */ get_counters(oldinfo, counters); @@ -938,6 +944,8 @@ up(&arpt_mutex); return 0; + put_module: + module_put(t->me); free_newinfo_counters_untrans_unlock: up(&arpt_mutex); free_newinfo_counters_untrans: diff -urN linux-2.5.65-bk2/net/ipv4/netfilter/ip_tables.c linux-2.5.65-bk3/net/ipv4/netfilter/ip_tables.c --- linux-2.5.65-bk2/net/ipv4/netfilter/ip_tables.c Mon Mar 31 12:41:37 2003 +++ linux-2.5.65-bk3/net/ipv4/netfilter/ip_tables.c Mon Mar 31 12:41:47 2003 @@ -1106,19 +1106,26 @@ goto free_newinfo_counters_untrans_unlock; } + /* Get a reference in advance, we're not allowed fail later */ + if (!try_module_get(t->me)) { + ret = -EBUSY; + goto free_newinfo_counters_untrans_unlock; + } + + oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); if (!oldinfo) - goto free_newinfo_counters_untrans_unlock; + goto put_module; /* Update module usage count based on number of rules */ duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n", oldinfo->number, oldinfo->initial_entries, newinfo->number); - if (t->me && (oldinfo->number <= oldinfo->initial_entries) && - (newinfo->number > oldinfo->initial_entries)) - __MOD_INC_USE_COUNT(t->me); - else if (t->me && (oldinfo->number > oldinfo->initial_entries) && - (newinfo->number <= oldinfo->initial_entries)) - __MOD_DEC_USE_COUNT(t->me); + if ((oldinfo->number > oldinfo->initial_entries) || + (newinfo->number <= oldinfo->initial_entries)) + module_put(t->me); + if ((oldinfo->number > oldinfo->initial_entries) && + (newinfo->number <= oldinfo->initial_entries)) + module_put(t->me); /* Get the old counters. */ get_counters(oldinfo, counters); @@ -1132,6 +1139,8 @@ up(&ipt_mutex); return 0; + put_module: + module_put(t->me); free_newinfo_counters_untrans_unlock: up(&ipt_mutex); free_newinfo_counters_untrans: diff -urN linux-2.5.65-bk2/net/ipv4/route.c linux-2.5.65-bk3/net/ipv4/route.c --- linux-2.5.65-bk2/net/ipv4/route.c Mon Mar 17 13:44:50 2003 +++ linux-2.5.65-bk3/net/ipv4/route.c Mon Mar 31 12:41:48 2003 @@ -1854,7 +1854,7 @@ goto out; /* I removed check for oif == dev_out->oif here. - It was wrong by three reasons: + It was wrong for two reasons: 1. ip_dev_find(saddr) can return wrong iface, if saddr is assigned to multiple interfaces. 2. Moreover, we are allowed to send packets with saddr diff -urN linux-2.5.65-bk2/net/ipv4/xfrm_policy.c linux-2.5.65-bk3/net/ipv4/xfrm_policy.c --- linux-2.5.65-bk2/net/ipv4/xfrm_policy.c Mon Mar 31 12:41:37 2003 +++ linux-2.5.65-bk3/net/ipv4/xfrm_policy.c Mon Mar 31 12:41:48 2003 @@ -1101,6 +1101,7 @@ case AF_INET6: /* Still not clear... */ default: + /* nothing */; } restart: diff -urN linux-2.5.65-bk2/net/ipv6/netfilter/ip6_tables.c linux-2.5.65-bk3/net/ipv6/netfilter/ip6_tables.c --- linux-2.5.65-bk2/net/ipv6/netfilter/ip6_tables.c Mon Mar 31 12:41:37 2003 +++ linux-2.5.65-bk3/net/ipv6/netfilter/ip6_tables.c Mon Mar 31 12:41:48 2003 @@ -1178,19 +1178,25 @@ goto free_newinfo_counters_untrans_unlock; } + /* Get a reference in advance, we're not allowed fail later */ + if (!try_module_get(t->me)) { + ret = -EBUSY; + goto free_newinfo_counters_untrans_unlock; + } + oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); if (!oldinfo) - goto free_newinfo_counters_untrans_unlock; + goto put_module; /* Update module usage count based on number of rules */ duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%u\n", oldinfo->number, oldinfo->initial_entries, newinfo->number); - if (t->me && (oldinfo->number <= oldinfo->initial_entries) && - (newinfo->number > oldinfo->initial_entries)) - __MOD_INC_USE_COUNT(t->me); - else if (t->me && (oldinfo->number > oldinfo->initial_entries) && - (newinfo->number <= oldinfo->initial_entries)) - __MOD_DEC_USE_COUNT(t->me); + if ((oldinfo->number > oldinfo->initial_entries) || + (newinfo->number <= oldinfo->initial_entries)) + module_put(t->me); + if ((oldinfo->number > oldinfo->initial_entries) && + (newinfo->number <= oldinfo->initial_entries)) + module_put(t->me); /* Get the old counters. */ get_counters(oldinfo, counters); @@ -1204,6 +1210,8 @@ up(&ip6t_mutex); return 0; + put_module: + module_put(t->me); free_newinfo_counters_untrans_unlock: up(&ip6t_mutex); free_newinfo_counters_untrans: diff -urN linux-2.5.65-bk2/sound/isa/cs423x/pc98.c linux-2.5.65-bk3/sound/isa/cs423x/pc98.c --- linux-2.5.65-bk2/sound/isa/cs423x/pc98.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/sound/isa/cs423x/pc98.c Mon Mar 31 12:41:50 2003 @@ -0,0 +1,466 @@ +/* + * Driver for CS4232 on NEC PC9800 series + * Copyright (c) by Jaroslav Kysela + * Osamu Tomita + * Takashi Iwai + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include +#include +#include +#define SNDRV_GET_ID +#include +#include "sound_pc9800.h" + +#define chip_t cs4231_t + +MODULE_AUTHOR("Osamu Tomita "); +MODULE_LICENSE("GPL"); +MODULE_CLASSES("{sound}"); +MODULE_DESCRIPTION("NEC PC9800 CS4232"); +MODULE_DEVICES("{{NEC,PC9800}}"); + +#define IDENT "PC98-CS4232" + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ +static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */ +static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ +#if 0 /* NOT USED */ +static long cport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ +#endif +static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* PnP setup */ +static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ +static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */ +static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 9,11,12,15 */ +static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ +static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ +static int pc98ii[SNDRV_CARDS]; /* PC98II */ + +MODULE_PARM(index, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +MODULE_PARM_DESC(index, "Index value for " IDENT " soundcard."); +MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC); +MODULE_PARM(id, "1-" __MODULE_STRING(SNDRV_CARDS) "s"); +MODULE_PARM_DESC(id, "ID string for " IDENT " soundcard."); +MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC); +MODULE_PARM(enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +MODULE_PARM_DESC(enable, "Enable " IDENT " soundcard."); +MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC); +MODULE_PARM(port, "1-" __MODULE_STRING(SNDRV_CARDS) "l"); +MODULE_PARM_DESC(port, "Port # for " IDENT " driver."); +MODULE_PARM_SYNTAX(port, SNDRV_PORT12_DESC); +#if 0 /* NOT USED */ +MODULE_PARM(cport, "1-" __MODULE_STRING(SNDRV_CARDS) "l"); +MODULE_PARM_DESC(cport, "Control port # for " IDENT " driver."); +MODULE_PARM_SYNTAX(cport, SNDRV_PORT12_DESC); +#endif +MODULE_PARM(mpu_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l"); +MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " IDENT " driver."); +MODULE_PARM_SYNTAX(mpu_port, SNDRV_PORT12_DESC); +MODULE_PARM(fm_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l"); +MODULE_PARM_DESC(fm_port, "FM port # for " IDENT " driver."); +MODULE_PARM_SYNTAX(fm_port, SNDRV_PORT12_DESC); +MODULE_PARM(irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +MODULE_PARM_DESC(irq, "IRQ # for " IDENT " driver."); +MODULE_PARM_SYNTAX(irq, SNDRV_IRQ_DESC); +MODULE_PARM(mpu_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " IDENT " driver."); +MODULE_PARM_SYNTAX(mpu_irq, SNDRV_IRQ_DESC); +MODULE_PARM(dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver."); +MODULE_PARM_SYNTAX(dma1, SNDRV_DMA_DESC); +MODULE_PARM(dma2, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver."); +MODULE_PARM_SYNTAX(dma2, SNDRV_DMA_DESC); +MODULE_PARM(pc98ii, "1-" __MODULE_STRING(SNDRV_CARDS) "i"); +MODULE_PARM_DESC(pc98ii, "Roland MPU-PC98II support."); +MODULE_PARM_SYNTAX(pc98ii, SNDRV_BOOLEAN_FALSE_DESC); + + +static snd_card_t *snd_pc98_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; + +/* + * initialize MPU401-UART + */ + +static int __init pc98_mpu401_init(int irq) +{ +#include "pc9801_118_magic.h" +#define outp118(reg,data) outb((reg),0x148e);outb((data),0x148f) +#define WAIT118 outb(0x00,0x5f) + int mpu_intr, count; +#ifdef OOKUBO_ORIGINAL + int err = 0; +#endif /* OOKUBO_ORIGINAL */ + + switch (irq) { + case 3: + mpu_intr = 3; + break; + case 5: + mpu_intr = 2; + break; + case 6: + mpu_intr = 1; + break; + case 10: + mpu_intr = 0; + break; + default: + snd_printk(KERN_ERR IDENT ": Bad IRQ %d\n", irq); + return -EINVAL; + } + + outp118(0x21, mpu_intr); + WAIT118; + outb(0x00, 0x148e); + if (inb(0x148f) & 0x08) { + snd_printk(KERN_INFO IDENT ": No MIDI daughter board found\n"); + return 0; + } + + outp118(0x20, 0x00); + outp118(0x05, 0x04); + for (count = 0; count < 35000; count ++) + WAIT118; + outb(0x05, 0x148e); + for (count = 0; count < 65000; count ++) + if (inb(0x148f) == 0x04) + goto set_mode_118; + snd_printk(KERN_ERR IDENT ": MIDI daughter board initialize failed at stage1\n\n"); + return -EINVAL; + + set_mode_118: + outp118(0x05, 0x0c); + outb(0xaa, 0x485); + outb(0x99, 0x485); + outb(0x2a, 0x485); + for (count = 0; count < sizeof(Data0485_99); count ++) { + outb(Data0485_99[count], 0x485); + WAIT118; + } + + outb(0x00, 0x486); + outb(0xaa, 0x485); + outb(0x9e, 0x485); + outb(0x2a, 0x485); + for (count = 0; count < sizeof(Data0485_9E); count ++) + if (inb(0x485) != Data0485_9E[count]) { +#ifdef OOKUBO_ORIGINAL + err = 1; +#endif /* OOKUBO_ORIGINAL */ + break; + } + outb(0x00, 0x486); + for (count = 0; count < 2000; count ++) + WAIT118; +#ifdef OOKUBO_ORIGINAL + if (!err) { + outb(0xaa, 0x485); + outb(0x36, 0x485); + outb(0x28, 0x485); + for (count = 0; count < sizeof(Data0485_36); count ++) + outb(Data0485_36[count], 0x485); + outb(0x00, 0x486); + for (count = 0; count < 1500; count ++) + WAIT118; + outp118(0x05, inb(0x148f) | 0x08); + outb(0xff, 0x148c); + outp118(0x05, inb(0x148f) & 0xf7); + for (count = 0; count < 1500; count ++) + WAIT118; + } +#endif /* OOKUBO_ORIGINAL */ + + outb(0xaa, 0x485); + outb(0xa9, 0x485); + outb(0x21, 0x485); + for (count = 0; count < sizeof(Data0485_A9); count ++) { + outb(Data0485_A9[count], 0x485); + WAIT118; + } + + outb(0x00, 0x486); + outb(0xaa, 0x485); + outb(0x0c, 0x485); + outb(0x20, 0x485); + for (count = 0; count < sizeof(Data0485_0C); count ++) { + outb(Data0485_0C[count], 0x485); + WAIT118; + } + + outb(0x00, 0x486); + outb(0xaa, 0x485); + outb(0x66, 0x485); + outb(0x20, 0x485); + for (count = 0; count < sizeof(Data0485_66); count ++) { + outb(Data0485_66[count], 0x485); + WAIT118; + } + + outb(0x00, 0x486); + outb(0xaa, 0x485); + outb(0x60, 0x485); + outb(0x20, 0x485); + for (count = 0; count < sizeof(Data0485_60); count ++) { + outb(Data0485_60[count], 0x485); + WAIT118; + } + + outb(0x00, 0x486); + outp118(0x05, 0x04); + outp118(0x05, 0x00); + for (count = 0; count < 35000; count ++) + WAIT118; + outb(0x05, 0x148e); + for (count = 0; count < 65000; count ++) + if (inb(0x148f) == 0x00) + goto end_mode_118; + snd_printk(KERN_ERR IDENT ": MIDI daughter board initialize failed at stage2\n"); + return -EINVAL; + + end_mode_118: + outb(0x3f, 0x148d); + snd_printk(KERN_INFO IDENT ": MIDI daughter board initialized\n"); + return 0; +} + +static int __init pc98_cs4231_chip_init(int dev) +{ + int intr_bits, intr_bits2, dma_bits; + + switch (irq[dev]) { + case 3: + intr_bits = 0x08; + intr_bits2 = 0x03; + break; + case 5: + intr_bits = 0x10; + intr_bits2 = 0x08; + break; + case 10: + intr_bits = 0x18; + intr_bits2 = 0x02; + break; + case 12: + intr_bits = 0x20; + intr_bits2 = 0x00; + break; + default: + snd_printk(KERN_ERR IDENT ": Bad IRQ %d\n", irq[dev]); + return -EINVAL; + } + + switch (dma1[dev]) { + case 0: + dma_bits = 0x01; + break; + case 1: + dma_bits = 0x02; + break; + case 3: + dma_bits = 0x03; + break; + default: + snd_printk(KERN_ERR IDENT ": Bad DMA %d\n", dma1[dev]); + return -EINVAL; + } + + if (dma2[dev] >= 2) { + snd_printk(KERN_ERR IDENT ": Bad DMA %d\n", dma2[dev]); + return -EINVAL; + } + if (dma1[dev] != dma2[dev] && dma2[dev] >= 0) + intr_bits |= 0x04; + + if (PC9800_SOUND_ID() == PC9800_SOUND_ID_118) { + /* Set up CanBe control registers. */ + snd_printd(KERN_INFO "Setting up CanBe Sound System\n"); + outb(inb(PC9800_SOUND_IO_ID) | 0x03, PC9800_SOUND_IO_ID); + outb(0x01, 0x0f4a); + outb(intr_bits2, 0x0f4b); + } + + outb(intr_bits | dma_bits, 0xf40); + return 0; +} + + +static int __init snd_card_pc98_probe(int dev) +{ + snd_card_t *card; + snd_pcm_t *pcm = NULL; + cs4231_t *chip; + opl3_t *opl3; + int err; + + if (port[dev] == SNDRV_AUTO_PORT) { + snd_printk(KERN_ERR IDENT ": specify port\n"); + return -EINVAL; + } + card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + if (card == NULL) + return -ENOMEM; + if (mpu_port[dev] < 0 || mpu_irq[dev] < 0) + mpu_port[dev] = SNDRV_AUTO_PORT; + if (fm_port[dev] < 0) + fm_port[dev] = SNDRV_AUTO_PORT; + + if ((err = pc98_cs4231_chip_init(dev)) < 0) { + snd_card_free(card); + return err; + } + + if ((err = snd_cs4231_create(card, + port[dev], + -1, + irq[dev], + dma1[dev], + dma2[dev], + CS4231_HW_DETECT, + 0, + &chip)) < 0) { + snd_card_free(card); + return err; + } + if ((err = snd_cs4231_pcm(chip, 0, &pcm)) < 0) { + snd_card_free(card); + return err; + } + if ((err = snd_cs4231_mixer(chip)) < 0) { + snd_card_free(card); + return err; + } + + if ((err = snd_cs4231_timer(chip, 0, NULL)) < 0) { + snd_card_free(card); + return err; + } + + if (fm_port[dev] != SNDRV_AUTO_PORT) { + /* ??? */ + outb(0x00, fm_port[dev] + 6); + inb(fm_port[dev] + 7); + /* Enable OPL-3 Function */ + outb(inb(PC9800_SOUND_IO_ID) | 0x03, PC9800_SOUND_IO_ID); + if (snd_opl3_create(card, + fm_port[dev], fm_port[dev] + 2, + OPL3_HW_OPL3_PC98, 0, &opl3) < 0) { + printk(KERN_ERR IDENT ": OPL3 not detected\n"); + } else { + if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { + snd_card_free(card); + return err; + } + } + } + + if (mpu_port[dev] != SNDRV_AUTO_PORT) { + err = pc98_mpu401_init(mpu_irq[dev]); + if (! err) { + err = snd_mpu401_uart_new(card, 0, + pc98ii[dev] ? MPU401_HW_PC98II : MPU401_HW_MPU401, + mpu_port[dev], 0, + mpu_irq[dev], SA_INTERRUPT, NULL); + if (err < 0) + snd_printk(KERN_INFO IDENT ": MPU401 not detected\n"); + } + } + + strcpy(card->driver, pcm->name); + strcpy(card->shortname, pcm->name); + sprintf(card->longname, "%s at 0x%lx, irq %i, dma %i", + pcm->name, + chip->port, + irq[dev], + dma1[dev]); + if (dma1[dev] >= 0) + sprintf(card->longname + strlen(card->longname), "&%d", dma2[dev]); + if ((err = snd_card_register(card)) < 0) { + snd_card_free(card); + return err; + } + snd_pc98_cards[dev] = card; + return 0; +} + +static int __init alsa_card_pc98_init(void) +{ + int dev, cards = 0; + + for (dev = 0; dev < SNDRV_CARDS; dev++) { + if (!enable[dev]) + continue; + if (snd_card_pc98_probe(dev) >= 0) + cards++; + } + if (!cards) { +#ifdef MODULE + printk(KERN_ERR IDENT " soundcard not found or device busy\n"); +#endif + return -ENODEV; + } + return 0; +} + +static void __exit alsa_card_pc98_exit(void) +{ + int idx; + + for (idx = 0; idx < SNDRV_CARDS; idx++) + snd_card_free(snd_pc98_cards[idx]); +} + +module_init(alsa_card_pc98_init) +module_exit(alsa_card_pc98_exit) + +#ifndef MODULE + +/* format is: snd-pc98-cs4232=enable,index,id,port, + mpu_port,fm_port, + irq,mpu_irq,dma1,dma2,pc98ii */ + +static int __init alsa_card_pc98_setup(char *str) +{ + static unsigned __initdata nr_dev = 0; + + if (nr_dev >= SNDRV_CARDS) + return 0; + (void)(get_option(&str,&enable[nr_dev]) == 2 && + get_option(&str,&index[nr_dev]) == 2 && + get_id(&str,&id[nr_dev]) == 2 && + get_option(&str,(int *)&port[nr_dev]) == 2 && + get_option(&str,(int *)&mpu_port[nr_dev]) == 2 && + get_option(&str,(int *)&fm_port[nr_dev]) == 2 && + get_option(&str,&irq[nr_dev]) == 2 && + get_option(&str,&mpu_irq[nr_dev]) == 2 && + get_option(&str,&dma1[nr_dev]) == 2 && + get_option(&str,&dma2[nr_dev]) == 2 && + get_option(&str,&pc98ii[nr_dev]) == 2); + nr_dev++; + return 1; +} + +__setup("snd-pc98-cs4232=", alsa_card_pc98_setup); + +#endif /* ifndef MODULE */ diff -urN linux-2.5.65-bk2/sound/isa/cs423x/pc9801_118_magic.h linux-2.5.65-bk3/sound/isa/cs423x/pc9801_118_magic.h --- linux-2.5.65-bk2/sound/isa/cs423x/pc9801_118_magic.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/sound/isa/cs423x/pc9801_118_magic.h Mon Mar 31 12:41:50 2003 @@ -0,0 +1,411 @@ + static unsigned char Data0485_A9[] = { + 0x12, 0x03, 0x90, 0xc2, 0x2a, 0x75, 0x1e, 0x20, + 0xe4, 0x12, 0x2b, 0x9b, 0x22, 0xa9, 0x16, 0x77, + 0x33, 0xe9, 0x04, 0x54, 0x03, 0x44, 0xa8, 0xf5, + 0x16, 0xc2, 0x2f, 0x22, 0xa9, 0x16, 0x77, 0x42, + 0xe9, 0x04, 0x54, 0x03, 0x44, 0xa8, 0xf9, 0x77, + 0xf8, 0x04, 0x54, 0x03, 0x44, 0xa8, 0xf5, 0x16, + 0xc2, 0x2f, 0x22, 0x90, 0x25, 0x9f, 0x30, 0x04, + 0x05, 0xc2, 0x04, 0x12, 0x1f, 0x62, 0x30, 0x00, + 0x05, 0xc2, 0x00, 0x12, 0x15, 0xe6, 0x30, 0x01, + 0x05, 0xc2, 0x01, 0x12, 0x29, 0xaf, 0x30, 0x02, + 0x05, 0xc2, 0x02, 0x12, 0x29, 0xaf, 0x30, 0x05, + 0x05, 0xc2, 0x05, 0x12, 0x16, 0x65, 0x30, 0x06, + 0x08, 0xc2, 0x06, 0x12, 0x16, 0xb1, 0x12, 0x29, + 0xaf, 0x30, 0x07, 0x08, 0xc2, 0x07, 0x12, 0x16, + 0xe9, 0x12, 0x29, 0xaf, 0x22, 0x20, 0x97, 0x09, + 0x53, 0xa8, 0xfb, 0x12, 0x04, 0x2c, 0x43, 0xa8, + 0x04, 0x22, 0x71, 0xb8, 0x71, 0xb8, 0x71, 0xb8, + 0x22, 0x20, 0x4b, 0x04, 0x75, 0x4e, 0x02, 0x22, + 0xe5, 0x35, 0x24, 0xff, 0xf5, 0x35, 0xe5, 0x36, + 0x34, 0xff, 0xf5, 0x36, 0x75, 0x4e, 0x02, 0x22, + 0x10, 0x19, 0x02, 0x80, 0x08, 0x78, 0x00, 0xe2, + 0x78, 0x07, 0xf2, 0x61, 0x9b, 0x78, 0x11, 0xe2, + 0xc0, 0x01, 0xc0, 0xf0, 0xc0, 0xd0, 0xc0, 0x02, + 0x71, 0x14, 0xe5, 0x30, 0xb4, 0x01, 0x02, 0x61, + 0x93, 0x43, 0x08, 0x40, 0x12, 0x2a, 0x53, 0x61, + 0x93, 0x79, 0x03, 0xe3, 0xa2, 0xe2, 0x92, 0x26, + 0xa2, 0xe3, 0x92, 0x27, 0x22, 0xad, 0x2b, 0xbd, + 0x04, 0x07, 0xf5, 0x72, 0x78, 0x27, 0x02, 0x11, + 0x76, 0x02, 0x11, 0x30, 0x00, 0x00, 0x00, 0x12, + 0x28, 0xba, 0x79, 0x01, 0xe3, 0x75, 0x21, 0x3f, + 0x75, 0x49, 0x11, 0x75, 0x4c, 0x11, 0x31, 0xdc, + 0x75, 0x1a, 0x80, 0x51, 0x72, 0x75, 0x81, 0xe3, + 0x12, 0x25, 0xc9, 0x43, 0xa8, 0x01, 0x00, 0x53, + 0xa8, 0xfe, 0x10, 0x50, 0x02, 0x80, 0x03, 0x12, + 0x1a, 0x8d, 0xd1, 0x28, 0x12, 0x03, 0xd9, 0xd1, + 0xf2, 0x12, 0x2d, 0xf0, 0xb0, 0x11, 0x92, 0xe0, + 0xa2, 0x2a, 0xa0, 0xb5, 0x82, 0xe0, 0x50, 0x03, + 0x79, 0x0f, 0xe3, 0x71, 0xca, 0x51, 0x1e, 0x91, + 0xe4, 0x53, 0xa8, 0xfb, 0x10, 0x10, 0x02, 0x80, + 0x26, 0xc2, 0x8e, 0xd2, 0xab, 0xa2, 0x1c, 0x40, + 0x13, 0xa2, 0x1d, 0x50, 0x0a, 0x43, 0x08, 0x40, + 0x12, 0x1a, 0x01, 0xd1, 0xd7, 0x80, 0x0b, 0x12, + 0x26, 0x04, 0x61, 0x08, 0x43, 0x08, 0x40, 0x12, + 0x1a, 0x01, 0xd2, 0x1f, 0x12, 0x17, 0x7f, 0x43, + 0xa8, 0x04, 0x51, 0x1e, 0x91, 0xe4, 0x12, 0x13, + 0x34, 0x80, 0x98, 0xa2, 0x17, 0x72, 0x16, 0x72, + 0x15, 0x72, 0x2d, 0x50, 0x06, 0xfa, 0x12, 0x13, + 0x66, 0x80, 0x25, 0xc2, 0x13, 0x30, 0x28, 0x05, + 0x12, 0x02, 0xbe, 0x80, 0x1b, 0xb4, 0x10, 0x12, + 0x78, 0x00, 0xf2, 0xe5, 0x30, 0xb4, 0x01, 0x06, + 0x12, 0x03, 0x90, 0xd2, 0x19, 0x22, 0x12, 0x00, + 0xdd, 0x22, 0x75, 0x30, 0x00, 0x12, 0x00, 0xa1, + 0x22, 0x00, 0x00, 0x75, 0x1e, 0x00, 0x74, 0x0c, + 0x12, 0x2b, 0x9b, 0x74, 0x40, 0x79, 0x05, 0xf3, + 0x74, 0x49, 0x12, 0x2b, 0x9b, 0x74, 0x04, 0x79, + 0x05, 0xf3, 0x75, 0x15, 0x04, 0x74, 0x10, 0x12, + 0x2b, 0x9b, 0x74, 0x00, 0x79, 0x05, 0xf3, 0x74, + 0x17, 0x12, 0x2b, 0x9b, 0x74, 0x00, 0x79, 0x05, + 0xf3, 0x74, 0x1a, 0x12, 0x2b, 0x9b, 0x74, 0x00, + 0x79, 0x05, 0xf3, 0x74, 0x0a, 0x12, 0x2b, 0x9b, + 0x74, 0x20, 0x79, 0x05, 0xf3, 0x79, 0xe0, 0x77, + 0x20, 0x22, 0xd0, 0x02, 0xd0, 0xd0, 0xd0, 0xf0, + 0xd0, 0x01, 0xe5, 0x5f, 0xd0, 0xa8, 0x22, 0x00, + 0x00, 0x90, 0x25, 0x9f, 0x75, 0x26, 0xff, 0x75, + 0x27, 0xff, 0x75, 0x28, 0x03, 0x75, 0x13, 0xff, + 0x75, 0x1f, 0x00, 0x75, 0x14, 0xff, 0x22, 0x79, + 0x06, 0xe5, 0x29, 0x60, 0x0b, 0xe3, 0x30, 0xe1, + 0xf8, 0xe5, 0x4f, 0x64, 0x80, 0x79, 0x07, 0xf3, + 0x22, 0x10, 0x4c, 0x01, 0x22, 0x30, 0x4b, 0x0a, + 0xc2, 0x4b, 0xe5, 0x4d, 0x64, 0x80, 0xf5, 0x4f, + 0x80, 0x1d, 0xe5, 0x15, 0xa2, 0xe0, 0x82, 0xe6, + 0x40, 0x02, 0x80, 0x35, 0x30, 0x4a, 0x04, 0xb1, + 0xe6, 0x80, 0x0c, 0x30, 0x49, 0x04, 0x51, 0x2b, + 0x80, 0x05, 0x30, 0x48, 0x24, 0x91, 0x7e, 0x79, + 0x06, 0xe3, 0x30, 0xe0, 0x1a, 0x79, 0x06, 0xf3, + 0xe5, 0x4e, 0x24, 0xff, 0x50, 0x04, 0xf5, 0x4e, + 0x80, 0x0d, 0x79, 0x0f, 0xf3, 0x20, 0x2a, 0x07, + 0x12, 0x2b, 0x32, 0x75, 0x29, 0x00, 0x22, 0x91, + 0x1b, 0x22, 0x79, 0x0f, 0xe3, 0xc0, 0xa8, 0x75, + 0xa8, 0x00, 0x30, 0x2b, 0x03, 0xd0, 0xa8, 0x22, + 0x79, 0x0e, 0xf3, 0xd0, 0xa8, 0x22, 0x8a, 0xf0, + 0xe5, 0x50, 0x10, 0xf3, 0x10, 0x23, 0x23, 0x23, + 0x25, 0xf0, 0x12, 0x2c, 0xb8, 0xa2, 0xe7, 0x92, + 0xe4, 0xc2, 0xe7, 0x80, 0x08, 0x23, 0x23, 0x23, + 0x25, 0xf0, 0x12, 0x2c, 0x19, 0x25, 0x4f, 0x20, + 0xd2, 0x04, 0xf5, 0x4f, 0x80, 0x0a, 0x40, 0x05, + 0x75, 0x4f, 0x7f, 0x80, 0x03, 0x75, 0x4f, 0xff, + 0xea, 0x12, 0x2c, 0x3c, 0x25, 0x50, 0x20, 0xe7, + 0x05, 0xb4, 0x03, 0x07, 0x80, 0x0c, 0x75, 0x50, + 0x00, 0x80, 0x09, 0x40, 0x05, 0x75, 0x50, 0x03, + 0x80, 0x02, 0xf5, 0x50, 0x22, 0xe5, 0x4d, 0xc4, + 0x54, 0x0c, 0x03, 0x03, 0xfa, 0x91, 0xa9, 0x71, + 0xb8, 0xe5, 0x4d, 0xc4, 0x54, 0x03, 0xfa, 0x91, + 0xa9, 0x71, 0xb8, 0xe5, 0x4d, 0x54, 0x0c, 0x03, + 0x03, 0xfa, 0x91, 0xa9, 0x71, 0xb8, 0xe5, 0x4d, + 0x54, 0x03, 0xfa, 0x91, 0xa9, 0x71, 0xb8, 0x22, + 0x8a, 0xf0, 0xe5, 0x50, 0x23, 0x23, 0x25, 0xf0, + 0x12, 0x2b, 0xf6, 0x25, 0x4f, 0x20, 0xd2, 0x04, + 0xf5, 0x4f, 0x80, 0x0a, 0x40, 0x05, 0x75, 0x4f, + 0x7f, 0x80, 0x03, 0x75, 0x4f, 0xff, 0xea, 0x12, + 0x2c, 0x40, 0x25, 0x50, 0x20, 0xe7, 0x05, 0xb4, + 0x05, 0x07, 0x80, 0x0c, 0x75, 0x50, 0x00, 0x80, + 0x09, 0x40, 0x05, 0x75, 0x50, 0x05, 0x80, 0x02, + 0xf5, 0x50, 0x22, 0x30, 0x26, 0x03, 0x12, 0x1e, + 0xf5, 0x30, 0x27, 0x03, 0x12, 0x1f, 0x37, 0x30, + 0x25, 0x09, 0x12, 0x1f, 0x4e, 0x30, 0x23, 0x03, + 0x12, 0x1f, 0x1e, 0x10, 0x22, 0x02, 0x80, 0x0a, + 0xe5, 0x3b, 0xb4, 0xff, 0x02, 0xc2, 0x20, 0x12, + 0x1e, 0x79, 0x22, 0x78, 0x11, 0xe2, 0x20, 0xe0, + 0x07, 0xc0, 0x01, 0x12, 0x28, 0xba, 0xd0, 0x01, + 0x78, 0x00, 0xf2, 0x61, 0x9b, 0x12, 0x2b, 0x32, + 0x12, 0x17, 0x7f, 0x78, 0x00, 0xf2, 0xaa, 0x35, + 0xab, 0x36, 0xea, 0x24, 0xff, 0xfa, 0xeb, 0x34, + 0xff, 0xfb, 0x50, 0x03, 0xd2, 0x10, 0x22, 0x75, + 0x37, 0x01, 0x75, 0x38, 0x00, 0x75, 0x39, 0x00, + 0x12, 0x04, 0x04, 0xd2, 0x8e, 0x22, 0xa8, 0x2b, + 0xb8, 0x00, 0x02, 0x80, 0x03, 0x02, 0x11, 0xbd, + 0xf5, 0x74, 0x78, 0x2a, 0x12, 0x11, 0xec, 0xe5, + 0x74, 0x78, 0x29, 0x12, 0x11, 0xec, 0x22, 0xfa, + 0xe5, 0x2b, 0x60, 0x01, 0x22, 0xea, 0x78, 0x2b, + 0xf5, 0x75, 0x12, 0x11, 0xec, 0x22, 0x74, 0x10, + 0x12, 0x2b, 0x9b, 0x74, 0x20, 0x78, 0x05, 0xf2, + 0x74, 0x09, 0x12, 0x17, 0x75, 0xe5, 0x15, 0x44, + 0x80, 0x79, 0x05, 0xf3, 0xf5, 0x15, 0x12, 0x17, + 0x7f, 0x22, 0x12, 0x03, 0x84, 0x79, 0x0f, 0xe3, + 0x78, 0x00, 0xf2, 0x12, 0x2b, 0x28, 0xe5, 0x81, + 0x24, 0xfc, 0xf5, 0x81, 0x61, 0x93, 0xd2, 0x07, + 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, 0x4c, 0xc2, + 0x0f, 0x12, 0x29, 0xa3, 0x61, 0x93, 0x02, 0x1b, + 0x77, 0x00, 0xe1, 0x81, 0xe1, 0x9a, 0xd2, 0x2c, + 0xa1, 0x0c, 0x20, 0x20, 0x02, 0xd2, 0x26, 0x02, + 0x1e, 0x35, 0x02, 0x1e, 0x61, 0x02, 0x1d, 0x8f, + 0xc2, 0x8e, 0x75, 0xa8, 0x9e, 0x22, 0x41, 0x49, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x29, 0x91, 0x00, 0x00, 0x00, 0xa1, 0xbb, + 0xa1, 0xc3, 0x02, 0x1e, 0x6b, 0xe5, 0x4d, 0xc4, + 0x54, 0x0f, 0xfa, 0x91, 0x2f, 0x71, 0xb8, 0xe5, + 0x4d, 0x54, 0x0f, 0xfa, 0x91, 0x2f, 0x71, 0xb8, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xc6, + 0x02, 0x1d, 0x8f, 0xc2, 0x8e, 0xd2, 0xab, 0xc2, + 0x10, 0x79, 0x0f, 0xf3, 0x22, 0x00, 0x02, 0x2a, + 0x84, 0x00, 0xe1, 0xbc, 0xe1, 0xc8, 0x02, 0x1e, + 0x27, 0x00, 0x78, 0x00, 0xf2, 0x78, 0x0b, 0xe2, + 0xf4, 0xf5, 0x4d, 0xd2, 0x4c, 0x61, 0x9b, 0x30, + 0xb5, 0x02, 0xc2, 0x11, 0x22, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x79, 0xbd, 0xf1, 0x3d, 0x83, + 0x22, 0xdd, 0xbd, 0xbd, 0xbd, 0x61, 0xbd, 0x8d, + 0x7a, 0xbd, 0xbd, 0xbd, 0xbd, 0x30, 0xbd, 0xbd, + 0xbd, 0x55, 0xbd, 0xbd, 0xbd, 0x52, 0xbd, 0xb6, + 0xb6, 0xbd, 0xbd, 0xbd, 0xbd, 0x00, 0xbd, 0xbd, + 0xbd, 0xe8, 0xda, 0xbd, 0xbd, 0xcf, 0xb9, 0xbd, + 0xc4, 0xf1, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0x7b, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0x70, 0x6a, 0x57, 0x47, 0x34, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x29, 0xbd, + 0xbd, 0xbd, 0xb6, 0xb6, 0xbd, 0xbd, 0xbd, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x2e, 0x25, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xfe, 0xf5, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x19, 0xbd, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x21, 0x8f, + 0x09, 0xbd, 0xf9, 0x86, 0xbd, 0xbd, 0xbd, 0xd7, + 0xbd, 0xa9, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x9b, + 0xd1, 0x9d, 0xbd, 0xae, 0xbd, 0xbd, 0xbd, 0xcb, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, + 0xb6, 0xa5, 0xbd, 0xc5, 0xbd, 0xbd, 0xbd, 0xc3, + 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0x74, 0x10, + 0x12, 0x2b, 0x9b, 0xe4, 0x78, 0x05, 0xf2, 0x74, + 0x09, 0x12, 0x17, 0x75, 0xe5, 0x15, 0x54, 0x7f, + 0x79, 0x05, 0xf3, 0xf5, 0x15, 0x12, 0x17, 0x7f, + 0x22, 0x30, 0x51, 0x01, 0x22, 0x53, 0xa8, 0xfb, + 0x12, 0x2d, 0xf0, 0x50, 0x22, 0x79, 0x03, 0xe3, + 0x20, 0xe4, 0x1c, 0xaa, 0x35, 0xab, 0x36, 0xea, + 0x24, 0xf0, 0xfa, 0xeb, 0x34, 0xff, 0xfb, 0x50, + 0x0e, 0x10, 0x1f, 0x02, 0x80, 0x09, 0x20, 0x2a, + 0x03, 0x12, 0x2b, 0x32, 0x12, 0x2d, 0xd6, 0x43, + 0xa8, 0x04, 0x22, 0xa2, 0x1c, 0x72, 0x1d, 0x40, + 0x07, 0x53, 0x08, 0xbf, 0x78, 0x00, 0xf2, 0x22, + 0xb1, 0x1e, 0x22, 0x00, 0x79, 0x02, 0x12, 0x27, + 0x3d, 0x02, 0x2d, 0x37, 0x14, 0x54, 0xf0, 0x60, + 0x21, 0xe5, 0xf0, 0x24, 0xb6, 0xe5, 0xf0, 0x50, + 0x16, 0x24, 0x8b, 0x50, 0x15, 0xe5, 0xf0, 0x24, + 0x56, 0xe5, 0xf0, 0x50, 0x08, 0x24, 0x2f, 0x50, + 0x09, 0xe5, 0xf0, 0x24, 0xd9, 0x24, 0xd5, 0x24, + 0xf0, 0x22, 0x15, 0x81, 0x15, 0x81, 0xe9, 0x22, + 0x78, 0x13, 0x74, 0x00, 0xf2, 0x75, 0x2e, 0x01, + 0xd2, 0x6a, 0xc2, 0x69, 0xc2, 0x68, 0xc2, 0x6c, + 0x90, 0x25, 0x9f, 0x75, 0xb8, 0x07, 0x41, 0xa4, + 0xc0, 0x01, 0xc0, 0xf0, 0xc0, 0xd0, 0xc0, 0x02, + 0xe5, 0x3d, 0x54, 0x7d, 0x03, 0x10, 0xe5, 0x05, + 0x90, 0x28, 0x4b, 0x80, 0x03, 0x90, 0x2b, 0x7c, + 0x73, 0xe5, 0x3d, 0x30, 0xe5, 0x07, 0x74, 0xfd, + 0x78, 0x00, 0xf2, 0x61, 0x9b, 0x90, 0x1a, 0x97, + 0x74, 0xb6, 0xc0, 0xe0, 0x74, 0x27, 0xc0, 0xe0, + 0xc0, 0xa8, 0x02, 0x1b, 0xab, 0x90, 0x25, 0x9f, + 0xd0, 0xa8, 0x22, 0x90, 0x27, 0xb6, 0xc0, 0x82, + 0xc0, 0x83, 0xc0, 0xa8, 0x02, 0x1d, 0xa6, 0x90, + 0x27, 0xb6, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0xa8, + 0x02, 0x1e, 0x0a, 0xea, 0x24, 0xf0, 0xfa, 0xeb, + 0x34, 0xff, 0xfb, 0x50, 0x2e, 0x20, 0x0b, 0x05, + 0x85, 0x44, 0xe0, 0x80, 0x03, 0x75, 0xe0, 0x00, + 0x30, 0xe1, 0x20, 0xe5, 0x35, 0x24, 0xff, 0xf5, + 0x35, 0xe5, 0x36, 0x34, 0xff, 0xf5, 0x36, 0xc3, + 0xe5, 0x36, 0x13, 0xf5, 0x36, 0xe5, 0x35, 0x13, + 0xf5, 0x35, 0x75, 0x3a, 0x10, 0x12, 0x1a, 0x77, + 0x02, 0x18, 0x77, 0x75, 0x3a, 0x00, 0x12, 0x1a, + 0x77, 0x02, 0x18, 0x1b, 0x20, 0x4b, 0x04, 0x75, + 0x4e, 0x03, 0x22, 0xe5, 0x35, 0x24, 0xff, 0xf5, + 0x35, 0xe5, 0x36, 0x34, 0xff, 0xf5, 0x36, 0x75, + 0x4e, 0x03, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x02, 0x2c, + 0x70, 0xd2, 0x00, 0x78, 0x11, 0xe2, 0x44, 0x11, + 0xf5, 0x3f, 0xc2, 0x08, 0x12, 0x29, 0xa3, 0x02, + 0x23, 0x93, 0x21, 0x62, 0x61, 0x40, 0x01, 0x3a, + 0x01, 0x73, 0x21, 0x76, 0x61, 0xa8, 0x21, 0x39, + 0x21, 0x4a, 0x02, 0x2a, 0x7b, 0x79, 0x06, 0xf3, + 0xc0, 0xd0, 0x12, 0x03, 0xd9, 0x78, 0x00, 0xf2, + 0xd0, 0xd0, 0x22, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x2c, 0xb4, 0x78, 0x11, 0xe2, 0x44, 0x11, 0x54, + 0x0f, 0xf8, 0xc4, 0x48, 0xd2, 0x05, 0xf5, 0x48, + 0xc2, 0x0d, 0x31, 0xa3, 0x02, 0x23, 0x93, 0x20, + 0x4b, 0x04, 0x75, 0x4e, 0x01, 0x22, 0xe5, 0x35, + 0x24, 0xff, 0xf5, 0x35, 0xe5, 0x36, 0x34, 0xff, + 0xf5, 0x36, 0x75, 0x4e, 0x01, 0x22, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x79, 0xd0, 0x77, 0x1b, 0x79, 0xd1, 0x77, 0x18, + 0x79, 0xd2, 0x77, 0x77, 0x79, 0xd3, 0x77, 0x18, + 0x22, 0x75, 0x29, 0x00, 0x75, 0x25, 0x00, 0x75, + 0x34, 0x03, 0x75, 0x22, 0x00, 0x75, 0x23, 0x05, + 0x75, 0x4f, 0x00, 0x75, 0x50, 0x00, 0x75, 0x30, + 0x00, 0x79, 0xdc, 0x77, 0x03, 0xc2, 0x8e, 0x75, + 0x17, 0xa8, 0x75, 0x16, 0xa8, 0x74, 0xaa, 0x79, + 0x01, 0xf3, 0x79, 0xd7, 0x77, 0x74, 0x79, 0xd8, + 0x77, 0xff, 0x79, 0xd9, 0x77, 0x07, 0x79, 0xda, + 0x77, 0x00, 0x12, 0x25, 0x6f, 0x43, 0x08, 0x40, + 0x71, 0x32, 0x79, 0x0e, 0xe3, 0x10, 0x51, 0x1c, + 0x74, 0x06, 0x71, 0x9b, 0xe5, 0x11, 0x44, 0x80, + 0x79, 0x05, 0xf3, 0xf5, 0x11, 0x74, 0x07, 0x71, + 0x9b, 0xe5, 0x12, 0x44, 0x80, 0x79, 0x05, 0xf3, + 0xf5, 0x12, 0x80, 0x18, 0x53, 0x27, 0xa0, 0x53, + 0x28, 0x01, 0x75, 0x20, 0xf7, 0x12, 0x23, 0x4c, + 0x75, 0x11, 0x80, 0x75, 0x12, 0x80, 0x12, 0x1f, + 0xc0, 0x12, 0x21, 0xdc, 0x79, 0x06, 0xf3, 0x22, + 0xd2, 0x02, 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, + 0x43, 0xc2, 0x0a, 0x12, 0x29, 0xa3, 0x02, 0x23, + 0x93, 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, 0x44, + 0xc2, 0x0b, 0x12, 0x29, 0xa3, 0x02, 0x23, 0x93, + 0x78, 0x00, 0xe2, 0x90, 0x25, 0x9f, 0x02, 0x23, + 0x93, 0x78, 0x11, 0xe2, 0x75, 0x20, 0xf7, 0x75, + 0x21, 0x3f, 0x75, 0x49, 0x11, 0x75, 0x4c, 0x11, + 0x31, 0xa3, 0x02, 0x23, 0x93, 0x78, 0x11, 0xe2, + 0x44, 0x11, 0x54, 0x0f, 0xf8, 0xc4, 0x48, 0xf8, + 0xe5, 0x49, 0x45, 0x3f, 0x58, 0xf5, 0x49, 0xd2, + 0x06, 0xc2, 0x0e, 0x31, 0xa3, 0x02, 0x23, 0x93, + 0xc0, 0x01, 0x20, 0x2a, 0x04, 0x71, 0x32, 0xc2, + 0x11, 0x11, 0x5e, 0xc2, 0x1f, 0xd0, 0x01, 0x02, + 0x23, 0x9b, 0x12, 0x21, 0xdc, 0x78, 0x00, 0xf2, + 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xda, + 0xe7, 0x70, 0x2b, 0x20, 0x0a, 0x05, 0x85, 0x43, + 0xe0, 0x80, 0x03, 0x75, 0xe0, 0x00, 0x30, 0xe1, + 0x1d, 0x20, 0xe2, 0x1f, 0x74, 0xe0, 0xca, 0x74, + 0x00, 0x71, 0x9b, 0xca, 0x79, 0x05, 0xf3, 0xf5, + 0x09, 0xca, 0x74, 0x01, 0x71, 0x9b, 0xca, 0x79, + 0x05, 0xf3, 0xf5, 0x0a, 0x80, 0x43, 0x12, 0x15, + 0x3e, 0x80, 0x3e, 0xe5, 0x0b, 0xb4, 0x17, 0x02, + 0x80, 0x0b, 0x50, 0x09, 0x74, 0x17, 0xc3, 0x95, + 0x0b, 0x44, 0x60, 0x80, 0x02, 0x74, 0x60, 0xca, + 0x74, 0x00, 0x71, 0x9b, 0xca, 0x79, 0x05, 0xf3, + 0xf5, 0x09, 0xe5, 0x0c, 0xb4, 0x17, 0x02, 0x80, + 0x0b, 0x50, 0x09, 0x74, 0x17, 0xc3, 0x95, 0x0c, + 0x44, 0x60, 0x80, 0x02, 0x74, 0x60, 0xca, 0x74, + 0x01, 0x71, 0x9b, 0xca, 0x79, 0x05, 0xf3, 0xf5, + 0x0a, 0x22, 0xd2, 0x04, 0x78, 0x11, 0xe2, 0x44, + 0x11, 0xf5, 0x46, 0xc2, 0x0c, 0x31, 0xa3, 0x02, + 0x23, 0x93, 0xd2, 0x05, 0x78, 0x11, 0xe2, 0x44, + 0x11, 0xf5, 0x48, 0xc2, 0x0d, 0x31, 0xa3, 0x02, + 0x23, 0x93, 0xd2, 0x06, 0x78, 0x11, 0xe2, 0x44, + 0x11, 0xf5, 0x49, 0xc2, 0x0e, 0x31, 0xa3, 0x02, + 0x23, 0x93, 0x30, 0x1c, 0x21, 0x20, 0x4d, 0x1e, + 0xe5, 0x29, 0x60, 0x1a, 0xc2, 0x1c, 0x12, 0x19, + 0xec, 0x12, 0x13, 0xcf, 0xd2, 0x4d, 0x12, 0x17, + 0x7f, 0x78, 0x00, 0xf2, 0x79, 0x06, 0xf3, 0x43, + 0xa8, 0x04, 0x12, 0x24, 0x1b, 0x22, 0x12, 0x27, + 0x24, 0x22, 0x78, 0x00, 0xe2, 0x90, 0x25, 0x9f, + 0x02, 0x23, 0x93, 0x78, 0x00, 0xe2, 0xa2, 0xe7, + 0x72, 0xe3, 0x92, 0xe7, 0x02, 0x1d, 0x85, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x79, 0x04, 0xe3, 0x54, 0x80, 0x70, 0xf9, 0x22, + 0xe5, 0x29, 0x79, 0xde, 0xf7, 0x75, 0x29, 0x00, + 0x70, 0x12, 0xe5, 0x15, 0x79, 0xdd, 0xf7, 0x12, + 0x2d, 0xf0, 0x40, 0x08, 0x20, 0x1c, 0x07, 0x20, + 0x1d, 0x04, 0x80, 0x02, 0x71, 0x32, 0x30, 0xb5, + 0x0c, 0x79, 0x06, 0xf3, 0x20, 0x2a, 0x06, 0x79, + 0xdd, 0xe7, 0x54, 0xfc, 0xf7, 0xd2, 0x2b, 0x12, + 0x25, 0x6f, 0x22, 0x00, 0x00, 0x00, 0x00, 0xe5, + 0x15, 0xa2, 0xe0, 0xb0, 0xe6, 0x40, 0x31, 0xa2, + 0xe1, 0xb0, 0xe7, 0x40, 0x38, 0x10, 0x2b, 0x02, + 0x80, 0x26, 0x79, 0xde, 0xe7, 0x70, 0x0b, 0x79, + 0xdd, 0xe7, 0x20, 0xe0, 0x12, 0x20, 0xe1, 0x28, + 0x80, 0x16, 0xf5, 0x29, 0x30, 0x4d, 0x11, 0x20, + 0x4c, 0x0e, 0x12, 0x24, 0x1b, 0x80, 0x09, 0x43, + 0x08, 0x40, 0x12, 0x13, 0xcf, 0x12, 0x17, 0x7f, + 0xe5, 0x13, 0x20, 0xe4, 0x05, 0x12, 0x18, 0x1b, + 0x80, 0x03, 0x12, 0x18, 0x77, 0xc2, 0x2b, 0x22, + 0x12, 0x26, 0xd7, 0x12, 0x13, 0xb7, 0x22, 0x78, + 0x04, 0x79, 0x00, 0xd9, 0xfe, 0xd8, 0xfa, 0x22, + 0x00, 0x74, 0x09, 0x71, 0x9b, 0xe5, 0x15, 0x54, + 0xfc, 0x79, 0x05, 0xf3, 0xf5, 0x15, 0x22, 0x78, + 0x11, 0xe2, 0x44, 0x11, 0x54, 0x0f, 0xf8, 0xc4, + 0x48, 0xf5, 0x46, 0xc2, 0x0c, 0xd2, 0x04, 0x31, + 0xa3, 0x02, 0x23, 0x93, 0x12, 0x26, 0xd7, 0x12, + 0x00, 0xb7, 0x22, 0x00, 0x79, 0x06, 0xf3, 0x74, + 0x0a, 0x71, 0x9b, 0x79, 0xe0, 0xe7, 0x44, 0x02, + 0xf7, 0x79, 0x05, 0xf3, 0x22, 0x74, 0x0a, 0x71, + 0x9b, 0x79, 0xe0, 0xe7, 0x54, 0xfd, 0xf7, 0x79, + 0x05, 0xf3, 0x22, 0x21, 0x59, 0x41, 0x23, 0x21, + 0x59, 0x41, 0x33, 0x41, 0x43, 0x21, 0x59, 0x21, + 0x59, 0x02, 0x25, 0x9f, 0x00, 0x74, 0x0d, 0x71, + 0x9b, 0x74, 0x4d, 0x79, 0x05, 0xf3, 0xd2, 0x52, + 0x22, 0x00, 0x53, 0x08, 0x40, 0x45, 0x08, 0x45, + 0x1e, 0x79, 0x04, 0xf3, 0xf5, 0x08, 0x22, 0xd2, + 0x01, 0x78, 0x11, 0xe2, 0x44, 0x11, 0xf5, 0x42, + 0xc2, 0x09, 0x31, 0xa3, 0x02, 0x23, 0x93, 0x00, + 0x00, 0x00, 0x00, 0x71, 0x6e, 0x74, 0x09, 0x12, + 0x17, 0x75, 0xe5, 0x15, 0x44, 0x40, 0x79, 0x05, + 0xf3, 0xf5, 0x15, 0x75, 0x3a, 0x00, 0x12, 0x1a, + 0x77, 0x02, 0x18, 0x1b, 0xf5, 0x38, 0xe5, 0x37, + 0x24, 0x01, 0xf5, 0x37, 0xe5, 0x38, 0x34, 0x00, + 0xf5, 0x38, 0x40, 0x05, 0x75, 0x39, 0x00, 0x80, + 0x03, 0x75, 0x39, 0x01, 0x12, 0x04, 0x04, 0xd2, + 0x8e, 0x02, 0x03, 0x8d, 0x00, 0xb4, 0x0d, 0x03, + 0x74, 0x14, 0x22, 0x04, 0x83, 0x22, 0x00, 0x02, + 0xff, 0x01, 0x00, 0x05, 0xfe, 0xff, 0x00, 0x0a, + 0xfc, 0xfe, 0x00, 0xc0, 0xf8, 0xfc, 0x00, 0x28, + 0xf0, 0xf8, 0x00, 0x30, 0xe0, 0xd0, 0x01, 0x88, + 0x04, 0x83, 0x22, 0x00, 0xff, 0xfe, 0xfd, 0xfc, + 0xfc, 0xfb, 0xfa, 0xfe, 0xfd, 0xfb, 0xf9, 0xf7, + 0xf7, 0xf5, 0xf3, 0xfc, 0xfa, 0xf6, 0xf2, 0xee, + 0xee, 0xea, 0xe6, 0xf8, 0xf4, 0xec, 0xe4, 0xdc, + 0xd4, 0xcc, 0xc4, 0x24, 0x21, 0x83, 0x22, 0x04, + 0x83, 0x22, 0xff, 0x01, 0xff, 0x01, 0x00, 0x00, + 0x00, 0x02, 0x22, 0x32, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x83, + 0x22, 0x8a, 0x01, 0x20, 0x01, 0x0b, 0xea, 0xf3, + 0xf9, 0x8b, 0x7e, 0x6b, 0xd5, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x3a, 0x01, 0x38, 0x01, 0x4b, 0x01, + 0x49, 0x01, 0x5c, 0x01, 0x5a, 0x01, 0x08, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x15, 0x24, 0x48, 0x83, 0x22, 0x04, + 0x83, 0x22, 0x00, 0x01, 0x02, 0x03, 0x04, 0x06, + 0x07, 0x08, 0x00, 0x03, 0x05, 0x07, 0x09, 0x0d, + 0x0f, 0x81, 0x00, 0x06, 0x0a, 0x0e, 0x82, 0x8a, + 0x8e, 0x22, 0x00, 0x0c, 0x84, 0x8c, 0x24, 0x2c, + 0xa4, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xaa, 0x35, 0xab, 0x36, + 0x02, 0x27, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x25, + 0x03, 0x03, 0x2b, 0x03, 0x00, 0x03, 0x00, 0x03, + 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x22, + 0x00, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, + 0x2b, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02, + 0x21, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, + 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x21, + 0x01, 0x02, 0x21, 0x02, 0x02, 0x02, 0x00, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x20, 0xb5, 0x05, + 0x79, 0x0f, 0xf3, 0xc2, 0x11, 0x22, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, + 0x15, 0xa2, 0xe0, 0xb0, 0xe6, 0x50, 0x01, 0x22, + 0xa2, 0xe1, 0xb0, 0xe7, 0x22, 0x02, 0x00}; + static unsigned char Data0485_0C[] = { + 0x02, 0x27, 0x69}; + static unsigned char Data0485_66[] = { + 0x02, 0x25, 0x47, 0x02, 0x25, 0x60}; + static unsigned char Data0485_60[] = { + 0x02, 0x22, 0x7e}; + static unsigned char Data0485_99[] = { + 0xc2, 0x53, 0x02, 0x12, 0x86}; + static unsigned char Data0485_9E[] = { + 0x70, 0xf9, 0x22}; +#ifdef OOKUBO_ORIGINAL + static unsigned char Data0485_36[] = { + 0x78, 0x00, 0xf2, 0xc2, 0x53, 0x74, 0x86, 0xc0, + 0xe0, 0x74, 0x12, 0xc0, 0xe0, 0x32}; +#endif /* OOKUBO_ORIGINAL */ diff -urN linux-2.5.65-bk2/sound/isa/cs423x/sound_pc9800.h linux-2.5.65-bk3/sound/isa/cs423x/sound_pc9800.h --- linux-2.5.65-bk2/sound/isa/cs423x/sound_pc9800.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.65-bk3/sound/isa/cs423x/sound_pc9800.h Mon Mar 31 12:41:50 2003 @@ -0,0 +1,23 @@ +#ifndef _SOUND_PC9800_H_ +#define _SOUND_PC9800_H_ + +#include + +#define PC9800_SOUND_IO_ID 0xa460 + +/* Sound Functions ID. */ +#define PC9800_SOUND_ID() ((inb(PC9800_SOUND_IO_ID) >> 4) & 0x0f) + +#define PC9800_SOUND_ID_DO 0x0 /* PC-98DO+ Internal */ +#define PC9800_SOUND_ID_GS 0x1 /* PC-98GS Internal */ +#define PC9800_SOUND_ID_73 0x2 /* PC-9801-73 (base 0x18x) */ +#define PC9800_SOUND_ID_73A 0x3 /* PC-9801-73/76 (base 0x28x) */ +#define PC9800_SOUND_ID_86 0x4 /* PC-9801-86 and compatible (base 0x18x) */ +#define PC9800_SOUND_ID_86A 0x5 /* PC-9801-86 (base 0x28x) */ +#define PC9800_SOUND_ID_NF 0x6 /* PC-9821Nf/Np Internal */ +#define PC9800_SOUND_ID_XMATE 0x7 /* X-Mate Internal and compatible */ +#define PC9800_SOUND_ID_118 0x8 /* PC-9801-118 and compatible(CanBe Internal, etc.) */ + +#define PC9800_SOUND_ID_UNKNOWN 0xf /* Unknown (No Sound System or PC-9801-26) */ + +#endif diff -urN linux-2.5.65-bk2/sound/isa/opti9xx/opti92x-ad1848.c linux-2.5.65-bk3/sound/isa/opti9xx/opti92x-ad1848.c --- linux-2.5.65-bk2/sound/isa/opti9xx/opti92x-ad1848.c Mon Mar 31 12:41:37 2003 +++ linux-2.5.65-bk3/sound/isa/opti9xx/opti92x-ad1848.c Mon Mar 31 12:41:50 2003 @@ -326,11 +326,11 @@ static long snd_legacy_find_free_ioport(long *port_table, long size) { while (*port_table != -1) { - if (!check_region(*port_table, size)) + if (request_region(*port_table, size, "opti92x-ad1848")) return *port_table; port_table++; } - return -1; + return SNDRV_AUTO_PORT; } static int __init snd_opti9xx_init(opti9xx_t *chip, unsigned short hardware) @@ -1917,6 +1917,10 @@ #ifdef __ISAPNP__ snd_card_opti9xx_deactivate(chip); #endif /* __ISAPNP__ */ + if (chip->wss_base != SNDRV_AUTO_PORT) + release_region(chip->wss_base, 4); + if (chip->mpu_port != SNDRV_AUTO_PORT) + release_region(chip->mpu_port, 2); if (chip->res_mc_base) { release_resource(chip->res_mc_base); kfree_nocheck(chip->res_mc_base); @@ -1962,6 +1966,16 @@ card->private_free = snd_card_opti9xx_free; chip = (opti9xx_t *)card->private_data; + chip->wss_base = port; + chip->fm_port = fm_port; + chip->mpu_port = mpu_port; + chip->irq = irq; + chip->mpu_irq = mpu_irq; + chip->dma1 = dma1; +#if defined(CS4231) || defined(OPTi93X) + chip->dma2 = dma2; +#endif + #ifdef __ISAPNP__ if (isapnp && (hw = snd_card_opti9xx_isapnp(chip)) > 0) { switch (hw) { @@ -2000,28 +2014,18 @@ return -ENOMEM; } - chip->wss_base = port; - chip->fm_port = fm_port; - chip->mpu_port = mpu_port; - chip->irq = irq; - chip->mpu_irq = mpu_irq; - chip->dma1 = dma1; -#if defined(CS4231) || defined(OPTi93X) - chip->dma2 = dma2; -#endif - #ifdef __ISAPNP__ if (!isapnp) { #endif if (chip->wss_base == SNDRV_AUTO_PORT) { - if ((chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) { + if ((chip->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) == SNDRV_AUTO_PORT) { snd_card_free(card); snd_printk("unable to find a free WSS port\n"); return -EBUSY; } } if (chip->mpu_port == SNDRV_AUTO_PORT) { - if ((chip->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) { + if ((chip->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) == SNDRV_AUTO_PORT) { snd_card_free(card); snd_printk("unable to find a free MPU401 port\n"); return -EBUSY; diff -urN linux-2.5.65-bk2/sound/isa/sb/es968.c linux-2.5.65-bk3/sound/isa/sb/es968.c --- linux-2.5.65-bk2/sound/isa/sb/es968.c Mon Mar 31 12:41:37 2003 +++ linux-2.5.65-bk3/sound/isa/sb/es968.c Mon Mar 31 12:41:50 2003 @@ -23,11 +23,7 @@ #include #include #include -#ifndef LINUX_ISAPNP_H -#include -#define isapnp_card pci_bus -#define isapnp_dev pci_dev -#endif +#include #include #define SNDRV_GET_ID #include @@ -35,6 +31,8 @@ #define chip_t sb_t +#define PFX "es968: " + MODULE_AUTHOR("Massimo Piccioni "); MODULE_DESCRIPTION("ESS AudioDrive ES968"); MODULE_LICENSE("GPL"); @@ -68,32 +66,18 @@ MODULE_PARM_SYNTAX(dma8, SNDRV_DMA8_DESC); struct snd_card_es968 { -#ifdef __ISAPNP__ - struct isapnp_dev *dev; -#endif /* __ISAPNP__ */ + struct pnp_dev *dev; }; -static snd_card_t *snd_es968_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; - -#ifdef __ISAPNP__ -static struct isapnp_card *snd_es968_isapnp_cards[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR; -static const struct isapnp_card_id *snd_es968_isapnp_id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR; - -static struct isapnp_card_id snd_es968_pnpids[] __devinitdata = { - { - ISAPNP_CARD_ID('E','S','S',0x0968), - .devs = { ISAPNP_DEVICE_ID('E','S','S',0x0968), } - }, - { ISAPNP_CARD_END, } +static struct pnp_card_id snd_es968_pnpids[] __devinitdata = { + { .id = "ESS0968", .devs = { { "@@@0968" }, } }, + { .id = "", } /* end */ }; -ISAPNP_CARD_TABLE(snd_es968_pnpids); - -#endif /* __ISAPNP__ */ +MODULE_DEVICE_TABLE(pnp_card, snd_es968_pnpids); #define DRIVER_NAME "snd-card-es968" - static void snd_card_es968_interrupt(int irq, void *dev_id, struct pt_regs *regs) { @@ -106,64 +90,50 @@ } } -#ifdef __ISAPNP__ -static int __init snd_card_es968_isapnp(int dev, struct snd_card_es968 *acard) -{ - const struct isapnp_card_id *id = snd_es968_isapnp_id[dev]; - struct isapnp_card *card = snd_es968_isapnp_cards[dev]; - struct isapnp_dev *pdev; - - acard->dev = isapnp_find_dev(card, id->devs[0].vendor, id->devs[0].function, NULL); - if (acard->dev->active) { - acard->dev = NULL; - return -EBUSY; +static int __devinit snd_card_es968_isapnp(int dev, struct snd_card_es968 *acard, + struct pnp_card_link *card, + const struct pnp_card_id *id) +{ + struct pnp_dev *pdev; + struct pnp_resource_table * cfg = kmalloc(GFP_ATOMIC, sizeof(struct pnp_resource_table)); + int err; + if (!cfg) + return -ENOMEM; + acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); + if (acard->dev == NULL) { + kfree(cfg); + return -ENODEV; } pdev = acard->dev; - if (pdev->prepare(pdev)<0) - return -EAGAIN; + pnp_init_resource_table(cfg); + + /* override resources */ if (port[dev] != SNDRV_AUTO_PORT) - isapnp_resource_change(&pdev->resource[0], port[dev], 16); + pnp_resource_change(&cfg->port_resource[0], port[dev], 16); if (dma8[dev] != SNDRV_AUTO_DMA) - isapnp_resource_change(&pdev->dma_resource[0], dma8[dev], - 1); + pnp_resource_change(&cfg->dma_resource[0], dma8[dev], 1); if (irq[dev] != SNDRV_AUTO_IRQ) - isapnp_resource_change(&pdev->irq_resource[0], irq[dev], 1); - - if (pdev->activate(pdev)<0) { - snd_printk("AUDIO isapnp configure failure\n"); - return -EBUSY; - } - - port[dev] = pdev->resource[0].start; - dma8[dev] = pdev->dma_resource[0].start; - irq[dev] = pdev->irq_resource[0].start; + pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1); + if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0) + printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n"); + err = pnp_activate_dev(pdev); + if (err < 0) { + printk(KERN_ERR PFX "AUDIO pnp configure failure\n"); + return err; + } + port[dev] = pnp_port_start(pdev, 0); + dma8[dev] = pnp_dma(pdev, 1); + irq[dev] = pnp_irq(pdev, 0); + kfree(cfg); return 0; } -static void snd_card_es968_deactivate(struct snd_card_es968 *acard) -{ - if (acard->dev) { - acard->dev->deactivate(acard->dev); - acard->dev = NULL; - } -} -#endif /* __ISAPNP__ */ - -static void snd_card_es968_free(snd_card_t *card) -{ - struct snd_card_es968 *acard = (struct snd_card_es968 *)card->private_data; - - if (acard) { -#ifdef __ISAPNP__ - snd_card_es968_deactivate(acard); -#endif /* __ISAPNP__ */ - } -} - -static int __init snd_card_es968_probe(int dev) +static int __init snd_card_es968_probe(int dev, + struct pnp_card_link *pcard, + const struct pnp_card_id *pid) { int error; sb_t *chip; @@ -174,18 +144,10 @@ sizeof(struct snd_card_es968))) == NULL) return -ENOMEM; acard = (struct snd_card_es968 *)card->private_data; - card->private_free = snd_card_es968_free; - -#ifdef __ISAPNP__ - if ((error = snd_card_es968_isapnp(dev, acard))) { + if ((error = snd_card_es968_isapnp(dev, acard, pcard, pid))) { snd_card_free(card); return error; } -#else - snd_printk("you have to enable PnP support ...\n"); - snd_card_free(card); - return -ENOSYS; -#endif /* __ISAPNP__ */ if ((error = snd_sbdsp_create(card, port[dev], irq[dev], @@ -221,13 +183,12 @@ snd_card_free(card); return error; } - snd_es968_cards[dev] = card; + pnp_set_card_drvdata(pcard, card); return 0; } -#ifdef __ISAPNP__ -static int __init snd_es968_isapnp_detect(struct isapnp_card *card, - const struct isapnp_card_id *id) +static int __devinit snd_es968_pnp_detect(struct pnp_card_link *card, + const struct pnp_card_id *id) { static int dev; int res; @@ -235,9 +196,7 @@ for ( ; dev < SNDRV_CARDS; dev++) { if (!enable[dev]) continue; - snd_es968_isapnp_cards[dev] = card; - snd_es968_isapnp_id[dev] = id; - res = snd_card_es968_probe(dev); + res = snd_card_es968_probe(dev, card, id); if (res < 0) return res; dev++; @@ -245,30 +204,31 @@ } return -ENODEV; } -#endif /* __ISAPNP__ */ -static int __init alsa_card_es968_init(void) +static void __devexit snd_es968_pnp_remove(struct pnp_card_link * pcard) { - int cards = 0; + snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard); -#ifdef __ISAPNP__ - cards += isapnp_probe_cards(snd_es968_pnpids, snd_es968_isapnp_detect); -#else - snd_printk("you have to enable ISA PnP support.\n"); -#endif -#ifdef MODULE - if (!cards) - snd_printk("no ES968 based soundcards found\n"); -#endif - return cards ? 0 : -ENODEV; + snd_card_disconnect(card); + snd_card_free_in_thread(card); } -static void __exit alsa_card_es968_exit(void) +static struct pnp_card_driver es968_pnpc_driver = { + .flags = PNP_DRIVER_RES_DISABLE, + .name = "es968", + .id_table = snd_es968_pnpids, + .probe = snd_es968_pnp_detect, + .remove = __devexit_p(snd_es968_pnp_remove), +}; + +static int __init alsa_card_es968_init(void) { - int dev; + return (pnp_register_card_driver(&es968_pnpc_driver) ? 0 : -ENODEV); +} - for (dev = 0; dev < SNDRV_CARDS; dev++) - snd_card_free(snd_es968_cards[dev]); +static void __exit alsa_card_es968_exit(void) +{ + pnp_unregister_card_driver(&es968_pnpc_driver); } module_init(alsa_card_es968_init) diff -urN linux-2.5.65-bk2/sound/oss/Kconfig linux-2.5.65-bk3/sound/oss/Kconfig --- linux-2.5.65-bk2/sound/oss/Kconfig Mon Mar 17 13:44:41 2003 +++ linux-2.5.65-bk3/sound/oss/Kconfig Mon Mar 31 12:41:50 2003 @@ -113,15 +113,17 @@ Say Y or M if you have a PCI sound card using the EMU10K1 chipset, such as the Creative SBLive!, SB PCI512 or Emu-APS. - For more information on this driver and the degree of support for the - different card models please check . + For more information on this driver and the degree of support for + the different card models please check: + + It is now possible to load dsp microcode patches into the EMU10K1 chip. These patches are used to implement real time sound processing effects which include for example: signal routing, bass/treble control, AC3 passthrough, ... Userspace tools to create new patches and load/unload them can be - found at . + found in the emu-tools package at the above URL. config MIDI_EMU10K1 bool "Creative SBLive! MIDI (EXPERIMENTAL)" diff -urN linux-2.5.65-bk2/sound/oss/audio_syms.c linux-2.5.65-bk3/sound/oss/audio_syms.c --- linux-2.5.65-bk2/sound/oss/audio_syms.c Mon Mar 17 13:43:44 2003 +++ linux-2.5.65-bk3/sound/oss/audio_syms.c Mon Mar 31 12:41:50 2003 @@ -1,9 +1,7 @@ /* * Exported symbols for audio driver. - * __NO_VERSION__ because this is still part of sound.o. */ -#define __NO_VERSION__ #include char audio_syms_symbol; diff -urN linux-2.5.65-bk2/sound/oss/cs46xx.c linux-2.5.65-bk3/sound/oss/cs46xx.c --- linux-2.5.65-bk2/sound/oss/cs46xx.c Mon Mar 17 13:43:37 2003 +++ linux-2.5.65-bk3/sound/oss/cs46xx.c Mon Mar 31 12:41:50 2003 @@ -4314,7 +4314,7 @@ { offset = ClrStat[i].BA1__DestByteOffset; count = ClrStat[i].BA1__SourceSize; - for( temp1 = offset; temp1<(offset+count); temp1+=4 ); + for( temp1 = offset; temp1<(offset+count); temp1+=4 ) writel(0, pBA1+temp1); } diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/audio.c linux-2.5.65-bk3/sound/oss/emu10k1/audio.c --- linux-2.5.65-bk2/sound/oss/emu10k1/audio.c Mon Mar 17 13:43:40 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/audio.c Mon Mar 31 12:41:50 2003 @@ -30,7 +30,6 @@ ********************************************************************** */ -#define __NO_VERSION__ #include #include #include @@ -983,11 +982,11 @@ unsigned long pgoff; int rd, wr; - DPF(4, "emu10k1_mm_nopage()\n"); - DPD(4, "addr: %#lx\n", address); + DPF(3, "emu10k1_mm_nopage()\n"); + DPD(3, "addr: %#lx\n", address); if (address > vma->vm_end) { - DPF(2, "EXIT, returning NOPAGE_SIGBUS\n"); + DPF(1, "EXIT, returning NOPAGE_SIGBUS\n"); return NOPAGE_SIGBUS; /* Disallow mremap */ } @@ -1009,14 +1008,14 @@ pgoff -= woinst->buffer.pages; dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE); } else - dmapage = virt_to_page (woinst->buffer.mem[0].addr[pgoff]); + dmapage = virt_to_page (woinst->voice[0].mem.addr[pgoff]); } else { dmapage = virt_to_page ((u8 *) wiinst->buffer.addr + pgoff * PAGE_SIZE); } get_page (dmapage); - DPD(4, "page: %#lx\n", dmapage); + DPD(3, "page: %#lx\n", (unsigned long) dmapage); return dmapage; } @@ -1083,8 +1082,8 @@ n_pages = ((vma->vm_end - vma->vm_start) + PAGE_SIZE - 1) >> PAGE_SHIFT; pgoffset = vma->vm_pgoff; - DPD(3, "vma_start: %#lx, vma_end: %#lx, vma_offset: %d\n", vma->vm_start, vma->vm_end, pgoffset); - DPD(3, "n_pages: %d, max_pages: %d\n", n_pages, max_pages); + DPD(2, "vma_start: %#lx, vma_end: %#lx, vma_offset: %ld\n", vma->vm_start, vma->vm_end, pgoffset); + DPD(2, "n_pages: %ld, max_pages: %ld\n", n_pages, max_pages); if (pgoffset + n_pages > max_pages) return -EINVAL; @@ -1092,7 +1091,6 @@ vma->vm_flags |= VM_RESERVED; vma->vm_ops = &emu10k1_mm_ops; vma->vm_private_data = wave_dev; - return 0; } @@ -1136,7 +1134,8 @@ if ((wiinst = (struct wiinst *) kmalloc(sizeof(struct wiinst), GFP_KERNEL)) == NULL) { ERROR(); - return -ENODEV; + kfree(wave_dev); + return -ENOMEM; } wiinst->recsrc = card->wavein.recsrc; @@ -1162,6 +1161,8 @@ wiinst->format.channels = hweight32(wiinst->fxwc); break; default: + kfree(wave_dev); + kfree(wiinst); BUG(); break; } @@ -1211,7 +1212,7 @@ woinst->num_voices = 1; for (i = 0; i < WAVEOUT_MAXVOICES; i++) { woinst->voice[i].usage = VOICE_USAGE_FREE; - woinst->buffer.mem[i].emupageindex = -1; + woinst->voice[i].mem.emupageindex = -1; } init_waitqueue_head(&woinst->wait_queue); @@ -1330,23 +1331,13 @@ if (file->f_mode & FMODE_READ) { spin_lock_irqsave(&wiinst->lock, flags); - if (wiinst->state == WAVE_STATE_CLOSED) { - calculate_ifrag(wiinst); - if (emu10k1_wavein_open(wave_dev) < 0) { - spin_unlock_irqrestore(&wiinst->lock, flags); - return (mask |= POLLERR); - } - } + if (wiinst->state & WAVE_STATE_OPEN) { + emu10k1_wavein_update(wave_dev->card, wiinst); + emu10k1_wavein_getxfersize(wiinst, &bytestocopy); - if (!(wiinst->state & WAVE_STATE_STARTED)) { - wave_dev->enablebits |= PCM_ENABLE_INPUT; - emu10k1_wavein_start(wave_dev); + if (bytestocopy >= wiinst->buffer.fragment_size) + mask |= POLLIN | POLLRDNORM; } - emu10k1_wavein_update(wave_dev->card, wiinst); - emu10k1_wavein_getxfersize(wiinst, &bytestocopy); - - if (bytestocopy >= wiinst->buffer.fragment_size) - mask |= POLLIN | POLLRDNORM; spin_unlock_irqrestore(&wiinst->lock, flags); } @@ -1376,6 +1367,13 @@ buffer->fragment_size = 1 << buffer->ossfragshift; + while (buffer->fragment_size * WAVEOUT_MINFRAGS > WAVEOUT_MAXBUFSIZE) + buffer->fragment_size >>= 1; + + /* now we are sure that: + (2^WAVEOUT_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEOUT_MAXBUFSIZE / WAVEOUT_MINFRAGS) + */ + if (!buffer->numfrags) { u32 numfrags; @@ -1390,19 +1388,14 @@ } } - if (buffer->numfrags < MINFRAGS) - buffer->numfrags = MINFRAGS; + if (buffer->numfrags < WAVEOUT_MINFRAGS) + buffer->numfrags = WAVEOUT_MINFRAGS; - if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE) { + if (buffer->numfrags * buffer->fragment_size > WAVEOUT_MAXBUFSIZE) buffer->numfrags = WAVEOUT_MAXBUFSIZE / buffer->fragment_size; - if (buffer->numfrags < MINFRAGS) { - buffer->numfrags = MINFRAGS; - buffer->fragment_size = WAVEOUT_MAXBUFSIZE / MINFRAGS; - } - - } else if (buffer->numfrags * buffer->fragment_size < WAVEOUT_MINBUFSIZE) - buffer->numfrags = WAVEOUT_MINBUFSIZE / buffer->fragment_size; + if (buffer->numfrags < WAVEOUT_MINFRAGS) + BUG(); buffer->size = buffer->fragment_size * buffer->numfrags; buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0); @@ -1436,24 +1429,29 @@ buffer->fragment_size = 1 << buffer->ossfragshift; + while (buffer->fragment_size * WAVEIN_MINFRAGS > WAVEIN_MAXBUFSIZE) + buffer->fragment_size >>= 1; + + /* now we are sure that: + (2^WAVEIN_MINFRAGSHIFT) <= (fragment_size = 2^n) <= (WAVEIN_MAXBUFSIZE / WAVEIN_MINFRAGS) + */ + + if (!buffer->numfrags) buffer->numfrags = (wiinst->format.bytespersec * WAVEIN_DEFAULTBUFLEN) / (buffer->fragment_size * 1000) - 1; - if (buffer->numfrags < MINFRAGS) - buffer->numfrags = MINFRAGS; + if (buffer->numfrags < WAVEIN_MINFRAGS) + buffer->numfrags = WAVEIN_MINFRAGS; - if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE) { + if (buffer->numfrags * buffer->fragment_size > WAVEIN_MAXBUFSIZE) buffer->numfrags = WAVEIN_MAXBUFSIZE / buffer->fragment_size; - if (buffer->numfrags < MINFRAGS) { - buffer->numfrags = MINFRAGS; - buffer->fragment_size = WAVEIN_MAXBUFSIZE / MINFRAGS; - } - } else if (buffer->numfrags * buffer->fragment_size < WAVEIN_MINBUFSIZE) - buffer->numfrags = WAVEIN_MINBUFSIZE / buffer->fragment_size; + if (buffer->numfrags < WAVEIN_MINFRAGS) + BUG(); bufsize = buffer->fragment_size * buffer->numfrags; + /* the buffer size for recording is restricted to certain values, adjust it now */ if (bufsize >= 0x10000) { buffer->size = 0x10000; buffer->sizeregval = 0x1f; @@ -1479,10 +1477,12 @@ } } + /* adjust the fragment size so that buffer size is an integer multiple */ + while (buffer->size % buffer->fragment_size) + buffer->fragment_size >>= 1; + buffer->numfrags = buffer->size / buffer->fragment_size; buffer->pages = buffer->size / PAGE_SIZE + ((buffer->size % PAGE_SIZE) ? 1 : 0); - if (buffer->size % buffer->fragment_size) - BUG(); DPD(2, " calculated recording fragment_size -> %d\n", buffer->fragment_size); DPD(2, " calculated recording numfrags -> %d\n", buffer->numfrags); diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/audio.h linux-2.5.65-bk3/sound/oss/emu10k1/audio.h --- linux-2.5.65-bk2/sound/oss/emu10k1/audio.h Mon Mar 17 13:44:46 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/audio.h Mon Mar 31 12:41:50 2003 @@ -33,8 +33,6 @@ #ifndef _AUDIO_H #define _AUDIO_H -#define MINFRAGS 2 /* _don't_ got bellow 2 */ - struct emu10k1_wavedevice { struct emu10k1_card *card; diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/cardwi.c linux-2.5.65-bk3/sound/oss/emu10k1/cardwi.c --- linux-2.5.65-bk2/sound/oss/emu10k1/cardwi.c Mon Mar 17 13:44:17 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/cardwi.c Mon Mar 31 12:41:50 2003 @@ -96,6 +96,7 @@ wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3; wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel; wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate; + wave_fmt->bytespervoicesample = wave_fmt->bytespersample; } static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer) @@ -120,7 +121,7 @@ struct emu10k1_card *card = wave_dev->card; struct wiinst *wiinst = wave_dev->wiinst; struct wiinst **wiinst_tmp = NULL; - u32 delay; + u16 delay; unsigned long flags; DPF(2, "emu10k1_wavein_open()\n"); @@ -169,6 +170,12 @@ emu10k1_set_record_src(card, wiinst); + emu10k1_reset_record(card, &wiinst->buffer); + + wiinst->buffer.hw_pos = 0; + wiinst->buffer.pos = 0; + wiinst->buffer.bytestocopy = 0; + delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec; emu10k1_timer_install(card, &wiinst->timer, delay / 2); @@ -222,10 +229,6 @@ emu10k1_start_record(card, &wiinst->buffer); emu10k1_timer_enable(wave_dev->card, &wiinst->timer); - wiinst->buffer.hw_pos = 0; - wiinst->buffer.pos = 0; - wiinst->buffer.bytestocopy = 0; - wiinst->state |= WAVE_STATE_STARTED; } @@ -249,7 +252,7 @@ { struct emu10k1_card *card = wave_dev->card; struct wiinst *wiinst = wave_dev->wiinst; - u32 delay; + u16 delay; DPF(2, "emu10k1_wavein_setformat()\n"); @@ -304,10 +307,9 @@ static void copy_block(u8 *dst, u8 * src, u32 str, u32 len, u8 cov) { - if (cov == 1) { - if (__copy_to_user(dst, src + str, len)) - return; - } else { + if (cov == 1) + __copy_to_user(dst, src + str, len); + else { u8 byte; u32 i; @@ -315,8 +317,7 @@ for (i = 0; i < len; i++) { byte = src[2 * i] ^ 0x80; - if (__copy_to_user(dst + i, &byte, 1)) - return; + __copy_to_user(dst + i, &byte, 1); } } } diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/cardwi.h linux-2.5.65-bk3/sound/oss/emu10k1/cardwi.h --- linux-2.5.65-bk2/sound/oss/emu10k1/cardwi.h Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/cardwi.h Mon Mar 31 12:41:50 2003 @@ -69,13 +69,14 @@ u16 fxwc; }; -#define WAVEIN_MAXBUFSIZE 65536 -#define WAVEIN_MINBUFSIZE 368 +#define WAVEIN_MAXBUFSIZE 65536 +#define WAVEIN_MINBUFSIZE 368 -#define WAVEIN_DEFAULTFRAGLEN 100 -#define WAVEIN_DEFAULTBUFLEN 1000 +#define WAVEIN_DEFAULTFRAGLEN 100 +#define WAVEIN_DEFAULTBUFLEN 1000 -#define WAVEIN_MINFRAGSHIFT 8 +#define WAVEIN_MINFRAGSHIFT 8 +#define WAVEIN_MINFRAGS 2 int emu10k1_wavein_open(struct emu10k1_wavedevice *); void emu10k1_wavein_close(struct emu10k1_wavedevice *); diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/cardwo.c linux-2.5.65-bk3/sound/oss/emu10k1/cardwo.c --- linux-2.5.65-bk2/sound/oss/emu10k1/cardwo.c Mon Mar 17 13:44:41 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/cardwo.c Mon Mar 31 12:41:50 2003 @@ -108,95 +108,20 @@ } wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3; + wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel; + wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate; if (wave_fmt->channels == 2) wave_fmt->bytespervoicesample = wave_fmt->channels * wave_fmt->bytesperchannel; else wave_fmt->bytespervoicesample = wave_fmt->bytesperchannel; - - wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel; - wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate; -} - -/** - * alloc_buffer - - * - * allocates the memory buffer for a voice. Two page tables are kept for each buffer. - * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable) - * is passed to the device so that it can do DMA to host memory. - * - */ -static int alloc_buffer(struct emu10k1_card *card, struct waveout_buffer *buffer, unsigned int voicenum) -{ - u32 pageindex, pagecount; - unsigned long busaddx; - int i; - - DPD(2, "requested pages is: %d\n", buffer->pages); - - if ((buffer->mem[voicenum].emupageindex = - emu10k1_addxmgr_alloc(buffer->pages * PAGE_SIZE, card)) < 0) - return -1; - - /* Fill in virtual memory table */ - for (pagecount = 0; pagecount < buffer->pages; pagecount++) { - if ((buffer->mem[voicenum].addr[pagecount] = - pci_alloc_consistent(card->pci_dev, PAGE_SIZE, - &buffer->mem[voicenum].dma_handle[pagecount])) == NULL) { - buffer->pages = pagecount; - return -1; - } - - DPD(2, "Virtual Addx: %p\n", buffer->mem[voicenum].addr[pagecount]); - - for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) { - busaddx = buffer->mem[voicenum].dma_handle[pagecount] + i * EMUPAGESIZE; - - DPD(3, "Bus Addx: %#lx\n", busaddx); - - pageindex = buffer->mem[voicenum].emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i; - - ((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex); - } - } - - return 0; -} - -/** - * free_buffer - - * - * frees the memory buffer for a voice. - */ -static void free_buffer(struct emu10k1_card *card, struct waveout_buffer *buffer, unsigned int voicenum) -{ - u32 pagecount, pageindex; - int i; - - if (buffer->mem[voicenum].emupageindex < 0) - return; - - for (pagecount = 0; pagecount < buffer->pages; pagecount++) { - pci_free_consistent(card->pci_dev, PAGE_SIZE, - buffer->mem[voicenum].addr[pagecount], - buffer->mem[voicenum].dma_handle[pagecount]); - - for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) { - pageindex = buffer->mem[voicenum].emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i; - ((u32 *) card->virtualpagetable.addr)[pageindex] = - cpu_to_le32((card->silentpage.dma_handle * 2) | pageindex); - } - } - - emu10k1_addxmgr_free(card, buffer->mem[voicenum].emupageindex); - buffer->mem[voicenum].emupageindex = -1; } static int get_voice(struct emu10k1_card *card, struct woinst *woinst, unsigned int voicenum) { struct emu_voice *voice = &woinst->voice[voicenum]; - /* Allocate voices here, if no voices available, return error. - * Init voice_allocdesc first.*/ + + /* Allocate voices here, if no voices available, return error. */ voice->usage = VOICE_USAGE_PLAYBACK; @@ -219,7 +144,7 @@ DPD(2, "Initial pitch --> %#x\n", voice->initial_pitch); - voice->startloop = (woinst->buffer.mem[voicenum].emupageindex << 12) / + voice->startloop = (voice->mem.emupageindex << 12) / woinst->format.bytespervoicesample; voice->endloop = voice->startloop + woinst->buffer.size / woinst->format.bytespervoicesample; voice->start = voice->startloop; @@ -297,12 +222,12 @@ struct woinst *woinst = wave_dev->woinst; struct waveout_buffer *buffer = &woinst->buffer; unsigned int voicenum; - u32 delay; + u16 delay; DPF(2, "emu10k1_waveout_open()\n"); for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) { - if (alloc_buffer(card, buffer, voicenum) < 0) { + if (emu10k1_voice_alloc_buffer(card, &woinst->voice[voicenum].mem, woinst->buffer.pages) < 0) { ERROR(); emu10k1_waveout_close(wave_dev); return -1; @@ -324,7 +249,7 @@ delay = (48000 * woinst->buffer.fragment_size) / (woinst->format.samplingrate * woinst->format.bytespervoicesample); - emu10k1_timer_install(card, &woinst->timer, delay / 2); + emu10k1_timer_install(card, &woinst->timer, delay); woinst->state = WAVE_STATE_OPEN; @@ -345,7 +270,7 @@ for (voicenum = 0; voicenum < woinst->num_voices; voicenum++) { emu10k1_voice_free(&woinst->voice[voicenum]); - free_buffer(card, &woinst->buffer, voicenum); + emu10k1_voice_free_buffer(card, &woinst->voice[voicenum].mem); } woinst->state = WAVE_STATE_CLOSED; @@ -371,7 +296,7 @@ struct emu10k1_card *card = wave_dev->card; struct woinst *woinst = wave_dev->woinst; unsigned int voicenum; - u32 delay; + u16 delay; DPF(2, "emu10k1_waveout_setformat()\n"); @@ -404,7 +329,7 @@ delay = (48000 * woinst->buffer.fragment_size) / (woinst->format.samplingrate * woinst->format.bytespervoicesample); - emu10k1_timer_install(card, &woinst->timer, delay / 2); + emu10k1_timer_install(card, &woinst->timer, delay); } return 0; @@ -449,7 +374,7 @@ pending_bytes = buffer->size - buffer->free_bytes; - buffer->fill_silence = (pending_bytes < (signed) buffer->fragment_size) ? 1 : 0; + buffer->fill_silence = (pending_bytes < (signed) buffer->fragment_size * 2) ? 1 : 0; if (pending_bytes > (signed) buffer->silence_bytes) { *total_free_bytes = (buffer->free_bytes + buffer->silence_bytes); @@ -483,17 +408,14 @@ if (len > PAGE_SIZE - pgoff) { k = PAGE_SIZE - pgoff; - if (__copy_from_user((u8 *)dst[pg] + pgoff, src, k)) - return; + __copy_from_user((u8 *)dst[pg] + pgoff, src, k); len -= k; while (len > PAGE_SIZE) { - if (__copy_from_user(dst[++pg], src + k, PAGE_SIZE)) - return; + __copy_from_user(dst[++pg], src + k, PAGE_SIZE); k += PAGE_SIZE; len -= PAGE_SIZE; } - if (__copy_from_user(dst[++pg], src + k, len)) - return; + __copy_from_user(dst[++pg], src + k, len); } else __copy_from_user((u8 *)dst[pg] + pgoff, src, len); @@ -511,15 +433,14 @@ unsigned int pg; unsigned int pgoff; unsigned int voice_num; - struct waveout_mem *mem = woinst->buffer.mem; + struct emu_voice *voice = woinst->voice; pg = str / PAGE_SIZE; pgoff = str % PAGE_SIZE; while (len) { for (voice_num = 0; voice_num < woinst->num_voices; voice_num++) { - if (__copy_from_user((u8 *)(mem[voice_num].addr[pg]) + pgoff, src, woinst->format.bytespervoicesample)) - return; + __copy_from_user((u8 *)(voice[voice_num].mem.addr[pg]) + pgoff, src, woinst->format.bytespervoicesample); src += woinst->format.bytespervoicesample; } @@ -544,7 +465,7 @@ unsigned int pg; unsigned int pgoff; unsigned int voice_num; - struct waveout_mem *mem = woinst->buffer.mem; + struct emu_voice *voice = woinst->voice; unsigned int k; pg = str / PAGE_SIZE; @@ -553,22 +474,22 @@ if (len > PAGE_SIZE - pgoff) { k = PAGE_SIZE - pgoff; for (voice_num = 0; voice_num < woinst->num_voices; voice_num++) - memset((u8 *)mem[voice_num].addr[pg] + pgoff, data, k); + memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, k); len -= k; while (len > PAGE_SIZE) { pg++; for (voice_num = 0; voice_num < woinst->num_voices; voice_num++) - memset(mem[voice_num].addr[pg], data, PAGE_SIZE); + memset(voice[voice_num].mem.addr[pg], data, PAGE_SIZE); len -= PAGE_SIZE; } pg++; for (voice_num = 0; voice_num < woinst->num_voices; voice_num++) - memset(mem[voice_num].addr[pg], data, len); + memset(voice[voice_num].mem.addr[pg], data, len); } else { for (voice_num = 0; voice_num < woinst->num_voices; voice_num++) - memset((u8 *)mem[voice_num].addr[pg] + pgoff, data, len); + memset((u8 *)voice[voice_num].mem.addr[pg] + pgoff, data, len); } } @@ -582,6 +503,7 @@ void emu10k1_waveout_xferdata(struct woinst *woinst, u8 *data, u32 *size) { struct waveout_buffer *buffer = &woinst->buffer; + struct voice_mem *mem = &woinst->voice[0].mem; u32 sizetocopy, sizetocopy_now, start; unsigned long flags; @@ -610,14 +532,14 @@ copy_ilv_block(woinst, start, data, sizetocopy_now); copy_ilv_block(woinst, 0, data + sizetocopy_now * woinst->num_voices, sizetocopy); } else { - copy_block(buffer->mem[0].addr, start, data, sizetocopy_now); - copy_block(buffer->mem[0].addr, 0, data + sizetocopy_now, sizetocopy); + copy_block(mem->addr, start, data, sizetocopy_now); + copy_block(mem->addr, 0, data + sizetocopy_now, sizetocopy); } } else { if (woinst->num_voices > 1) copy_ilv_block(woinst, start, data, sizetocopy); else - copy_block(buffer->mem[0].addr, start, data, sizetocopy); + copy_block(mem->addr, start, data, sizetocopy); } } @@ -674,7 +596,7 @@ { u32 hw_pos; u32 diff; - + /* There is no actual start yet */ if (!(woinst->state & WAVE_STATE_STARTED)) { hw_pos = woinst->buffer.hw_pos; diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/cardwo.h linux-2.5.65-bk3/sound/oss/emu10k1/cardwo.h --- linux-2.5.65-bk2/sound/oss/emu10k1/cardwo.h Mon Mar 17 13:44:22 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/cardwo.h Mon Mar 31 12:41:50 2003 @@ -39,20 +39,13 @@ /* setting this to other than a power of two may break some applications */ #define WAVEOUT_MAXBUFSIZE MAXBUFSIZE -#define WAVEOUT_MINBUFSIZE 64 #define WAVEOUT_DEFAULTFRAGLEN 20 /* Time to play a fragment in ms (latency) */ #define WAVEOUT_DEFAULTBUFLEN 500 /* Time to play the entire buffer in ms */ -#define WAVEOUT_MINFRAGSHIFT 6 -#define WAVEOUT_MAXVOICES 6 - -/* waveout_mem is cardwo internal */ -struct waveout_mem { - int emupageindex; - void *addr[BUFMAXPAGES]; - dma_addr_t dma_handle[BUFMAXPAGES]; -}; +#define WAVEOUT_MINFRAGSHIFT 6 /* Minimum fragment size in bytes is 2^6 */ +#define WAVEOUT_MINFRAGS 3 /* _don't_ go bellow 3, it would break silence filling */ +#define WAVEOUT_MAXVOICES 6 struct waveout_buffer { u16 ossfragshift; @@ -60,7 +53,6 @@ u32 fragment_size; /* in bytes units */ u32 size; /* in bytes units */ u32 pages; /* buffer size in page units*/ - struct waveout_mem mem[WAVEOUT_MAXVOICES]; u32 silence_pos; /* software cursor position (including silence bytes) */ u32 hw_pos; /* hardware cursor position */ u32 free_bytes; /* free bytes available on the buffer (not including silence bytes) */ diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/efxmgr.c linux-2.5.65-bk3/sound/oss/emu10k1/efxmgr.c --- linux-2.5.65-bk2/sound/oss/emu10k1/efxmgr.c Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/efxmgr.c Mon Mar 31 12:41:50 2003 @@ -38,7 +38,7 @@ struct dsp_patch *patch; struct dsp_rpatch *rpatch; char s[PATCH_NAME_SIZE + 4]; - u32 *gpr_used; + unsigned long *gpr_used; int i; DPD(2, "emu10k1_find_control_gpr(): %s %s\n", patch_name, gpr_name); @@ -103,7 +103,7 @@ card->ac97.mixer_state[oss_mixer] = (right << 8) | left; - if (!card->isaps) + if (!card->is_aps) card->ac97.write_mixer(&card->ac97, oss_mixer, left, right); emu10k1_set_volume_gpr(card, card->mgr.ctrl_gpr[oss_mixer][0], left, @@ -171,9 +171,8 @@ { struct patch_manager *mgr = &card->mgr; unsigned long flags; - int muting; - const s32 log2lin[5] ={ // attenuation (dB) + static const s32 log2lin[4] ={ // attenuation (dB) 0x7fffffff, // 0.0 0x7fffffff * 0.840896415253715 , // 1.5 0x7fffffff * 0.707106781186548, // 3.0 @@ -183,12 +182,10 @@ if (addr < 0) return; - muting = (scale == 0x10) ? 0x7f: scale; - vol = (100 - vol ) * scale / 100; // Thanks to the comp.dsp newsgroup for this neat trick: - vol = (vol >= muting) ? 0 : (log2lin[vol & 3] >> (vol >> 2)); + vol = (vol >= scale) ? 0 : (log2lin[vol & 3] >> (vol >> 2)); spin_lock_irqsave(&mgr->lock, flags); emu10k1_set_control_gpr(card, addr, vol, 0); diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/efxmgr.h linux-2.5.65-bk3/sound/oss/emu10k1/efxmgr.h --- linux-2.5.65-bk2/sound/oss/emu10k1/efxmgr.h Mon Mar 17 13:44:49 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/efxmgr.h Mon Mar 31 12:41:50 2003 @@ -35,9 +35,9 @@ #define WRITE_EFX(a, b, c) sblive_writeptr((a), MICROCODEBASE + (b), 0, (c)) #define OP(op, z, w, x, y) \ - do { WRITE_EFX(card, (pc) * 2, ((x) << 10) | (y)); \ - WRITE_EFX(card, (pc) * 2 + 1, ((op) << 20) | ((z) << 10) | (w)); \ - ++pc; } while (0) + do { WRITE_EFX(card, (pc) * 2, ((x) << 10) | (y)); \ + WRITE_EFX(card, (pc) * 2 + 1, ((op) << 20) | ((z) << 10) | (w)); \ + ++pc; } while (0) #define NUM_INPUTS 0x20 #define NUM_OUTPUTS 0x20 @@ -47,52 +47,52 @@ struct dsp_rpatch { char name[PATCH_NAME_SIZE]; - u16 code_start; - u16 code_size; + u16 code_start; + u16 code_size; - u32 gpr_used[NUM_GPRS / 32]; - u32 gpr_input[NUM_GPRS / 32]; - u32 route[NUM_OUTPUTS]; - u32 route_v[NUM_OUTPUTS]; + unsigned long gpr_used[NUM_GPRS / (sizeof(unsigned long) * 8) + 1]; + unsigned long gpr_input[NUM_GPRS / (sizeof(unsigned long) * 8) + 1]; + unsigned long route[NUM_OUTPUTS]; + unsigned long route_v[NUM_OUTPUTS]; }; struct dsp_patch { - char name[PATCH_NAME_SIZE]; - u8 id; - u32 input; /* bitmap of the lines used as inputs */ - u32 output; /* bitmap of the lines used as outputs */ - u16 code_start; - u16 code_size; - - u32 gpr_used[NUM_GPRS / 32]; /* bitmap of used gprs */ - u32 gpr_input[NUM_GPRS / 32]; - u8 traml_istart; /* starting address of the internal tram lines used */ - u8 traml_isize; /* number of internal tram lines used */ - - u8 traml_estart; - u8 traml_esize; - - u16 tramb_istart; /* starting address of the internal tram memory used */ - u16 tramb_isize; /* amount of internal memory used */ - u32 tramb_estart; - u32 tramb_esize; + char name[PATCH_NAME_SIZE]; + u8 id; + unsigned long input; /* bitmap of the lines used as inputs */ + unsigned long output; /* bitmap of the lines used as outputs */ + u16 code_start; + u16 code_size; + + unsigned long gpr_used[NUM_GPRS / (sizeof(unsigned long) * 8) + 1]; /* bitmap of used gprs */ + unsigned long gpr_input[NUM_GPRS / (sizeof(unsigned long) * 8) + 1]; + u8 traml_istart; /* starting address of the internal tram lines used */ + u8 traml_isize; /* number of internal tram lines used */ + + u8 traml_estart; + u8 traml_esize; + + u16 tramb_istart; /* starting address of the internal tram memory used */ + u16 tramb_isize; /* amount of internal memory used */ + u32 tramb_estart; + u32 tramb_esize; }; struct dsp_gpr { - u8 type; /* gpr type, STATIC, DYNAMIC, INPUT, OUTPUT, CONTROL */ - char name[GPR_NAME_SIZE]; /* gpr value, only valid for control gprs */ - s32 min, max; /* value range for this gpr, only valid for control gprs */ - u8 line; /* which input/output line is the gpr attached, only valid for input/output gprs */ - u8 usage; + u8 type; /* gpr type, STATIC, DYNAMIC, INPUT, OUTPUT, CONTROL */ + char name[GPR_NAME_SIZE]; /* gpr value, only valid for control gprs */ + s32 min, max; /* value range for this gpr, only valid for control gprs */ + u8 line; /* which input/output line is the gpr attached, only valid for input/output gprs */ + u8 usage; }; enum { - GPR_TYPE_NULL = 0, - GPR_TYPE_IO, - GPR_TYPE_STATIC, - GPR_TYPE_DYNAMIC, - GPR_TYPE_CONTROL, - GPR_TYPE_CONSTANT + GPR_TYPE_NULL = 0, + GPR_TYPE_IO, + GPR_TYPE_STATIC, + GPR_TYPE_DYNAMIC, + GPR_TYPE_CONTROL, + GPR_TYPE_CONSTANT }; #define GPR_BASE 0x100 @@ -101,15 +101,14 @@ #define MAX_PATCHES_PAGES 32 struct patch_manager { - void *patch[MAX_PATCHES_PAGES]; + void *patch[MAX_PATCHES_PAGES]; int current_pages; - struct dsp_rpatch rpatch; - struct dsp_gpr gpr[NUM_GPRS]; /* gpr usage table */ + struct dsp_rpatch rpatch; + struct dsp_gpr gpr[NUM_GPRS]; /* gpr usage table */ spinlock_t lock; s16 ctrl_gpr[SOUND_MIXER_NRDEVICES][2]; }; - #define PATCHES_PER_PAGE (PAGE_SIZE / sizeof(struct dsp_patch)) #define PATCH(mgr, i) ((struct dsp_patch *) (mgr)->patch[(i) / PATCHES_PER_PAGE] + (i) % PATCHES_PER_PAGE) diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/hwaccess.c linux-2.5.65-bk3/sound/oss/emu10k1/hwaccess.c --- linux-2.5.65-bk2/sound/oss/emu10k1/hwaccess.c Mon Mar 17 13:43:50 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/hwaccess.c Mon Mar 31 12:41:50 2003 @@ -187,6 +187,15 @@ } } +void emu10k1_timer_set(struct emu10k1_card * card, u16 data) +{ + unsigned long flags; + + spin_lock_irqsave(&card->lock, flags); + outw(data & TIMER_RATE_MASK, card->iobase + TIMER); + spin_unlock_irqrestore(&card->lock, flags); +} + /************************************************************************ * write/read Emu10k1 pointer-offset register set, accessed through * * the PTR and DATA registers * diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/hwaccess.h linux-2.5.65-bk3/sound/oss/emu10k1/hwaccess.h --- linux-2.5.65-bk2/sound/oss/emu10k1/hwaccess.h Mon Mar 17 13:44:03 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/hwaccess.h Mon Mar 31 12:41:50 2003 @@ -126,6 +126,7 @@ #define CMD_SETMCH_FX _IOW('D', 17, struct mixer_private_ioctl) #define CMD_SETPASSTHROUGH _IOW('D', 18, struct mixer_private_ioctl) #define CMD_PRIVATE3_VERSION _IOW('D', 19, struct mixer_private_ioctl) +#define CMD_AC97_BOOST _IOW('D', 20, struct mixer_private_ioctl) //up this number when breaking compatibility #define PRIVATE3_VERSION 1 @@ -144,7 +145,7 @@ u16 emupagetable[MAXPAGES]; struct list_head timers; - unsigned timer_delay; + u16 timer_delay; spinlock_t timer_lock; struct pci_dev *pci_dev; @@ -181,7 +182,7 @@ u8 chiprev; /* Chip revision */ - int isaps; + u8 is_aps; struct patch_manager mgr; struct pt_data pt; @@ -190,8 +191,6 @@ int emu10k1_addxmgr_alloc(u32, struct emu10k1_card *); void emu10k1_addxmgr_free(struct emu10k1_card *, int); - - int emu10k1_find_control_gpr(struct patch_manager *, const char *, const char *); void emu10k1_set_control_gpr(struct emu10k1_card *, int , s32, int ); @@ -211,12 +210,14 @@ /* Hardware Abstraction Layer access functions */ -void emu10k1_writefn0(struct emu10k1_card *, u32 , u32 ); -u32 emu10k1_readfn0(struct emu10k1_card *, u32 ); +void emu10k1_writefn0(struct emu10k1_card *, u32, u32); +u32 emu10k1_readfn0(struct emu10k1_card *, u32); + +void emu10k1_timer_set(struct emu10k1_card *, u16); -void sblive_writeptr(struct emu10k1_card *, u32 , u32 , u32 ); -void sblive_writeptr_tag(struct emu10k1_card *card, u32 channel, ...); -#define TAGLIST_END 0 +void sblive_writeptr(struct emu10k1_card *, u32, u32, u32); +void sblive_writeptr_tag(struct emu10k1_card *, u32, ...); +#define TAGLIST_END 0 u32 sblive_readptr(struct emu10k1_card *, u32 , u32 ); diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/irqmgr.c linux-2.5.65-bk3/sound/oss/emu10k1/irqmgr.c --- linux-2.5.65-bk2/sound/oss/emu10k1/irqmgr.c Mon Mar 17 13:44:07 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/irqmgr.c Mon Mar 31 12:41:50 2003 @@ -1,4 +1,3 @@ - /* ********************************************************************** * irqmgr.c - IRQ manager for emu10k1 driver @@ -41,7 +40,7 @@ void emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct emu10k1_card *card = (struct emu10k1_card *) dev_id; - u32 irqstatus; + u32 irqstatus, irqstatus_tmp; DPD(4, "emu10k1_interrupt called, irq = %u\n", irq); @@ -60,8 +59,7 @@ while ((irqstatus = inl(card->iobase + IPR))) { DPD(4, "irq status %#x\n", irqstatus); - /* acknowledge interrupt */ - outl(irqstatus, card->iobase + IPR); + irqstatus_tmp = irqstatus; if (irqstatus & IRQTYPE_TIMER) { emu10k1_timer_irqhandler(card); @@ -98,7 +96,15 @@ irqstatus &=~IPR_VOLDECR; } - if (irqstatus) - emu10k1_irq_disable(card, irqstatus); + if (irqstatus){ + printk(KERN_ERR "emu10k1: Warning, unhandled interrupt: %#08x\n", irqstatus); + //make sure any interrupts we don't handle are disabled: + emu10k1_irq_disable(card, ~(INTE_MIDIRXENABLE | INTE_MIDITXENABLE | INTE_INTERVALTIMERENB | + INTE_VOLDECRENABLE | INTE_VOLINCRENABLE | INTE_MUTEENABLE | + INTE_FXDSPENABLE)); + } + + /* acknowledge interrupt */ + outl(irqstatus_tmp, card->iobase + IPR); } } diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/main.c linux-2.5.65-bk3/sound/oss/emu10k1/main.c --- linux-2.5.65-bk2/sound/oss/emu10k1/main.c Mon Mar 17 13:44:48 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/main.c Mon Mar 31 12:41:50 2003 @@ -1,4 +1,4 @@ -/* + /* ********************************************************************** * main.c - Creative EMU10K1 audio driver * Copyright 1999, 2000 Creative Labs, Inc. @@ -69,7 +69,20 @@ * 0.16 Mixer improvements, added old treble/bass support (Daniel Bertrand) * Small code format cleanup. * Deadlock bug fix for emu10k1_volxxx_irqhandler(). - * + * 0.17 Fix for mixer SOUND_MIXER_INFO ioctl. + * Fix for HIGHMEM machines (emu10k1 can only do 31 bit bus master) + * midi poll initial implementation. + * Small mixer fixes/cleanups. + * Improved support for 5.1 cards. + * 0.18 Fix for possible leak in pci_alloc_consistent() + * Cleaned up poll() functions (audio and midi). Don't start input. + * Restrict DMA pages used to 512Mib range. + * New AC97_BOOST mixer ioctl. + * 0.19 Real fix for kernel with highmem support (cast dma_handle to u32). + * Fix recording buffering parameters calculation. + * Use unsigned long for variables in bit ops. + * 0.20 Fixed recording startup + * Fixed timer rate setting (it's a 16-bit register) *********************************************************************/ /* These are only included once per module */ @@ -102,11 +115,10 @@ #define SNDCARD_EMU10K1 46 #endif -#define DRIVER_VERSION "0.16" +#define DRIVER_VERSION "0.20" -/* FIXME: is this right? */ -/* does the card support 32 bit bus master?*/ -#define EMU10K1_DMA_MASK 0xffffffff /* DMA buffer mask for pci_alloc_consist */ +/* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */ +#define EMU10K1_DMA_MASK 0x1fffffff /* DMA buffer mask for pci_alloc_consist */ #ifndef PCI_VENDOR_ID_CREATIVE #define PCI_VENDOR_ID_CREATIVE 0x1102 @@ -188,7 +200,7 @@ /* Assign default recording parameters */ /* FIXME */ - if(card->isaps) + if (card->is_aps) card->wavein.recsrc = WAVERECORD_FX; else card->wavein.recsrc = WAVERECORD_AC97; @@ -211,6 +223,8 @@ static int __devinit emu10k1_mixer_init(struct emu10k1_card *card) { char s[32]; + + struct ac97_codec *codec = &card->ac97; card->ac97.dev_mixer = register_sound_mixer(&emu10k1_mixer_fops, -1); if (card->ac97.dev_mixer < 0) { printk(KERN_ERR "emu10k1: cannot register mixer device\n"); @@ -219,7 +233,7 @@ card->ac97.private_data = card; - if (!card->isaps) { + if (!card->is_aps) { card->ac97.id = 0; card->ac97.codec_read = emu10k1_ac97_read; card->ac97.codec_write = emu10k1_ac97_write; @@ -228,11 +242,14 @@ printk(KERN_ERR "emu10k1: unable to probe AC97 codec\n"); goto err_out; } - /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version - does not support this, it shouldn't do any harm */ - sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE); + /* 5.1: Enable the additional AC97 Slots and unmute extra channels on AC97 codec */ + if (codec->codec_read(codec, AC97_EXTENDED_ID) & 0x0080){ + printk(KERN_INFO "emu10k1: SBLive! 5.1 card detected\n"); + sblive_writeptr(card, AC97SLOT, 0, AC97SLOT_CNTR | AC97SLOT_LFE); + codec->codec_write(codec, AC97_SURROUND_MASTER, 0x0); + } - // Force 5bit + // Force 5bit: //card->ac97.bit_resolution=5; if (!proc_mkdir ("driver/emu10k1", 0)) { @@ -274,7 +291,7 @@ { char s[32]; - if (!card->isaps) { + if (!card->is_aps) { sprintf(s, "driver/emu10k1/%s/ac97", card->pci_dev->slot_name); remove_proc_entry(s, NULL); @@ -586,15 +603,15 @@ CONNECT(PCM1_IN_R, ANALOG_REAR_R); /* Digital In + PCM + AC97 In + MULTI_FRONT --> Digital out */ - OP(6, 0x10b, 0x100, 0x102, 0x10c); - OP(6, 0x10b, 0x10b, 0x113, 0x40); + OP(6, 0x10a, 0x100, 0x102, 0x10c); + OP(6, 0x10a, 0x10a, 0x113, 0x40); CONNECT(MULTI_FRONT_L, DIGITAL_OUT_L); CONNECT(PCM_IN_L, DIGITAL_OUT_L); CONNECT(AC97_IN_L, DIGITAL_OUT_L); CONNECT(SPDIF_CD_L, DIGITAL_OUT_L); - OP(6, 0x10a, 0x101, 0x103, 0x10e); + OP(6, 0x10b, 0x101, 0x103, 0x10e); OP(6, 0x10b, 0x10b, 0x114, 0x40); CONNECT(MULTI_FRONT_R, DIGITAL_OUT_R); @@ -768,7 +785,7 @@ VTFT, 0xffff, CVCF, 0xffff, PTRX, 0, - CPF, 0, + //CPF, 0, CCR, 0, PSST, 0, @@ -794,7 +811,9 @@ ENVVOL, 0, ENVVAL, 0, TAGLIST_END); + sblive_writeptr(card, CPF, nCh, 0); } + /* ** Init to 0x02109204 : @@ -852,19 +871,19 @@ } for (pagecount = 0; pagecount < MAXPAGES; pagecount++) - ((u32 *) card->virtualpagetable.addr)[pagecount] = cpu_to_le32((card->silentpage.dma_handle * 2) | pagecount); + ((u32 *) card->virtualpagetable.addr)[pagecount] = cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pagecount); /* Init page table & tank memory base register */ sblive_writeptr_tag(card, 0, - PTB, card->virtualpagetable.dma_handle, + PTB, (u32) card->virtualpagetable.dma_handle, TCB, 0, TCBS, 0, TAGLIST_END); for (nCh = 0; nCh < NUM_G; nCh++) { sblive_writeptr_tag(card, nCh, - MAPA, MAP_PTI_MASK | (card->silentpage.dma_handle * 2), - MAPB, MAP_PTI_MASK | (card->silentpage.dma_handle * 2), + MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2), + MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2), TAGLIST_END); } @@ -951,8 +970,9 @@ VTFT, 0, CVCF, 0, PTRX, 0, - CPF, 0, + //CPF, 0, TAGLIST_END); + sblive_writeptr(card, CPF, ch, 0); } /* Disable audio and lock cache */ @@ -999,7 +1019,7 @@ int ret; if (pci_set_dma_mask(pci_dev, EMU10K1_DMA_MASK)) { - printk(KERN_ERR "emu10k1: architecture does not support 32bit PCI busmaster DMA\n"); + printk(KERN_ERR "emu10k1: architecture does not support 29bit PCI busmaster DMA\n"); return -ENODEV; } @@ -1038,12 +1058,12 @@ pci_read_config_byte(pci_dev, PCI_REVISION_ID, &card->chiprev); pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &card->model); - printk(KERN_INFO "emu10k1: %s rev %d model 0x%x found, IO at 0x%04lx-0x%04lx, IRQ %d\n", + printk(KERN_INFO "emu10k1: %s rev %d model %#04x found, IO at %#04lx-%#04lx, IRQ %d\n", card_names[pci_id->driver_data], card->chiprev, card->model, card->iobase, card->iobase + card->length - 1, card->irq); pci_read_config_dword(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid); - card->isaps = (subsysvid == EMU_APS_SUBID); + card->is_aps = (subsysvid == EMU_APS_SUBID); spin_lock_init(&card->lock); init_MUTEX(&card->open_sem); @@ -1074,7 +1094,7 @@ goto err_emu10k1_init; } - if (card->isaps) + if (card->is_aps) emu10k1_ecard_init(card); list_add(&card->list, &emu10k1_devs); @@ -1119,7 +1139,7 @@ pci_set_drvdata(pci_dev, NULL); } -MODULE_AUTHOR("Bertrand Lee, Cai Ying. (Email to: emu10k1-devel@opensource.creative.com)"); +MODULE_AUTHOR("Bertrand Lee, Cai Ying. (Email to: emu10k1-devel@lists.sourceforge.net)"); MODULE_DESCRIPTION("Creative EMU10K1 PCI Audio Driver v" DRIVER_VERSION "\nCopyright (C) 1999 Creative Technology Ltd."); MODULE_LICENSE("GPL"); diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/midi.c linux-2.5.65-bk3/sound/oss/emu10k1/midi.c --- linux-2.5.65-bk2/sound/oss/emu10k1/midi.c Mon Mar 17 13:44:51 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/midi.c Mon Mar 31 12:41:50 2003 @@ -29,8 +29,8 @@ ********************************************************************** */ -#define __NO_VERSION__ #include +#include #include #include #include @@ -371,8 +371,32 @@ static unsigned int emu10k1_midi_poll(struct file *file, struct poll_table_struct *wait) { + struct emu10k1_mididevice *midi_dev = (struct emu10k1_mididevice *) file->private_data; + unsigned long flags; + unsigned int mask = 0; + DPF(4, "emu10k1_midi_poll() called\n"); - return 0; + + if (file->f_mode & FMODE_WRITE) + poll_wait(file, &midi_dev->oWait, wait); + + if (file->f_mode & FMODE_READ) + poll_wait(file, &midi_dev->iWait, wait); + + spin_lock_irqsave(&midi_spinlock, flags); + + if (file->f_mode & FMODE_WRITE) + mask |= POLLOUT | POLLWRNORM; + + if (file->f_mode & FMODE_READ) { + if (midi_dev->mistate == MIDIIN_STATE_STARTED) + if (midi_dev->icnt > 0) + mask |= POLLIN | POLLRDNORM; + } + + spin_unlock_irqrestore(&midi_spinlock, flags); + + return mask; } int emu10k1_midi_callback(unsigned long msg, unsigned long refdata, unsigned long *pmsg) diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/mixer.c linux-2.5.65-bk3/sound/oss/emu10k1/mixer.c --- linux-2.5.65-bk2/sound/oss/emu10k1/mixer.c Mon Mar 17 13:44:21 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/mixer.c Mon Mar 31 12:41:50 2003 @@ -30,7 +30,6 @@ ********************************************************************** */ -#define __NO_VERSION__ /* Kernel version only defined once */ #include #include #include @@ -251,7 +250,7 @@ case CMD_SETRECSRC: switch (ctl->val[0]) { case WAVERECORD_AC97: - if (card->isaps) { + if (card->is_aps) { ret = -EINVAL; break; } @@ -444,6 +443,7 @@ case CMD_SETGPR2OSS: id = ctl->val[0]; + /* 0 == left, 1 == right */ ch = ctl->val[1]; addr = ctl->val[2]; @@ -454,19 +454,19 @@ card->mgr.ctrl_gpr[id][ch] = addr; - if (card->isaps) + if (card->is_aps) break; if (addr >= 0) { unsigned int state = card->ac97.mixer_state[id]; - if (ch) { + if (ch == 1) { state >>= 8; card->ac97.stereo_mixers |= (1 << id); - } else { - card->ac97.supported_mixers |= (1 << id); } + card->ac97.supported_mixers |= (1 << id); + if (id == SOUND_MIXER_TREBLE) { set_treble(card, card->ac97.mixer_state[id] & 0xff, (card->ac97.mixer_state[id] >> 8) & 0xff); } else if (id == SOUND_MIXER_BASS) { @@ -475,10 +475,10 @@ emu10k1_set_volume_gpr(card, addr, state & 0xff, volume_params[id]); } else { - if (ch) { - card->ac97.stereo_mixers &= ~(1 << id); - card->ac97.stereo_mixers |= card->ac97_stereo_mixers; - } else { + card->ac97.stereo_mixers &= ~(1 << id); + card->ac97.stereo_mixers |= card->ac97_stereo_mixers; + + if (ch == 0) { card->ac97.supported_mixers &= ~(1 << id); card->ac97.supported_mixers |= card->ac97_supported_mixers; } @@ -499,6 +499,12 @@ ret = -EFAULT; break; + case CMD_AC97_BOOST: + if(ctl->val[0]) + emu10k1_ac97_write(&card->ac97, 0x18, 0x0); + else + emu10k1_ac97_write(&card->ac97, 0x18, 0x0808); + break; default: ret = -EINVAL; break; @@ -551,7 +557,7 @@ card->tankmem.size = size; - sblive_writeptr_tag(card, 0, TCB, card->tankmem.dma_handle, TCBS, size_reg, TAGLIST_END); + sblive_writeptr_tag(card, 0, TCB, (u32) card->tankmem.dma_handle, TCBS, size_reg, TAGLIST_END); emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 0); } @@ -572,6 +578,8 @@ int val; int scale; + card->ac97.modcnt++; + if (get_user(val, (int *)arg)) return -EFAULT; @@ -612,7 +620,7 @@ unsigned int oss_mixer = _IOC_NR(cmd); ret = -EINVAL; - if (!card->isaps) { + if (!card->is_aps) { if (cmd == SOUND_MIXER_INFO) { mixer_info info; @@ -626,7 +634,7 @@ return 0; } - if ((_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES) + if ((_SIOC_DIR(cmd) == (_SIOC_WRITE|_SIOC_READ)) && oss_mixer <= SOUND_MIXER_NRDEVICES) ret = emu10k1_dsp_mixer(card, oss_mixer, arg); else ret = card->ac97.mixer_ioctl(&card->ac97, cmd, arg); diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/passthrough.c linux-2.5.65-bk3/sound/oss/emu10k1/passthrough.c --- linux-2.5.65-bk2/sound/oss/emu10k1/passthrough.c Mon Mar 17 13:44:05 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/passthrough.c Mon Mar 31 12:41:50 2003 @@ -29,7 +29,6 @@ ********************************************************************** */ -#define __NO_VERSION__ #include #include #include @@ -165,15 +164,12 @@ DPD(3, "prepend size %d, prepending %d bytes\n", pt->prepend_size, needed); if (count < needed) { - if (copy_from_user(pt->buf + pt->prepend_size, buffer, - count)) - return -EFAULT; + copy_from_user(pt->buf + pt->prepend_size, buffer, count); pt->prepend_size += count; DPD(3, "prepend size now %d\n", pt->prepend_size); return count; } - if (copy_from_user(pt->buf + pt->prepend_size, buffer, needed)) - return -EFAULT; + copy_from_user(pt->buf + pt->prepend_size, buffer, needed); r = pt_putblock(wave_dev, (u16 *) pt->buf, nonblock); if (r) return r; @@ -184,8 +180,7 @@ blocks_copied = 0; while (blocks > 0) { u16 *bufptr = (u16 *) buffer + (bytes_copied/2); - if (copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE)) - return -EFAULT; + copy_from_user(pt->buf, bufptr, PT_BLOCKSIZE); bufptr = (u16 *) pt->buf; r = pt_putblock(wave_dev, bufptr, nonblock); if (r) { @@ -201,8 +196,7 @@ i = count - bytes_copied; if (i) { pt->prepend_size = i; - if (copy_from_user(pt->buf, buffer + bytes_copied, i)) - return -EFAULT; + copy_from_user(pt->buf, buffer + bytes_copied, i); bytes_copied += i; DPD(3, "filling prepend buffer with %d bytes", i); } diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/recmgr.c linux-2.5.65-bk3/sound/oss/emu10k1/recmgr.c --- linux-2.5.65-bk2/sound/oss/emu10k1/recmgr.c Mon Mar 17 13:44:51 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/recmgr.c Mon Mar 31 12:41:50 2003 @@ -29,19 +29,28 @@ ********************************************************************** */ +#include #include "8010.h" #include "recmgr.h" +void emu10k1_reset_record(struct emu10k1_card *card, struct wavein_buffer *buffer) +{ + DPF(2, "emu10k1_reset_record()\n"); + + sblive_writeptr(card, buffer->sizereg, 0, ADCBS_BUFSIZE_NONE); + + sblive_writeptr(card, buffer->sizereg, 0, buffer->sizeregval); + + while (sblive_readptr(card, buffer->idxreg, 0)) + udelay(5); +} + void emu10k1_start_record(struct emu10k1_card *card, struct wavein_buffer *buffer) { DPF(2, "emu10k1_start_record()\n"); - sblive_writeptr(card, buffer->sizereg, 0, buffer->sizeregval); - if (buffer->adcctl) sblive_writeptr(card, ADCCR, 0, buffer->adcctl); - - return; } void emu10k1_stop_record(struct emu10k1_card *card, struct wavein_buffer *buffer) @@ -51,10 +60,6 @@ /* Disable record transfer */ if (buffer->adcctl) sblive_writeptr(card, ADCCR, 0, 0); - - sblive_writeptr(card, buffer->sizereg, 0, ADCBS_BUFSIZE_NONE); - - return; } void emu10k1_set_record_src(struct emu10k1_card *card, struct wiinst *wiinst) @@ -130,9 +135,7 @@ break; } - DPD(2, "bus addx: %#x\n", buffer->dma_handle); - - sblive_writeptr(card, buffer->addrreg, 0, buffer->dma_handle); + DPD(2, "bus addx: %#lx\n", (unsigned long) buffer->dma_handle); - return; + sblive_writeptr(card, buffer->addrreg, 0, (u32)buffer->dma_handle); } diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/recmgr.h linux-2.5.65-bk3/sound/oss/emu10k1/recmgr.h --- linux-2.5.65-bk2/sound/oss/emu10k1/recmgr.h Mon Mar 17 13:44:47 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/recmgr.h Mon Mar 31 12:41:50 2003 @@ -40,9 +40,9 @@ #define WAVERECORD_MIC 0x02 #define WAVERECORD_FX 0x03 +void emu10k1_reset_record(struct emu10k1_card *card, struct wavein_buffer *buffer); void emu10k1_start_record(struct emu10k1_card *, struct wavein_buffer *); void emu10k1_stop_record(struct emu10k1_card *, struct wavein_buffer *); void emu10k1_set_record_src(struct emu10k1_card *, struct wiinst *wiinst); - #endif /* _RECORDMGR_H */ diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/timer.c linux-2.5.65-bk3/sound/oss/emu10k1/timer.c --- linux-2.5.65-bk2/sound/oss/emu10k1/timer.c Mon Mar 17 13:43:45 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/timer.c Mon Mar 31 12:41:50 2003 @@ -59,7 +59,7 @@ return; } -void emu10k1_timer_install(struct emu10k1_card *card, struct emu_timer *timer, u32 delay) +void emu10k1_timer_install(struct emu10k1_card *card, struct emu_timer *timer, u16 delay) { struct emu_timer *t; struct list_head *entry; @@ -85,7 +85,7 @@ card->timer_delay = delay; delay = (delay < 1024 ? delay : 1024); - emu10k1_writefn0(card, TIMER_RATE, delay); + emu10k1_timer_set(card, delay); list_for_each(entry, &card->timers) { t = list_entry(entry, struct emu_timer, list); @@ -108,7 +108,7 @@ { struct emu_timer *t; struct list_head *entry; - u32 delay = TIMER_STOPPED; + u16 delay = TIMER_STOPPED; unsigned long flags; if (timer->state == TIMER_STATE_UNINSTALLED) @@ -133,7 +133,7 @@ else { delay = (delay < 1024 ? delay : 1024); - emu10k1_writefn0(card, TIMER_RATE, delay); + emu10k1_timer_set(card, delay); list_for_each(entry, &card->timers) { t = list_entry(entry, struct emu_timer, list); diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/timer.h linux-2.5.65-bk3/sound/oss/emu10k1/timer.h --- linux-2.5.65-bk2/sound/oss/emu10k1/timer.h Mon Mar 17 13:43:39 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/timer.h Mon Mar 31 12:41:50 2003 @@ -36,17 +36,17 @@ struct list_head list; struct tasklet_struct tasklet; u8 state; - u32 count; /* current number of interrupts */ - u32 count_max; /* number of interrupts needed to schedule the bh */ - u32 delay; /* timer delay */ + u16 count; /* current number of interrupts */ + u16 count_max; /* number of interrupts needed to schedule the bh */ + u16 delay; /* timer delay */ }; -void emu10k1_timer_install(struct emu10k1_card *, struct emu_timer *, u32); +void emu10k1_timer_install(struct emu10k1_card *, struct emu_timer *, u16); void emu10k1_timer_uninstall(struct emu10k1_card *, struct emu_timer *); void emu10k1_timer_enable(struct emu10k1_card *, struct emu_timer *); void emu10k1_timer_disable(struct emu10k1_card *, struct emu_timer *); -#define TIMER_STOPPED 0xffffffff +#define TIMER_STOPPED 0xffff #define TIMER_STATE_INSTALLED 0x01 #define TIMER_STATE_ACTIVE 0x02 #define TIMER_STATE_UNINSTALLED 0x04 diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/voicemgr.c linux-2.5.65-bk3/sound/oss/emu10k1/voicemgr.c --- linux-2.5.65-bk2/sound/oss/emu10k1/voicemgr.c Mon Mar 17 13:44:09 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/voicemgr.c Mon Mar 31 12:41:50 2003 @@ -32,6 +32,84 @@ #include "voicemgr.h" #include "8010.h" +/** + * emu10k1_voice_alloc_buffer - + * + * allocates the memory buffer for a voice. Two page tables are kept for each buffer. + * One (dma_handle) keeps track of the host memory pages used and the other (virtualpagetable) + * is passed to the device so that it can do DMA to host memory. + * + */ +int emu10k1_voice_alloc_buffer(struct emu10k1_card *card, struct voice_mem *mem, u32 pages) +{ + u32 pageindex, pagecount; + u32 busaddx; + int i; + + DPD(2, "requested pages is: %d\n", pages); + + if ((mem->emupageindex = emu10k1_addxmgr_alloc(pages * PAGE_SIZE, card)) < 0) + { + DPF(1, "couldn't allocate emu10k1 address space\n"); + return -1; + } + + /* Fill in virtual memory table */ + for (pagecount = 0; pagecount < pages; pagecount++) { + if ((mem->addr[pagecount] = pci_alloc_consistent(card->pci_dev, PAGE_SIZE, &mem->dma_handle[pagecount])) + == NULL) { + mem->pages = pagecount; + DPF(1, "couldn't allocate dma memory\n"); + return -1; + } + + DPD(2, "Virtual Addx: %p\n", mem->addr[pagecount]); + + for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) { + busaddx = (u32) mem->dma_handle[pagecount] + i * EMUPAGESIZE; + + DPD(3, "Bus Addx: %#x\n", busaddx); + + pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i; + + ((u32 *) card->virtualpagetable.addr)[pageindex] = cpu_to_le32((busaddx * 2) | pageindex); + } + } + + mem->pages = pagecount; + + return 0; +} + +/** + * emu10k1_voice_free_buffer - + * + * frees the memory buffer for a voice. + */ +void emu10k1_voice_free_buffer(struct emu10k1_card *card, struct voice_mem *mem) +{ + u32 pagecount, pageindex; + int i; + + if (mem->emupageindex < 0) + return; + + for (pagecount = 0; pagecount < mem->pages; pagecount++) { + pci_free_consistent(card->pci_dev, PAGE_SIZE, + mem->addr[pagecount], + mem->dma_handle[pagecount]); + + for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) { + pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i; + ((u32 *) card->virtualpagetable.addr)[pageindex] = + cpu_to_le32(((u32) card->silentpage.dma_handle * 2) | pageindex); + } + } + + emu10k1_addxmgr_free(card, mem->emupageindex); + mem->emupageindex = -1; +} + int emu10k1_voice_alloc(struct emu10k1_card *card, struct emu_voice *voice) { u8 *voicetable = card->voicetable; @@ -96,8 +174,10 @@ VTFT, 0x0000ffff, PTRX_PITCHTARGET, 0, CVCF, 0x0000ffff, - CPF, 0, + //CPF, 0, TAGLIST_END); + + sblive_writeptr(card, CPF, voice->num + i, 0); } voice->usage = VOICE_USAGE_FREE; @@ -151,8 +231,8 @@ Z1, 0, Z2, 0, /* Invalidate maps */ - MAPA, MAP_PTI_MASK | (card->silentpage.dma_handle * 2), - MAPB, MAP_PTI_MASK | (card->silentpage.dma_handle * 2), + MAPA, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2), + MAPB, MAP_PTI_MASK | ((u32) card->silentpage.dma_handle * 2), /* modulation envelope */ CVCF, 0x0000ffff, VTFT, 0x0000ffff, diff -urN linux-2.5.65-bk2/sound/oss/emu10k1/voicemgr.h linux-2.5.65-bk3/sound/oss/emu10k1/voicemgr.h --- linux-2.5.65-bk2/sound/oss/emu10k1/voicemgr.h Mon Mar 17 13:44:09 2003 +++ linux-2.5.65-bk3/sound/oss/emu10k1/voicemgr.h Mon Mar 31 12:41:50 2003 @@ -64,6 +64,12 @@ u32 byampl_env_decay; }; +struct voice_mem { + int emupageindex; + void *addr[BUFMAXPAGES]; + dma_addr_t dma_handle[BUFMAXPAGES]; + u32 pages; +}; struct emu_voice { @@ -72,16 +78,20 @@ u8 num; /* Voice ID */ u8 flags; /* Stereo/mono, 8/16 bit */ - u32 startloop; - u32 endloop; + u32 startloop; + u32 endloop; u32 start; u32 initial_pitch; u32 pitch_target; struct voice_param params[2]; + + struct voice_mem mem; }; +int emu10k1_voice_alloc_buffer(struct emu10k1_card *, struct voice_mem *, u32); +void emu10k1_voice_free_buffer(struct emu10k1_card *, struct voice_mem *); int emu10k1_voice_alloc(struct emu10k1_card *, struct emu_voice *); void emu10k1_voice_free(struct emu_voice *); void emu10k1_voice_playback_setup(struct emu_voice *); diff -urN linux-2.5.65-bk2/sound/oss/i810_audio.c linux-2.5.65-bk3/sound/oss/i810_audio.c --- linux-2.5.65-bk2/sound/oss/i810_audio.c Mon Mar 17 13:44:38 2003 +++ linux-2.5.65-bk3/sound/oss/i810_audio.c Mon Mar 31 12:41:50 2003 @@ -2406,9 +2406,9 @@ i810_set_dac_channels ( state, channels ); /* check that they really got turned on */ - if ( !state->card->ac97_status & SURR_ON ) + if (!(state->card->ac97_status & SURR_ON)) val &= ~DSP_BIND_SURR; - if ( !state->card->ac97_status & CENTER_LFE_ON ) + if (!(state->card->ac97_status & CENTER_LFE_ON)) val &= ~DSP_BIND_CENTER_LFE; } } diff -urN linux-2.5.65-bk2/sound/oss/maestro.c linux-2.5.65-bk3/sound/oss/maestro.c --- linux-2.5.65-bk2/sound/oss/maestro.c Mon Mar 17 13:44:43 2003 +++ linux-2.5.65-bk3/sound/oss/maestro.c Mon Mar 31 12:41:50 2003 @@ -3367,7 +3367,7 @@ /* check to see if we have a capabilities list in the config register */ pci_read_config_word(pcidev, PCI_STATUS, &w); - if(! w & PCI_STATUS_CAP_LIST) return 0; + if(!(w & PCI_STATUS_CAP_LIST)) return 0; /* walk the list, starting at the head. */ pci_read_config_byte(pcidev,PCI_CAPABILITY_LIST,&next); diff -urN linux-2.5.65-bk2/sound/oss/midi_syms.c linux-2.5.65-bk3/sound/oss/midi_syms.c --- linux-2.5.65-bk2/sound/oss/midi_syms.c Mon Mar 17 13:43:42 2003 +++ linux-2.5.65-bk3/sound/oss/midi_syms.c Mon Mar 31 12:41:50 2003 @@ -1,9 +1,7 @@ /* * Exported symbols for midi driver. - * __NO_VERSION__ because this is still part of sound.o. */ -#define __NO_VERSION__ #include char midi_syms_symbol; diff -urN linux-2.5.65-bk2/sound/oss/mpu401.c linux-2.5.65-bk3/sound/oss/mpu401.c --- linux-2.5.65-bk2/sound/oss/mpu401.c Mon Mar 17 13:44:44 2003 +++ linux-2.5.65-bk3/sound/oss/mpu401.c Mon Mar 31 12:41:50 2003 @@ -1762,13 +1762,13 @@ static struct address_info cfg; -static int __initdata io = -1; -static int __initdata irq = -1; +static int io = -1; +static int irq = -1; MODULE_PARM(irq, "i"); MODULE_PARM(io, "i"); -int __init init_mpu401(void) +static int __init init_mpu401(void) { int ret; /* Can be loaded either for module use or to provide functions @@ -1785,7 +1785,7 @@ return 0; } -void __exit cleanup_mpu401(void) +static void __exit cleanup_mpu401(void) { if (io != -1 && irq != -1) { /* Check for use by, for example, sscape driver */ diff -urN linux-2.5.65-bk2/sound/oss/nm256_audio.c linux-2.5.65-bk3/sound/oss/nm256_audio.c --- linux-2.5.65-bk2/sound/oss/nm256_audio.c Mon Mar 17 13:44:05 2003 +++ linux-2.5.65-bk3/sound/oss/nm256_audio.c Mon Mar 31 12:41:50 2003 @@ -19,7 +19,6 @@ * Ported to 2.4 PCI API. */ -#define __NO_VERSION__ #include #include #include diff -urN linux-2.5.65-bk2/sound/oss/sequencer_syms.c linux-2.5.65-bk3/sound/oss/sequencer_syms.c --- linux-2.5.65-bk2/sound/oss/sequencer_syms.c Mon Mar 17 13:44:01 2003 +++ linux-2.5.65-bk3/sound/oss/sequencer_syms.c Mon Mar 31 12:41:50 2003 @@ -1,9 +1,7 @@ /* * Exported symbols for sequencer driver. - * __NO_VERSION__ because this is still part of sound.o. */ -#define __NO_VERSION__ #include char sequencer_syms_symbol; diff -urN linux-2.5.65-bk2/sound/pci/ac97/ac97_codec.c linux-2.5.65-bk3/sound/pci/ac97/ac97_codec.c --- linux-2.5.65-bk2/sound/pci/ac97/ac97_codec.c Mon Mar 31 12:41:37 2003 +++ linux-2.5.65-bk3/sound/pci/ac97/ac97_codec.c Mon Mar 31 12:41:50 2003 @@ -1870,7 +1870,7 @@ */ static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem) { - signed long end_time; + unsigned long end_time; end_time = jiffies + timeout; do { unsigned short ext_mid; @@ -1930,7 +1930,7 @@ int err; ac97_t *ac97; char name[64]; - signed long end_time; + unsigned long end_time; static snd_device_ops_t ops = { .dev_free = snd_ac97_dev_free, }; @@ -2083,7 +2083,7 @@ */ static int ac97_modem_reset_wait(ac97_t *ac97, int timeout) { - signed long end_time; + unsigned long end_time; end_time = jiffies + timeout; do { unsigned short ext_mid; diff -urN linux-2.5.65-bk2/sound/pci/intel8x0.c linux-2.5.65-bk3/sound/pci/intel8x0.c --- linux-2.5.65-bk2/sound/pci/intel8x0.c Mon Mar 31 12:41:37 2003 +++ linux-2.5.65-bk3/sound/pci/intel8x0.c Mon Mar 31 12:41:51 2003 @@ -1778,7 +1778,7 @@ static int snd_intel8x0_ich_chip_init(intel8x0_t *chip) { - signed long end_time; + unsigned long end_time; unsigned int cnt, status, nstatus; /* put logic to right state */